К основному содержанию
скилл CX Codex

nuxt-server — скилл для Claude Code: серверный Nuxt 4 на Nitro

Скилл для серверной разработки на Nuxt 4 с Nitro: API-роуты, middleware, базы данных и WebSocket. Пригодится, когда бэкенд живёт внутри Nuxt-проекта.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add secondsky/claude-skills --skill nuxt-server -a claude-code
Открыть на GitHub

Что делает nuxt-server

Скилл описывает файловую структуру серверной части Nuxt 4: server/api/ для эндпоинтов, server/routes/ для не-API маршрутов, server/middleware/ для middleware, server/plugins/ для Nitro-плагинов и server/utils/ для хелперов. HTTP-метод задаётся суффиксом файла: .get.ts, .post.ts, .put.ts, .patch.ts, .delete.ts, а .ts без суффикса ловит все методы.

Внутри — примеры на defineEventHandler: чтение параметров через getRouterParam и getQuery, тела запроса через readBody, заголовков через getHeader. Ответ формируется через setResponseStatus, sendRedirect, ошибки — через createError. Отдельные разделы про cookies (getCookie, setCookie, deleteCookie) и про middleware, которое кладёт пользователя в event.context.user.

Для баз данных есть связка Cloudflare D1 с Drizzle: drizzle-orm/d1, схема в server/database/schema.ts на sqliteTable. Подключение к PostgreSQL и паттерны запросов лежат в отдельных справочниках, которые скилл подгружает по необходимости. Учтите: примеры завязаны на event.context.cloudflare.env, поэтому вне Cloudflare-окружения этот кусок придётся переписать под свой драйвер.

Какие задачи решает

  • создать API-роут с файловой маршрутизацией
  • прочитать параметры и тело запроса в обработчике
  • повесить middleware, которое проверяет токен на каждом запросе
  • подключить D1 к Nuxt через Drizzle
  • описать схему таблиц для Drizzle

Примеры запросов агенту

  • Сделай эндпоинт GET /api/users/[id] с проверкой id и ошибкой 400, если его нет
  • Добавь серверный middleware, которое пускает без токена только /api/auth/login и /api/health
  • Настрой подключение к D1 через Drizzle в server/utils/db.ts

Как установить nuxt-server

1Через Skills CLI (Vercel)

npx skills add secondsky/claude-skills --skill nuxt-server -a claude-code

2Вручную: положить файлы

~/.claude/skills/nuxt-server/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/nuxt-server/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Из того же набора89

session-management Скилл для ИИ-кодинга, который помогает собрать вход в аккаунт: JWT-токены, хранение сессий в Redis, обновление токена и настройка cookie. CX Codex +1 408установок bun-test-coverage Скилл для работы с покрытием тестов в Bun: флаг --coverage, отчёты lcov, пороги и запуск в CI. Пригодится, когда тесты уже есть, а процент покрытия надо видеть и держать. CX Codex +1 403установок bun-workers Скилл подсказывает агенту, как запускать Web Workers и worker_threads в Bun: параллельные задачи, пул воркеров, обмен сообщениями. CX Codex +1 402установок dependency-upgrade Помогает обновлять зависимости без риска: настраивает карантин для новых версий, блокирует postinstall-скрипты и ведёт обновления поэтапно. CX Codex +1 404установок bun-http-server Скилл подсказывает агенту, как поднять HTTP-сервер через Bun.serve(): маршруты, разбор тела запроса, ответы, CORS. CX Codex +1 400установок bun-cloudflare-workers Скилл для сборки и деплоя Cloudflare Workers на Bun: подсказывает структуру проекта, биндинги KV, D1, R2 и Durable Objects. CX Codex +1 402установок mobile-offline-support Скилл для офлайн-первого подхода в мобильных приложениях: локальное хранилище, очередь синхронизации, разрешение конфликтов. CX Codex +1 398установок api-versioning-strategy Помогает выбрать способ версионирования API и провести старую версию до отключения без сюрпризов для клиентов. CX Codex +1 399установок

Похожие

nuxt Anthony Fu Скилл добавляет поддержку Nuxt 5 — полнофункционального Vue-фреймворка с серверным рендерингом, файловой маршрутизацией и автоимпортами. Помогает агенту писать серверные маршруты, работать с useFetch, middleware и гибридным рендерингом. CX Codex +1 24 100установок clerk-nuxt-patterns clerk Скилл подсказывает агенту паттерны авторизации @clerk/nuxt для Nuxt 3. Пригодится при настройке серверных роутов Nitro, SSR-гидратации и защите страниц. CX Codex +1 13 900установок Expert Nuxt Developer официальный github Помогает разрабатывать приложения на Nuxt 3 и Nitro с типизацией на TypeScript. Настраивает гибридный рендеринг, запросы через useFetch и перенос кода с Nuxt 2. ★ 40 418звёзд репо nuxthub onmax Помогает настраивать NuxtHub v0.10.8 с базой данных на Drizzle ORM, KV-хранилищем и blob. Пригодится при сборке бэкенда Nuxt под Cloudflare, Vercel или локальный PGlite. CX Codex +1 2 200установок drizzle-migrations bobmatnyc Скилл задаёт порядок работы с базой в TypeScript: сначала SQL-миграция, потом схема. Пригодится, когда схема меняется в нескольких окружениях. CX Codex +1 1 300установок drizzle-best-practices Marc A. Maceira Zayas Скилл подсказывает агенту, как правильно писать схемы, запросы и связи в Drizzle ORM на PostgreSQL. Пригодится, когда проект на TypeScript и Postgres. CX Codex +1 685установок

Рядом в теме «Бэкенд и API»

Всё по теме «Бэкенд и API» →

Вопросы о nuxt-server

Как установить nuxt-server в Claude?

Выполните npx skills add secondsky/claude-skills --skill nuxt-server -a claude-code. Скилл появится в ~/.claude/skills/nuxt-server/SKILL.md.

Что делает nuxt-server?

Даёт агенту справочник по серверной части Nuxt 4 на Nitro: API-роуты, middleware, cookies, обработка ошибок, интеграция с D1 и PostgreSQL через Drizzle, WebSocket и загрузка файлов.

Нужен ли Cloudflare для работы скилла?

Нет, но пример с Drizzle для D1 берёт базу из event.context.cloudflare.env. В другом окружении этот код придётся адаптировать под свой драйвер.

Исходный текст

SKILL.md · MIT
---
name: nuxt-server
description: "| Nuxt 4 server-side development with Nitro: API routes, server middleware, database integration, and backend patterns. Use when: creating server API routes, implementing server middleware, integrating databases (D1, PostgreSQL, Drizzle), handling file uploads, implementing WebSockets, or building backend logic with Nitro."
license: MIT
metadata:
  version: 4.0.0
  author: Claude Skills Maintainers
  category: Framework
  framework: Nuxt
  framework-version: 4.x
  last-verified: 2025-12-28
  keywords:
    - server routes
    - API routes
    - Nitro
    - defineEventHandler
    - getRouterParam
    - getQuery
    - readBody
    - setCookie
    - createError
    - server middleware
    - D1
    - Drizzle
    - PostgreSQL
    - WebSocket
    - file upload
---
# Nuxt 4 Server Development

Server routes, API patterns, and backend development with Nitro.

## Quick Reference

### File-Based Server Routes

```
server/
├── api/                      # API endpoints (/api/*)
│   ├── users/
│   │   ├── index.get.ts      → GET  /api/users
│   │   ├── index.post.ts     → POST /api/users
│   │   ├── [id].get.ts       → GET  /api/users/:id
│   │   ├── [id].put.ts       → PUT  /api/users/:id
│   │   └── [id].delete.ts    → DELETE /api/users/:id
│   └── health.get.ts         → GET  /api/health
├── routes/                   # Non-API routes
│   └── sitemap.xml.get.ts    → GET  /sitemap.xml
├── middleware/               # Server middleware
│   └── auth.ts               # Runs on every request
├── plugins/                  # Nitro plugins
│   └── database.ts           # Initialize database
└── utils/                    # Server utilities
    └── db.ts                 # Database helpers
```

### HTTP Method Suffixes

| Suffix | HTTP Method |
|--------|-------------|
| `.get.ts` | GET |
| `.post.ts` | POST |
| `.put.ts` | PUT |
| `.patch.ts` | PATCH |
| `.delete.ts` | DELETE |
| `.ts` | All methods |

## When to Load References

**Load `references/server.md` when:**
- Implementing complex API routes
- Handling authentication and sessions
- Working with cookies and headers
- Building file upload endpoints
- Understanding Nitro internals

**Load `references/database-patterns.md` when:**
- Integrating Cloudflare D1 with Drizzle
- Setting up PostgreSQL connections
- Implementing database migrations
- Building query patterns

**Load `references/websocket-patterns.md` when:**
- Implementing real-time features
- Building WebSocket endpoints
- Using Durable Objects for state

## Basic Event Handler

```typescript
// server/api/users/index.get.ts
export default defineEventHandler(async (event) => {
  // Return data (automatically serialized to JSON)
  return {
    users: [
      { id: 1, name: 'John' },
      { id: 2, name: 'Jane' }
    ]
  }
})
```

## Request Utilities

### URL Parameters

```typescript
// server/api/users/[id].get.ts
export default defineEventHandler(async (event) => {
  const id = getRouterParam(event, 'id')

  if (!id) {
    throw createError({
      statusCode: 400,
      message: 'User ID is required'
    })
  }

  return { id }
})
```

