nuxt

GitHub

用于在 Nuxt 应用中嵌入模拟器,支持同域 OAuth、服务器路由配置、状态持久化及预览部署场景。

skills/nuxt/SKILL.md vercel-labs/emulate

Trigger Scenarios

Nuxt emulator adapter-nuxt embedded emulator same-origin OAuth

Install

npx skills add vercel-labs/emulate --skill nuxt -g -y
More Options

Use without installing

npx skills use vercel-labs/emulate@nuxt

指定 Agent (Claude Code)

npx skills add vercel-labs/emulate --skill nuxt -a claude-code -g -y

安装 repo 全部 skill

npx skills add vercel-labs/emulate --all -g -y

预览 repo 内 skill

npx skills add vercel-labs/emulate --list

SKILL.md

Frontmatter
{
    "name": "nuxt",
    "description": "Nuxt adapter for embedding emulators directly in a Nuxt app via @emulators\/adapter-nuxt. Use when the user needs to embed emulators in Nuxt, set up same-origin OAuth for preview deployments, create an emulate catch-all server route, configure persistence for embedded Nuxt emulators, or wrap nuxt.config with withEmulate. Triggers include \"Nuxt emulator\", \"adapter-nuxt\", \"embedded emulator\", \"same-origin OAuth\", \"createEmulateHandler\", \"withEmulate\", or any task requiring emulators inside a Nuxt app.",
    "allowed-tools": "Bash(npx emulate:*)"
}

Nuxt Integration

The @emulators/adapter-nuxt package embeds emulators directly into a Nuxt app, running them on the same origin. This is useful for preview deployments where OAuth callback URLs change with every deployment.

Install

npm install @emulators/adapter-nuxt @emulators/github @emulators/google

