Framework Adapters

Next.js

First-class Next.js App Router support

Next.js#

The @surfjs/next package provides first-class Next.js App Router support with edge-compatible Web Standard Request/Response handling. Install it alongside @surfjs/core:

bash
pnpm add @surfjs/next @surfjs/core

Create a catch-all route handler at app/api/surf/[...slug]/route.ts:

typescript
// app/api/surf/[...slug]/route.ts
import { createSurf } from '@surfjs/core'
import { createSurfRouteHandler } from '@surfjs/next'
ย 
const surf = await createSurf({
name: 'My Next.js App',
commands: {
search: {
description: 'Search products',
params: { query: { type: 'string', required: true } },
run: async ({ query }) => db.search(query),
},
},
})
ย 
// Returns { GET, POST } โ€” export directly as Next.js route handlers
export const { GET, POST } = createSurfRouteHandler(surf)

This mounts the following endpoints under /api/surf/:

| Method | Path | Description | |--------|------|-------------| | GET | /.well-known/surf.json | Manifest (auto via middleware) | | GET / POST | /api/surf/execute | Command execution | | POST | /api/surf/pipeline | Pipeline execution | | POST | /api/surf/session/start | Start session | | POST | /api/surf/session/end | End session |

๐Ÿ’ก Tip: When using @surfjs/next, pass basePath: '/api/surf/execute' to your SurfClient (or --base-path /api/surf/execute to the CLI) so the client targets the correct route.

typescript
import { SurfClient } from '@surfjs/client'
ย 
// Point the client at your Next.js app's execute endpoint
const client = await SurfClient.discover('https://my-app.vercel.app', {
basePath: '/api/surf/execute',
})