### Query Parameters

```typescript
// GET /api/users?page=1&limit=10&search=john
export default defineEventHandler(async (event) => {
  const query = getQuery(event)

  const page = Number(query.page) || 1
  const limit = Number(query.limit) || 10
  const search = query.search as string | undefined

  return { page, limit, search }
})
```

### Request Body

```typescript
// server/api/users/index.post.ts
export default defineEventHandler(async (event) => {
  const body = await readBody(event)

  // Validate body
  if (!body.name || !body.email) {
    throw createError({
      statusCode: 400,
      message: 'Name and email are required'
    })
  }

  // Create user...
  return { success: true, user: { id: 1, ...body } }
})
```

### Headers

```typescript
export default defineEventHandler(async (event) => {
  // Read headers
  const authHeader = getHeader(event, 'authorization')
  const contentType = getHeader(event, 'content-type')

  // Set response headers
  setHeader(event, 'X-Custom-Header', 'value')
  setHeader(event, 'Cache-Control', 'max-age=3600')

  return { authHeader, contentType }
})
```

## Response Utilities

### Setting Status Code

```typescript
export default defineEventHandler(async (event) => {
  // Set status code
  setResponseStatus(event, 201)  // Created

  return { message: 'Resource created' }
})
```

### Redirects

```typescript
export default defineEventHandler(async (event) => {
  // Redirect
  return sendRedirect(event, '/new-location', 302)
})
```

### Error Handling

```typescript
export default defineEventHandler(async (event) => {
  const id = getRouterParam(event, 'id')

  const user = await findUser(id)

  if (!user) {
    throw createError({
      statusCode: 404,
      statusMessage: 'Not Found',
      message: `User with ID ${id} not found`
    })
  }

  return user
})
```

## Cookies

```typescript
export default defineEventHandler(async (event) => {
  // Read cookie
  const sessionId = getCookie(event, 'session_id')

  // Set cookie
  setCookie(event, 'session_id', 'abc123', {
    httpOnly: true,
    secure: true,
    sameSite: 'lax',
    maxAge: 60 * 60 * 24 * 7  // 1 week
  })

  // Delete cookie
  deleteCookie(event, 'old_cookie')

  return { sessionId }
})
```

## Server Middleware

```typescript
// server/middleware/auth.ts
export default defineEventHandler(async (event) => {
  // Skip for public routes
  const publicRoutes = ['/api/auth/login', '/api/health']
  if (publicRoutes.includes(event.path)) {
    return  // Continue to next handler
  }

  // Check authentication
  const token = getHeader(event, 'authorization')?.replace('Bearer ', '')

  if (!token) {
    throw createError({
      statusCode: 401,
      message: 'Authentication required'
    })
  }

  // Verify token and attach user to context
  const user = await verifyToken(token)
  event.context.user = user
})
```

### Accessing Context in Routes

```typescript
// server/api/profile.get.ts
export default defineEventHandler(async (event) => {
  // User attached by middleware
  const user = event.context.user

  if (!user) {
    throw createError({ statusCode: 401, message: 'Not authenticated' })
  }

  return { user }
})
```

## Database Integration

### Cloudflare D1 with Drizzle

```typescript
// server/utils/db.ts
import { drizzle } from 'drizzle-orm/d1'
import * as schema from '~/server/database/schema'

export function useDB(event: H3Event) {
  const { DB } = event.context.cloudflare.env
  return drizzle(DB, { schema })
}

// server/api/users/index.get.ts
export default defineEventHandler(async (event) => {
  const db = useDB(event)

  const users = await db.select().from(schema.users).limit(10)

  return { users }
})
```

### Schema Definition

```typescript
// server/database/schema.ts
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'

export const users = sqliteTable('users', {
  id: integer('id').primaryKey({ autoIncrement: true }),
  name: text('name').notNull(),
  email: text('email').notNull().unique(),
  createdAt: integer('created_at', { mode: 'timestamp' })
    .notNull()
    .$defaultFn(() => new Date())
})

export const posts = sqliteTable('posts', {
  id: integer('id').primaryKey({ autoIncrement: true }),
  userId: integer('user_id').notNull().references(() => users.id),
  title: text('title').notNull(),
  content: text('content'),
  createdAt: integer('created_at', { mode: 'timestamp' })
    .notNull()
    .$defaultFn(() => new Date())
})
```

### CRUD Operations

