Go on the server.
tRPC on the client.

Write your handlers in Go and call them from TypeScript with tRPC. trpcgo generates the router types, Zod schemas, and enum values from your Go code.

Install
go get github.com/befabri/trpcgo@latest
server.go
// Role is a user's permission level.
type Role string

const (
  RoleAdmin  Role = "admin"
  RoleEditor Role = "editor"
)

type CreateUserInput struct {
  Name  string `json:"name"`
  Email string `json:"email" validate:"email"`
  Role  Role   `json:"role"`
}

trpcgo.MustMutation(
  router, "user.create", createUser,
)
gen/
/** Role is a user's permission level. */
export type Role = "admin" | "editor";

export interface CreateUserInput {
  name: string;
  email: string;
  role: Role;
}

type AppRouterRecord = {
  user: {
    create: $Mutation<CreateUserInput, User>;
  };
};
client.ts
import { createTRPCClient, httpBatchLink } from "@trpc/client";
import type { AppRouter } from "./gen/trpc";
import { RoleEnum } from "./gen/enums";
import {
  CreateUserInputSchema,
} from "./gen/zod";

const client = createTRPCClient<AppRouter>({
  links: [httpBatchLink({ url: "/trpc" })],
});

const input = CreateUserInputSchema.parse({
  name: "Ada",
  email: "ada@example.com",
  role: RoleEnum.admin,
});

const user = await
  client.user.create.mutate(input);

The tRPC backend features you expect, in Go.

Use net/http with the Go router and middleware you already know.

Typed procedures
Go queries, mutations, and SSE subscriptions, with middleware, metadata, and server-side callers.
HTTP runtime
Batching, SSE subscriptions, CORS, trusted origins, and error formatting.
Frontend generation
Generate TypeScript AppRouter types, Zod schemas, and enum values. Watch mode keeps them up to date as you edit Go files.

Start with your Go module.

Register your Go procedures and choose where the generated files go. Create the HTTP handler to start generation in development mode.

router := trpcgo.NewRouter(
  trpcgo.WithDev(true),
  trpcgo.WithValidator(validate.Struct),
  trpcgo.WithTypeOutput("../web/gen/trpc.ts"),
  trpcgo.WithZodOutput("../web/gen/zod.ts"),
  trpcgo.WithEnumsOutput("../web/gen/enums.ts"),
)
defer router.Close()

trpcgo.MustMutation(router, "user.create", createUser)
Open the quick start →