---
title: "Mount MainSDK in your framework"
description: "Add the adapter for Next.js, Hono, Express, Cloudflare Workers or a job worker so every request carries a trace, a context and a problem response."
section: "guides"
status: "Building for 0.2"
spec: "adapters"
canonical: "https://mainsdk.dev/docs/guides/mount-mainsdk-in-your-framework"
updated: "2026-10-28"
---

# Mount MainSDK in your framework

> Add the adapter for Next.js, Hono, Express, Cloudflare Workers or a job worker so every request carries a trace, a context and a problem response.

Status: Building for 0.2 · Canonical: https://mainsdk.dev/docs/guides/mount-mainsdk-in-your-framework · Updated: 2026-10-28

You will mount one adapter and see a trace id on every log record. It takes about 10 minutes.

## You need

- A MainSDK app on Next.js, Hono, Express or Cloudflare Workers.

## 1. Mount it

```ts title="server.ts (Hono)"
import { Hono } from "hono";
import { mainsdk } from "mainsdk/hono";

const app = new Hono();
app.use("*", mainsdk());
app.get("/hello", (c) => c.json({ ok: true }));
```

Other frameworks:

```ts title="app/api/orders/route.ts (Next.js App Router)"
import { withMainSDK } from "mainsdk/next";

export const GET = withMainSDK(async (req, ctx) => Response.json({ trace: ctx.traceId }));
```

```ts title="server.ts (Express)"
import express from "express";
import { mainsdk } from "mainsdk/express";

const app = express();
app.use(mainsdk());
app.use(mainsdk.errors());     // last: turns a thrown error into a problem
```

## 2. Read the context

Inside any handler, `requestContext()` from `mainsdk/adapters` returns the trace id, user and tenant. Call `/hello` with a `traceparent` header and every log record carries that trace id. Without it the adapter starts a new one.

## 3. Add hooks if you need them

```ts
import { Hono } from "hono";
import { mainsdk } from "mainsdk/hono";

declare const metrics: { done(traceId: string): void };
declare function warmCaches(): Promise<void>;
declare function flushQueues(): Promise<void>;

const app = new Hono();

app.use("*", mainsdk({
  hooks: { finally: (ctx) => metrics.done(ctx.traceId) },
  startup: async () => warmCaches(),
  shutdown: async () => flushQueues(),
}));
```

`metrics`, `warmCaches` and `flushQueues` are your own.

## 4. Run a job worker

```ts title="jobs/report.ts"
import { worker } from "mainsdk/worker";

declare function buildReport(orderId: string): Promise<void>;

export default worker(async (input: { orderId: string }, ctx) => {
  await buildReport(input.orderId);   // ctx.traceId is the producer's trace
});
```

## Check it worked

```bash
curl -i -H "traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01" localhost:3000/hello
npx mainsdk logs --trace 4bf92f3577b34da6a3ce929d0e0e4736
```

You should see the request's records under that trace.

## Troubleshooting

- `MAIN-CORE-0500`: a handler threw an error that is not a `MainError`. Read the log record with the same trace id.
- A health probe answers 503: the app is draining, which is expected during shutdown.
- A sign-in route answers 404 `MAIN-AUTH-0084`: the method is not in `auth.methods`.

See the [adapters interface](https://mainsdk.dev/docs/interfaces/adapters).