Only install the emulators you need. Each @emulators/* package is published independently, keeping server bundles small.

Server Route

Create a named catch-all route that serves emulator traffic:

// server/routes/emulate/[...path].ts
import { createEmulateHandler } from '@emulators/adapter-nuxt'
import * as github from '@emulators/github'
import * as google from '@emulators/google'

export default defineEventHandler(createEmulateHandler({
  services: {
    github: {
      emulator: github,
      seed: {
        users: [{ login: 'octocat', name: 'The Octocat' }],
        repos: [{ owner: 'octocat', name: 'hello-world', auto_init: true }],
      },
    },
    google: {
      emulator: google,
      seed: {
        users: [{ email: 'test@example.com', name: 'Test User' }],
      },
    },
  },
}))

This creates these routes:

  • /emulate/github/** serves the GitHub emulator
  • /emulate/google/** serves the Google emulator

GitHub installation-token metadata is available server-side at /emulate/github/_emulate/installation-tokens.

Nuxt Config

Emulator UI pages use bundled fonts. Wrap your Nuxt config so Nitro traces the core package assets into production builds:

// nuxt.config.ts
import { withEmulate } from '@emulators/adapter-nuxt'

export default defineNuxtConfig(withEmulate({
  // your normal Nuxt config
}))

OAuth Configuration

Point your OAuth provider at the emulator paths on the same origin:

const baseUrl = process.env.NUXT_PUBLIC_SITE_URL ?? 'http://localhost:3000'

export const githubOAuth = {
  clientId: 'any-value',
  clientSecret: 'any-value',
  authorizationUrl: `${baseUrl}/emulate/github/login/oauth/authorize`,
  tokenUrl: `${baseUrl}/emulate/github/login/oauth/access_token`,
  userInfoUrl: `${baseUrl}/emulate/github/user`,
}

No oauth_apps need to be seeded. When none are configured, the emulator skips client_id, client_secret, and redirect_uri validation.

Persistence

By default, emulator state is in-memory and resets on every cold start. To persist state across restarts, pass a persistence adapter.

Nitro Storage

import { createEmulateHandler } from '@emulators/adapter-nuxt'
import * as github from '@emulators/github'

const storageAdapter = {
  async load() { return await useStorage('emulate').getItem<string>('state') },
  async save(data: string) { await useStorage('emulate').setItem('state', data) },
}

export default defineEventHandler(createEmulateHandler({
  services: { github: { emulator: github } },
  persistence: storageAdapter,
}))

File Persistence

For local development, @emulators/core ships a file-based adapter:

import { filePersistence } from '@emulators/core'

persistence: filePersistence('.emulate/state.json'),

GitHub App seeds may omit private_key. Retain the handler and call server-only generatedSecrets(); explicit keys are excluded. Keep persisted snapshots private and implement initialize atomically.

How Persistence Works

  • Cold start: The adapter loads state from the persistence adapter. If found, it restores the full Store and token map. If not found, it seeds from config and saves the initial state.
  • After mutating requests (POST, PUT, PATCH, DELETE): State is saved. Saves are serialized via an internal queue to prevent race conditions.
  • No persistence configured: Falls back to pure in-memory. Seed data re-initializes on every cold start.

How It Works

  1. Incoming request: /emulate/github/login/oauth/authorize?client_id=...
  2. Parse: service = github, rest = /login/oauth/authorize
  3. Strip prefix: A new Request is created with the stripped path and forwarded to the GitHub service app
  4. Rewrite response: HTML action and href attributes, CSS url() font references, and Location headers get the service prefix prepended
  5. Persist: After mutating requests, state is saved via the persistence adapter

Limitations

  • Requires a Node-compatible Nuxt server runtime since emulators use Node APIs
  • Concurrent mutations use last-write-wins semantics. Generated identities require initialize to select the initial snapshot atomically across cold starts.

Config Reference

createEmulateHandler(config, options?)

Field Type Description
services Record<string, EmulatorEntry> Map of service name to emulator config
persistence? PersistenceAdapter Optional persistence adapter for state across cold starts

Each EmulatorEntry:

Field Type Description
emulator EmulatorModule The emulator package, such as import * as github from '@emulators/github'
seed? Record<string, unknown> Seed data matching the service's config schema

Options:

Option Type Default Description
param string "path" Named catch-all route param
routePrefix string detected Path prefix where the catch-all route is mounted

withEmulate(nuxtConfig)

Wraps a Nuxt config to include @emulators/core assets in Nitro's production trace. Call it inside defineNuxtConfig in nuxt.config.ts.

PersistenceAdapter

interface PersistenceAdapter {
  load(): Promise<string | null>
  save(data: string): Promise<void>
  initialize?(data: string): Promise<string>
}

initialize must atomically create the initial value or return the value another instance created first. Implement it with compare-and-set semantics such as Redis SET NX. The built-in filePersistence(path) from @emulators/core provides this behavior for local development.

Custom emulators

The adapter accepts definitions created with defineEmulator from emulate in services[name].emulator. Reuse the definition from CLI/tests; custom inspector is opt-in. Root-relative redirect locations stay under the service mount, while custom HTML bodies pass through unchanged. Await the returned handler's close() in test teardown. Install emulate as a runtime dependency for deployed definitions. See https://emulate.dev/docs/custom-emulators for seeds, snapshots, persistence, and lifecycle rules.

Version History

  • 3edeb2d Current 2026-09-28 03:20

    新增自定义有状态 HTTP API 模拟器支持,修复 Windows 路径处理、Node 26 兼容性、流式响应持久化及 watch 模式恢复问题。

  • 037ffc1 2026-09-09 10:02

    新增 inspect installation token metadata 功能;重构并共享 Next 和 Nuxt 适配器的持久化运行时与测试,修复不完整规范身份验证问题。

  • 1e4b71a 2026-07-25 08:56

Same Skill Collection

skills/apple/SKILL.md
skills/custom-apis/SKILL.md
skills/github/SKILL.md
skills/linear/SKILL.md
skills/resend/SKILL.md
skills/emulate/SKILL.md
skills/google/SKILL.md
skills/microsoft/SKILL.md
skills/next/SKILL.md
skills/vercel/SKILL.md

Metadata

Files
0
Version
3edeb2d
Hash
6d068090
Indexed
2026-07-25 08:56

Home - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-09-28 21:50
浙ICP备14020137号-1