go-trpc

module
v0.5.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 10, 2026 License: MIT

README

go-trpc

End-to-end typesafe APIs with Go + TypeScript

Write Go handlers. Generate TypeScript types. Use @trpc/client. Zero Protobuf.

CI Go Reference


go-trpc demo
Try the Live Demo

A real-time chat app with rooms, instant messaging via SSE subscriptions, and built-in dev tools — all powered by go-trpc.

Source code · Report Bug


Architecture

How go-trpc works


How It Works

Define a Go handler with typed structs:

gotrpc.Query(r, "getUser",
    func(ctx context.Context, input GetUserInput) (User, error) {
        return db.FindUser(input.ID)
    },
)

Generate TypeScript types from your Go code:

gotrpc generate ./api --output ./web/src/generated/router.d.ts

# Preview without writing to disk (useful for CI)
gotrpc generate ./api --output ./web/src/generated/router.d.ts --dry-run

Call it from the frontend with full type-safety:

const user = await trpc.getUser.query({ id: '1' }); // fully typed ✓

That's it. Go structs become TypeScript types. No schemas, no Protobuf, no manual type definitions.

Features

Feature
Protocol tRPC v10/v11 compatible Works with @trpc/client unmodified
Type Safety Go generics + codegen Compile-time safety on both ends
Real-time SSE & WebSocket subscriptions Stream events with <-chan T, wsLink compatible
Middlewares Rate limiting, auth, timeout Global and per-procedure, chainable
Batching Batch queries & mutations Built-in tRPC batch support
Deploy Anywhere stdlib HTTP, Lambda, Cloudflare Workers
Dependencies Minimal stdlib + 2 deps (x/time, coder/websocket)

Quick Start

Install
go get github.com/sebasusnik/go-trpc
go install github.com/sebasusnik/go-trpc/cmd/gotrpc@latest
Scaffold a Project
gotrpc init          # creates gotrpc.json, trpc.ts client, generated/ dir
gotrpc init --ws     # same, but with WebSocket (splitLink + wsLink) setup
Server (Go)
package main

import (
    "context"
    "net/http"
    gotrpc "github.com/sebasusnik/go-trpc/pkg/router"
)

type GetUserInput struct {
    ID string `json:"id"`
}

type User struct {
    ID    string `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

func main() {
    r := gotrpc.NewRouter()

    gotrpc.Query(r, "getUser",
        func(ctx context.Context, input GetUserInput) (User, error) {
            return User{ID: input.ID, Name: "John", Email: "john@example.com"}, nil
        },
    )

    http.ListenAndServe(":8080", r.Handler())
}
Client (TypeScript)
import { createTRPCClient, httpLink } from '@trpc/client';
import type { AppRouter } from './generated/router';

const trpc = createTRPCClient<AppRouter>({
  links: [httpLink({ url: 'http://localhost:8080/trpc' })],
});

const user = await trpc.getUser.query({ id: '1' });
//    ^? { id: string; name: string; email: string }

Real-time Subscriptions

Define a subscription once — clients can consume it via SSE or WebSocket:

gotrpc.Subscription(r, "onMessage",
    func(ctx context.Context, input RoomInput) (<-chan Message, error) {
        ch := store.Subscribe(input.RoomID)
        go func() {
            <-ctx.Done()
            store.Unsubscribe(input.RoomID, ch)
        }()
        return ch, nil
    },
)

SSE (simple, works everywhere):

const es = new EventSource('/trpc/onMessage?input={"roomId":"1"}');
es.addEventListener('data', (e) => {
    const msg = JSON.parse(e.data).result.data; // typed Message
});

WebSocket (multiplexed, uses tRPC's wsLink):

import { createTRPCClient, splitLink, httpLink, wsLink } from '@trpc/client';

const trpc = createTRPCClient<AppRouter>({
  links: [
    splitLink({
      condition: (op) => op.type === 'subscription',
      true: wsLink({ url: 'ws://localhost:8080/trpc' }),
      false: httpLink({ url: 'http://localhost:8080/trpc' }),
    }),
  ],
});

// Type-safe subscription with automatic reconnection
trpc.onMessage.subscribe({ roomId: '1' }, {
  onData: (msg) => console.log(msg), // typed Message
});

Nested Routers

Organize procedures into namespaces:

userRouter := gotrpc.NewRouter()
gotrpc.Query(userRouter, "get", getUser)
gotrpc.Mutation(userRouter, "create", createUser)

r := gotrpc.NewRouter()
r.Merge("user", userRouter)  // → user.get, user.create

Middlewares

Global middlewares

Apply to every procedure in the router:

r.Use(gotrpc.RateLimit(100))              // 100 req/s per IP
r.Use(gotrpc.BearerAuth(validateToken))   // JWT/token auth
r.Use(gotrpc.Timeout(5 * time.Second))    // per-request timeout
r.Use(gotrpc.MaxInputSize(4096))          // limit payload size
Per-procedure middlewares

Apply middlewares to individual procedures with WithMiddleware:

// Public — no auth required
gotrpc.Query(r, "listItems", listHandler)

// Requires authentication
gotrpc.Query(r, "getItem", getHandler,
    gotrpc.WithMiddleware(authMiddleware),
)

// Admin-only with stacked middlewares
gotrpc.Mutation(r, "createItem", createHandler,
    gotrpc.WithMiddleware(
        adminAuth,
        gotrpc.MaxInputSize(4096),
        gotrpc.Timeout(2 * time.Second),
    ),
)
Rate limit by key

Rate limit by an arbitrary key (user ID, API key, etc.) instead of IP:

gotrpc.Query(r, "search", searchHandler,
    gotrpc.WithMiddleware(
        gotrpc.RateLimitByKey(10, func(ctx context.Context) string {
            return getUserID(ctx) // rate limit per user
        }),
    ),
)

Deploy Anywhere

// Standard HTTP — Docker, Railway, Fly.io, etc.
http.ListenAndServe(":8080", r.Handler())

// AWS Lambda
trpclambda.Start(r)

// Cloudflare Workers
trpccf.Serve(r)

Documentation

Guide Description
React Query Integration Using @trpc/react-query with go-trpc
Request Cancellation Context cancellation patterns for queries, SSE, and WebSocket
Contributing Development setup, architecture overview, and guidelines
Roadmap What's built, what's next

License

MIT

Directories

Path Synopsis
cmd
gotrpc command
examples
basic command
cloudflare command
lambda command
middleware command
nested-router command
otel command
subscription command
timeout command
validation command
pkg
adapters/cloudflare
Package cloudflare provides a CloudFlare Workers adapter for go-trpc.
Package cloudflare provides a CloudFlare Workers adapter for go-trpc.
adapters/nethttp
Package nethttp provides a production-ready net/http adapter for go-trpc with configurable timeouts and graceful shutdown support.
Package nethttp provides a production-ready net/http adapter for go-trpc with configurable timeouts and graceful shutdown support.
codegen
Package codegen generates TypeScript type definitions from Go source code.
Package codegen generates TypeScript type definitions from Go source code.
otel
Package otel provides OpenTelemetry tracing and metrics integration for go-trpc.
Package otel provides OpenTelemetry tracing and metrics integration for go-trpc.
router
Package router implements a tRPC-compatible RPC server for Go.
Package router implements a tRPC-compatible RPC server for Go.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL