Loading...
Loading...
Next.js adapter for embedding emulators directly in a Next.js app via @emulators/adapter-next. Use when the user needs to embed emulators in Next.js, set up same-origin OAuth for Vercel preview deployments, create an emulate catch-all route handler, configure Auth.js/NextAuth with embedded emulators, add persistence to embedded emulators, or wrap next.config with withEmulate. Triggers include "Next.js emulator", "adapter-next", "embedded emulator", "same-origin OAuth", "Vercel preview", "createEmulateHandler", "withEmulate", or any task requiring emulators inside a Next.js app.
npx skill4agent add vercel-labs/emulate next@emulators/adapter-nextnpm install @emulators/adapter-next @emulators/github @emulators/google@emulators/*// app/emulate/[...path]/route.ts
import { createEmulateHandler } from '@emulators/adapter-next'
import * as github from '@emulators/github'
import * as google from '@emulators/google'
export const { GET, POST, PUT, PATCH, DELETE } = 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' }],
},
},
},
})/emulate/github/**/emulate/google/**import GitHub from 'next-auth/providers/github'
const baseUrl = process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
: 'http://localhost:3000'
GitHub({
clientId: 'any-value',
clientSecret: 'any-value',
authorization: { url: `${baseUrl}/emulate/github/login/oauth/authorize` },
token: { url: `${baseUrl}/emulate/github/login/oauth/access_token` },
userinfo: { url: `${baseUrl}/emulate/github/user` },
})oauth_appsclient_idclient_secretredirect_uri// next.config.mjs
import { withEmulate } from '@emulators/adapter-next'
export default withEmulate({
// your normal Next.js config
})export default withEmulate(nextConfig, { routePrefix: '/api/emulate' })persistenceimport { createEmulateHandler } from '@emulators/adapter-next'
import * as github from '@emulators/github'
const kvAdapter = {
async load() { return await kv.get('emulate-state') },
async save(data: string) { await kv.set('emulate-state', data) },
}
export const { GET, POST, PUT, PATCH, DELETE } = createEmulateHandler({
services: { github: { emulator: github } },
persistence: kvAdapter,
})@emulators/coreimport { filePersistence } from '@emulators/core'
// persists to a JSON file
persistence: filePersistence('.emulate/state.json'),/emulate/github/login/oauth/authorize?client_id=...github/login/oauth/authorizeRequestactionhrefurl()Locationcrypto.randomBytescreateEmulateHandler(config)| Field | Type | Description |
|---|---|---|
| | Map of service name to emulator config |
| | Optional persistence adapter for state across cold starts |
EmulatorEntry| Field | Type | Description |
|---|---|---|
| | The emulator package (e.g. |
| | Seed data matching the service's config schema |
withEmulate(nextConfig, options?)next.config.mjsnext.config.ts| Option | Type | Default | Description |
|---|---|---|---|
| | | The path prefix where the catch-all route is mounted |
PersistenceAdapterinterface PersistenceAdapter {
load(): Promise<string | null>
save(data: string): Promise<void>
}filePersistence(path)@emulators/core