Deploy with Next.js
Deploy generated App Router handlers without treating serverless memory or post-response work as durable.
Next.js support is generated by the Lucid CLI; there is no standalone Next.js
adapter package. Generated App Router modules pass the original Request and
route params to a shared Lucid HTTP runtime.
Generate from the Next workspace
Build this repository first, then run its local CLI so the route modules and workspace API belong to the same Next snapshot:
bun install --frozen-lockfile
bun run build:packages
bun packages/cli/dist/index.js my-service --adapter=next
cd my-service
bun install --frozen-lockfile
bun run type-check
bun run buildRunning an unpinned bunx @lucid-agents/cli resolves the public Stable CLI,
not this repository's Next surface.
The generated application includes:
- public discovery routes under
/.well-known/...; - the main Lucid API under
/api/agent; - thin invoke, stream, task, health, manifest, and landing modules;
- one server-only runtime/handler module;
- an optional read-only endpoint directory.
Do not hand-copy only one route: the set evolves with the runtime contract.
Keep route modules thin
An invoke route should only validate its dynamic key and delegate:
import type { NextRequest } from 'next/server';
import { handlers } from '@/lib/agent';
export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';
type RouteContext = {
params: Promise<{ key?: string }>;
};
export async function POST(request: NextRequest, context: RouteContext) {
const { key } = await context.params;
if (!key) return new Response('Missing key', { status: 400 });
return handlers.invoke(request, { key });
}The shared @/lib/agent module should build one runtime per server instance and
export its handlers. Do not instantiate a new runtime/store for each request,
parse the body in the route, or wrap the route with separate x402 middleware.
Use the Node.js route runtime when importing SQLite/Postgres drivers or other Node-only subpaths. Edge deployment is possible only for the portable package surface and external store/provider clients that the target supports.
Understand the host process model
Many Next hosts create, freeze, scale, and destroy instances independently. Therefore:
- module-level in-memory payment totals and idempotency are per instance;
- local files may be ephemeral and not shared;
- a task handler started after returning
202/200may be frozen or killed; - scheduler timers are not a reliable job service;
- connection pools and cold starts affect facilitator/database calls;
- maximum request and stream duration is provider-specific.
Use shared Postgres/custom stores for paid state. Run Lucid background tasks and scheduler workers in a separate long-lived service unless the host offers a durable job primitive you explicitly integrate and test.
Configuration and secrets
Configure server-only values through the deployment environment:
PAYMENTS_FACILITATOR_URL=https://YOUR_PRODUCTION_FACILITATOR
PAYMENTS_NETWORK=eip155:8453
PAYMENTS_RECEIVABLE_ADDRESS=0xYOUR_RECEIVING_ADDRESS
PAYMENTS_FACILITATOR_AUTH=...
DATABASE_URL=...Never prefix signing keys, database credentials, facilitator tokens, or Stripe
secrets with NEXT_PUBLIC_. The generated endpoint directory needs no browser
wallet or payment credentials.
Public origin and base paths
The generated storefront derives its origin from request headers and expects
the API at /api/agent. Configure one canonical public host, trusted forwarded
scheme/host headers, and any platform rewrite consistently. Verify both root
well-known routes and the API Agent Card URLs after deploy.
Avoid a rewrite that changes the signed payment resource between challenge and retry. If the external base path differs from the runtime path, regenerate or configure the runtime rather than correcting URLs only in the UI.
Streaming
Test POST /api/agent/entrypoints/:key/stream through the production CDN and
function runtime. Confirm:
- headers and the first SSE event flush before handler completion;
- no CDN/framework cache or body transformation applies;
- disconnect reaches the request abort signal;
- host max duration/idle timeout exceeds the bounded stream;
- concurrency and response-size limits match the product contract.
If the host buffers or caps streams below your requirement, deploy the API on a long-lived Hono/Express service and let Next serve only the storefront.
Self-hosted build
For a persistent Node deployment:
bun run type-check
bun run build
NODE_ENV=production PORT=3000 bun run startContainerize the build with a pinned Node/Bun-compatible image and the Next
standalone/output mode you have tested. Persist no critical state in the image
or writable container layer. Add graceful termination at the platform level;
Next route modules do not automatically call runtime.close() for every
shutdown topology, so verify connection/resource cleanup in your chosen host.
Readiness and canary
The public /api/agent/health handler is liveness, not database/facilitator
readiness. Add a protected route or deployment check for schema, store atomic
probe, wallet/provider availability, and facilitator support.
After deploy:
curl --fail https://service.example/api/agent/health
curl --fail https://service.example/.well-known/agent-card.json
curl -i https://service.example/api/agent/entrypoints/quote/invoke \
-H 'content-type: application/json' \
-H 'idempotency-key: deploy-next-canary-000001' \
--data '{"input":{"symbol":"ETH"}}'Require an unpaid 402, then perform one low-limit funded canary. Verify the
schema-valid output, PAYMENT-RESPONSE, external transaction, durable payment
record, and same-key replay from a different/new instance. If tasks are
advertised, kill the submitting instance and verify worker recovery before
production.
Rollback
Retain the prior immutable build and use expand/contract database migrations. On a canary discrepancy, stop paid admission, preserve staged settlements and idempotency records, reconcile money plus fulfillment, then route back to a schema-compatible build. Do not point the storefront at a legacy unprotected handler.
See Add Lucid to an existing app, durable storage, and the deployment overview.