Skip to main content

adapter-standalone

Mount tRPC on Node.js built-in HTTP server with createHTTPServer() from @trpc/server/adapters/standalone, createHTTPHandler() for custom http.createServer, createHTTP2Handler() for HTTP/2 with TLS. Configure basePath to slice URL prefix, CORS via the cors npm package passed as middleware option. CreateHTTPContextOptions provides req and res for context creation.

Jump to install

Source facts

Repository
trpc/trpc
Last source activity
March 28, 2026 at 10:58
Detected SKILL.md language
English
Stars
40,667
Forks
1,691

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
adapter-standalone
description
Mount tRPC on Node.js built-in HTTP server with createHTTPServer() from @trpc/server/adapters/standalone, createHTTPHandler() for custom http.createServer, createHTTP2Handler() for HTTP/2 with TLS. Configure basePath to slice URL prefix, CORS via the cors npm package passed as middleware option. CreateHTTPContextOptions provides req and res for context creation.
type
core
library
trpc
library_version
11.16.0
requires
["server-setup"]
sources
["www/docs/server/adapters/standalone.md","examples/standalone-server/src/server.ts"]
# tRPC — Adapter: Standalone ## Setup ```ts // server.ts import { initTRPC } from '@trpc/server'; import { createHTTPServer } from '@trpc/server/adapters/standalone'; import { z } from 'zod'; const t = initTRPC.create(); const appRouter = t.router({ greet: t.procedure .input(z.object({ name: z.string() })) .query(({ input }) => ({ greeting: `Hello, ${input.name}!` })), }); export type AppRouter = typeof appRouter; createHTTPServer({ router: appRouter, createContext() { return {}; }, }).listen(3000); console.log('Listening on http://localhost:3000'); ``` ## Core Patterns ### CORS with the cors package ```ts import { createHTTPServer } from '@trpc/server/adapters/standalone'; import cors from 'cors'; import { createContext } from './context'; import { appRouter } from './router'; createHTTPServer({ middleware: cors({ origin: 'http://localhost:5173' }), router: appRouter, createContext, }).listen(3000); ``` Install CORS support: `npm install cors @types/cors` ### Custom HTTP server with createHTTPHandler ```ts import { createServer } from 'http'; import { createHTTPHandler } from '@trpc/server/adapters/standalone'; import { appRouter } from './router'; const handler = createHTTPHandler({ router: appRouter, createContext() { return {}; }, }); createServer((req, res) => { if (req.url?.startsWith('/health')) { res.writeHead(200); res.end('OK'); return; } handler(req, res); }).listen(3000); ``` ### basePath for URL prefix stripping ```ts import { createServer } from 'http'; import { createHTTPHandler } from '@trpc/server/adapters/standalone'; import { appRouter } from './router'; const handler = createHTTPHandler({ router: appRouter, basePath: '/trpc/', }); createServer((req, res) => { if (req.url?.startsWith('/trpc/')) { return handler(req, res); } res.statusCode = 404; res.end('Not Found'); }).listen(3000); ``` The `basePath` option strips the prefix before routing, so `/trpc/greet` resolves to the `greet` procedure. ### HTTP/2 with createHTTP2Handler ```ts import http2 from 'http2'; import { readFileSync } from 'node:fs'; import { createHTTP2Handler } from '@trpc/server/adapters/standalone'; import type { CreateHTTP2ContextOptions } from '@trpc/server/adapters/standalone'; import { appRouter } from './router'; const tlsKey = readFileSync('./certs/server.key'); const tlsCert = readFileSync('./certs/server.crt'); async function createContext(opts: CreateHTTP2ContextOptions) { return {}; } const handler = createHTTP2Handler({ router: appRouter, createContext, }); const server = http2.createSecureServer( { key: tlsKey, cert: tlsCert }, (req, res) => { handler(req, res); }, ); server.listen(3001); ``` ### Limiting batch size with maxBatchSize ```ts import { createHTTPServer } from '@trpc/server/adapters/standalone'; import { appRouter } from './router'; createHTTPServer({ router: appRouter, maxBatchSize: 10, }).listen(3000); ``` Requests batching more than `maxBatchSize` operations are rejected with a `400 Bad Request` error. Set `maxItems` on your client's `httpBatchLink` to the same value to avoid exceeding the limit. ## Common Mistakes ### HIGH No CORS configuration for cross-origin requests Wrong: ```ts createHTTPServer({ router: appRouter, createContext() { return {}; }, }).listen(3000); ``` Correct: ```ts import cors from 'cors'; createHTTPServer({ middleware: cors({ origin: 'http://localhost:5173' }), router: appRouter, createContext() { return {}; }, }).listen(3000); ``` The standalone adapter has no CORS handling by default. Cross-origin browser requests fail silently because preflight OPTIONS requests receive no CORS headers. Source: www/docs/server/adapters/standalone.md ## See Also - **server-setup** -- `initTRPC.create()`, router/procedure definition, context - **adapter-express** -- alternative adapter when you need Express middleware ecosystem - **adapter-fetch** -- alternative adapter for edge/serverless runtimes - **subscriptions** -- adding real-time subscriptions to a standalone server
View on GitHub