```typescript
// server/api/users/index.post.ts
import { users } from '~/server/database/schema'
import { eq } from 'drizzle-orm'

export default defineEventHandler(async (event) => {
  const db = useDB(event)
  const body = await readBody(event)

  // Create
  const [user] = await db.insert(users)
    .values({ name: body.name, email: body.email })
    .returning()

  return { user }
})

// server/api/users/[id].put.ts
export default defineEventHandler(async (event) => {
  const db = useDB(event)
  const id = getRouterParam(event, 'id')
  const body = await readBody(event)

  // Update
  const [user] = await db.update(users)
    .set({ name: body.name })
    .where(eq(users.id, Number(id)))
    .returning()

  if (!user) {
    throw createError({ statusCode: 404, message: 'User not found' })
  }

  return { user }
})

// server/api/users/[id].delete.ts
export default defineEventHandler(async (event) => {
  const db = useDB(event)
  const id = getRouterParam(event, 'id')

  // Delete
  await db.delete(users).where(eq(users.id, Number(id)))

  return { success: true }
})
```

## Validation with Zod

```typescript
// server/api/users/index.post.ts
import { z } from 'zod'

const createUserSchema = z.object({
  name: z.string().min(2).max(100),
  email: z.email(),
  age: z.number().int().min(0).max(150).optional()
})

export default defineEventHandler(async (event) => {
  const body = await readBody(event)

  // Validate
  const result = createUserSchema.safeParse(body)

  if (!result.success) {
    throw createError({
      statusCode: 400,
      message: 'Validation failed',
      data: result.error.flatten()
    })
  }

  // Use validated data
  const { name, email, age } = result.data

  // Create user...
  return { success: true }
})
```

## File Uploads

```typescript
// server/api/upload.post.ts
export default defineEventHandler(async (event) => {
  const formData = await readMultipartFormData(event)

  if (!formData) {
    throw createError({ statusCode: 400, message: 'No file uploaded' })
  }

  const file = formData.find(f => f.name === 'file')

  if (!file) {
    throw createError({ statusCode: 400, message: 'File field is required' })
  }

  // file.filename - Original filename
  // file.type - MIME type
  // file.data - Buffer with file contents

  // Upload to R2 (Cloudflare)
  const { R2 } = event.context.cloudflare.env
  const key = `uploads/${Date.now()}-${file.filename}`
  await R2.put(key, file.data)

  return { key, filename: file.filename, type: file.type }
})
```

## Server Utilities

```typescript
// server/utils/auth.ts
import { H3Event } from 'h3'

export function requireAuth(event: H3Event) {
  const user = event.context.user

  if (!user) {
    throw createError({
      statusCode: 401,
      message: 'Authentication required'
    })
  }

  return user
}

export function requireRole(event: H3Event, role: string) {
  const user = requireAuth(event)

  if (user.role !== role) {
    throw createError({
      statusCode: 403,
      message: 'Insufficient permissions'
    })
  }

  return user
}

// Usage in routes
export default defineEventHandler(async (event) => {
  const user = requireAuth(event)
  // or
  const admin = requireRole(event, 'admin')
})
```

## Common Anti-Patterns

### Missing Method Suffix

```typescript
// WRONG - Handles all methods
// server/api/users.ts

// CORRECT - Explicit method
// server/api/users.get.ts   → GET
// server/api/users.post.ts  → POST
```

### Not Throwing Errors

```typescript
// WRONG - Returns error as data
export default defineEventHandler(async (event) => {
  const user = await findUser(id)
  if (!user) {
    return { error: 'Not found' }  // 200 status!
  }
})

// CORRECT - Throw error
export default defineEventHandler(async (event) => {
  const user = await findUser(id)
  if (!user) {
    throw createError({ statusCode: 404, message: 'Not found' })
  }
})
```

### Forgetting Async/Await

```typescript
// WRONG - Body not awaited
export default defineEventHandler((event) => {
  const body = readBody(event)  // Returns Promise!
})

// CORRECT
export default defineEventHandler(async (event) => {
  const body = await readBody(event)
})
```

## Troubleshooting

**404 on API Routes:**
- Ensure file is in `server/api/` (not `app/api/`)
- Check method suffix matches request (`.get.ts` for GET)
- Verify file extension is `.ts`

**Body is Empty:**
- Ensure `await readBody(event)` not `readBody(event)`
- Check Content-Type header is set correctly
- For multipart, use `readMultipartFormData`

**Middleware Not Running:**
- Check file is in `server/middleware/`
- Middleware runs for ALL requests unless filtered

**D1 Binding Not Found:**
- Check wrangler.toml has `[[d1_databases]]` configured
- Access via `event.context.cloudflare.env.DB`

## Related Skills

- **nuxt-core**: Project setup, routing, configuration
- **nuxt-data**: Composables, data fetching, state
- **nuxt-production**: Performance, testing, deployment
- **cloudflare-d1**: D1 database patterns

---

**Version**: 4.0.0 | **Last Updated**: 2025-12-28 | **License**: MIT

© Claude Skills Maintainers · MIT · secondsky/claude-skills

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой