rembrembdocs

You can create a tRPC server within any edge runtime that follow the WinterCG, specifically the Minimum Common Web Platform API specification.

Some of these runtimes includes, but not limited to:

This also makes it easy to integrate into frameworks that uses the web platform APIs to represent requests and responses, such as:

Example apps

Description

Links

Cloudflare Workers example

[

Source

](https://github.com/trpc/trpc/tree/main/examples/cloudflare-workers)

Deno Deploy example

[

Source

](https://github.com/trpc/trpc/tree/main/examples/deno-deploy)

Next.js Edge Runtime example

[

Source

](https://github.com/trpc/trpc/tree/main/examples/next-edge-runtime)

Vercel Edge Runtime example

[

Source

](https://github.com/trpc/trpc/tree/main/examples/vercel-edge-runtime)

How to use tRPC server with an edge runtime

tRPC provides a fetch adapter that uses the native Request and Response APIs as input and output. The tRPC-specific code is the same across all runtimes, the only difference being how the response is returned.

tRPC includes an adapter for the native Fetch API out of the box. This adapter lets you convert your tRPC router into a Request handler that returns Response objects.

Required Web APIs

tRPC server uses the following Fetch APIs:

If your runtime supports these APIs, you can use tRPC server.

tip

Fun fact: that also means you can use a tRPC server in your browser!

Common setup

Install dependencies

tip

You can skip this step if you use Deno Deploy.

sh

npm install @trpc/server zod

sh

npm install @trpc/server zod

Zod isn't a required dependency, but it's used in the sample router below.

Create the router

First of all you need a router to handle your queries, mutations and subscriptions.

A sample router is given below, save it in a file named router.ts.

router.ts

If your router file starts getting too big, split your router into several subrouters each implemented in its own file. Then merge them into a single root appRouter.

Create the context

Then you need a context that will be created for each request.

A sample context is given below, save it in a file named context.ts:

context.ts

Runtimes-specific setup

Astro

src/pages/trpc/[trpc].ts

ts

import { fetchRequestHandler } from '@trpc/server/adapters/fetch';

import type { APIRoute } from 'astro';

import { createContext } from '../../server/context';

import { appRouter } from '../../server/router';

export const all: APIRoute = (opts) => {

return fetchRequestHandler({

`endpoint: '/trpc',`

`req: opts.request,`

`router: appRouter,`

`createContext,`

});

};

Cloudflare Worker

Create Cloudflare Worker

server.ts

ts

import { fetchRequestHandler } from '@trpc/server/adapters/fetch';

import { createContext } from './context';

import { appRouter } from './router';

export default {

async fetch(request: Request): Promise<Response> {

`return fetchRequestHandler({`

  `endpoint: '/trpc',`

  `req: request,`

  `router: appRouter,`

  `createContext,`

`});`

},

};

Run wrangler dev server.ts and your endpoints will be available via HTTP!

Endpoint

HTTP URI

getUser

GET http://localhost:8787/trpc/getUserById?input=INPUT

where INPUT is a URI-encoded JSON string.

createUser

POST http://localhost:8787/trpc/createUser

with req.body of type User

Deno Oak

note

This assumes you have Deno installed and setup. Refer to their getting started guide for more information.

Update the imports in router.ts

router.ts

ts

import { initTRPC } from 'npm:@trpc/server';

import { z } from 'npm:zod';

import { Context } from './context.ts';

Update the imports in context.ts

context.ts

ts

import { FetchCreateContextFnOptions } from 'npm:@trpc/server/adapters/fetch';

Use fetchRequestHandler with Oak in app.ts

app.ts

ts

import { Application, Router } from 'https://deno.land/x/oak/mod.ts';

import { fetchRequestHandler } from 'npm:@trpc/server/adapters/fetch';

import { createContext } from './context.ts';

import { appRouter } from './router.ts';

const app = new Application();

const router = new Router();

router.all('/trpc/(.*)', async (ctx) => {

const res = await fetchRequestHandler({

`endpoint: '/trpc',`

`req: new Request(ctx.request.url, {`

  `headers: ctx.request.headers,`

  `body:`

    `ctx.request.method !== 'GET' && ctx.request.method !== 'HEAD'`

      `? ctx.request.body({ type: 'stream' }).value`

      `: void 0,`

  `method: ctx.request.method,`

`}),`

`router: appRouter,`

`createContext,`

});

ctx.response.status = res.status;

ctx.response.headers = res.headers;

ctx.response.body = res.body;

});

app.use(router.routes());

app.use(router.allowedMethods());

await app.listen({ port: 3000 });

Deno Deploy

note

This assumes you have Deno installed and setup. Refer to their getting started guide for more information.

Update the imports in router.ts

router.ts

ts

import { initTRPC } from 'npm:@trpc/server';

import { z } from 'npm:zod';

import { Context } from './context.ts';

Update the imports in context.ts

context.ts

ts

import { FetchCreateContextFnOptions } from 'npm:@trpc/server/adapters/fetch';

Create Deno Deploy Function

server.ts

ts

import { fetchRequestHandler } from 'npm:@trpc/server/adapters/fetch';

import { createContext } from './context.ts';

import { appRouter } from './router.ts';

function handler(request) {

return fetchRequestHandler({

`endpoint: '/trpc',`

`req: request,`

`router: appRouter,`

`createContext,`

});

}

Deno.serve(handler);

Run deno run --allow-net=:8000 --allow-env ./server.ts and your endpoints will be available via HTTP!

Endpoint

HTTP URI

getUser

GET http://localhost:8000/trpc/getUserById?input=INPUT

where INPUT is a URI-encoded JSON string.

createUser

POST http://localhost:8000/trpc/createUser

with req.body of type User

Next.js Edge Runtime

See a full example here.

Remix

app/routes/trpc/$trpc.ts

ts

import type { ActionArgs, LoaderArgs } from '@remix-run/node';

import { fetchRequestHandler } from '@trpc/server/adapters/fetch';

import { createContext } from '~/server/context';

import { appRouter } from '~/server/router';

export const loader = async (args: LoaderArgs) => {

return handleRequest(args);

};

export const action = async (args: ActionArgs) => {

return handleRequest(args);

};

function handleRequest(args: LoaderArgs | ActionArgs) {

return fetchRequestHandler({

`endpoint: '/trpc',`

`req: args.request,`

`router: appRouter,`

`createContext,`

});

}

SolidStart

src/routes/api/trpc/[trpc].ts

ts

import { fetchRequestHandler } from '@trpc/server/adapters/fetch';

import type { APIEvent } from 'solid-start';

import { createContext } from '../../server/context';

import { appRouter } from '../../server/router';

const handler = (event: APIEvent) =>

fetchRequestHandler({

`endpoint: '/api/trpc',`

`req: event.request,`

`router: appRouter,`

`createContext,`

});

export { handler as GET, handler as POST };

Vercel Edge Runtime

Install dependencies

sh

npm install -g edge-runtime

sh

npm install -g edge-runtime

Create Edge Runtime Function

server.ts

ts

import { fetchRequestHandler } from '@trpc/server/adapters/fetch';

import { createContext } from './context';

import { appRouter } from './router';

addEventListener('fetch', (event) => {

return event.respondWith(

`fetchRequestHandler({`

  `endpoint: '/trpc',`

  `req: event.request,`

  `router: appRouter,`

  `createContext,`

`}),`

);

});

Run edge-runtime --listen server.ts --port 3000 and your endpoints will be available via HTTP!

Endpoint

HTTP URI

getUser

GET http://localhost:3000/trpc/getUserById?input=INPUT

where INPUT is a URI-encoded JSON string.

createUser

POST http://localhost:3000/trpc/createUser

with req.body of type User