Overview
@contract-kit/next is the Next.js adapter for the framework-agnostic @contract-kit/server runtime. It translates Next.js Request/Response to/from the runtime’s internal types and provides a minimal API for both catch-all and per-contract routing.
Installation
Peer Dependencies
next: ^14.0.0 || ^15.0.0 || ^16.0.0@contract-kit/openapi: ^0.1.0 (optional, for OpenAPI documentation)
Quick Start
1. Define Your Contracts
2. Create Your Server
3. Set Up Routes
You have two options for routing:Option A: Catch-All Route (Recommended)
Create a catch-all route that handles all contracts:Option B: Per-Contract Routes
Create individual route files for each contract:API Reference
createNextServer<Ctx>(options)
Creates a Next.js server instance with the given options.
Parameters:
options: Same ascreateServerfrom@contract-kit/server:ports: Required - Ports object defining available service interfacescreateContext: Async function to create request contextonUnhandledError: Error handler functionroutes?: Array of route configurations (contract + handler)middleware?: Optional array of middlewareproviders?: Optional array of service providersproviderEnv?: Optional environment variables for providersproviderConfig?: Optional provider configuration overrides
Promise<NextServer<Ctx>>
NextServer Methods
server.api()
Returns a Next.js handler for catch-all routes. Use this with app/api/[...contract-kit]/route.ts to handle all registered contracts.
server.handle(contract)
Returns a Next.js handler for a specific contract. Use this when you want to handle a contract without registering it globally.
server.route(contract)
Returns a route builder for creating custom handlers for a specific contract. The contract is NOT registered globally (won’t be available via server.api()).
Returns: Route builder with:
handle(fn): Create a custom handler functionuseCase(useCase, maps): Connect a use case with input/output mapping
server.register(contract)
Returns a route builder (same as route()) but also registers the contract globally, making it available via server.api().
server.createContextFromNext()
Creates a context object from Next.js Server Components by automatically extracting headers and cookies. This allows you to call use cases directly from React Server Components without going through API routes.
Returns: Promise<Ctx> - Your context object from createContext
- Eliminates unnecessary API routes for server-side data fetching
- Maintains type safety and business logic separation
- Automatically handles headers and cookies from Next.js
- Reuses your existing context creation logic
- Can only be called from Next.js Server Components (not in Client Components or during build time)
- The internal Request-like object uses HTTP method
"GET". If yourcreateContextchecksreq.method, it will always see"GET". - The
req.urlis set to a placeholder (http://server-component.invalid) since Server Components don’t have real HTTP URLs - The
req.json()andreq.text()methods return empty values since there’s no actual HTTP request body in Server Components
server.stop()
Stops the server and cleans up resources (closes provider connections, etc.).
Handler Function Context
When using.handle(), your handler function receives an object with:
Use Case Integration
Contract Kit promotes clean architecture by separating use cases from HTTP concerns. Use the.useCase() method to connect use cases:
Middleware
Middleware can be added at the server level:Providers
Providers are service adapters that implement ports (database, cache, logger, etc.):Error Handling
Global Error Handler
Route-Level Error Handling
OpenAPI Documentation
If you have@contract-kit/openapi installed, you can generate OpenAPI documentation:
Examples
Basic CRUD API
With Authentication
Helper Functions
toRequestLike(req: Request): HttpRequestLike
Converts a Next.js Request to the framework-agnostic HttpRequestLike shape.
toNextResponse(res: HttpResponseLike): Response
Converts an HttpResponseLike to a Next.js Response.
These are used internally by the adapter but can be used directly if needed.
Best Practices
Use catch-all routes for simplicity
Use catch-all routes for simplicity
The catch-all route pattern is recommended for most applications as it reduces boilerplate.
Separate use cases from HTTP handlers
Separate use cases from HTTP handlers
Keep business logic in use cases and use
.useCase() to connect them to routes.Create context wisely
Create context wisely
Only include data in context that’s needed across multiple routes. Keep it lightweight.
Handle errors consistently
Handle errors consistently
Use the global error handler for common errors and route-level handling for specific cases.