End-to-end type safety from Go to TypeScript

2 min read Original article ↗

A Go framework for end-to-end type-safe APIs

Write Go.
TypeScript keeps up.

Define typed handler functions in Go. ShiftAPI generates an OpenAPI 3.1 spec at runtime and a fully-typed TypeScript client via Vite/Next.js HMR — no codegen CLI, no manual spec, no drift.

Your Go struct becomes the TypeScript type. Change a field in Go, your frontend knows instantly.

Three layers, one source of truth. No manual steps between them.

1

Define typed handlers

Write standard Go functions with struct input/output types. Use json, query, path, and header struct tags — ShiftAPI routes them automatically.

shiftapi.Handle(api, "POST /greet", greet)

2

OpenAPI 3.1 spec generated at runtime

ShiftAPI reflects your Go types into a complete OpenAPI 3.1 schema. Served at /openapi.json — always matches your code, never maintained by hand.

GET /openapi.json → { "openapi": "3.1", ... }

3

TypeScript client via HMR

A Vite or Next.js plugin fetches the spec from your running Go server and generates a fully-typed client. Save a Go file, types update instantly.

const { data } = await client.POST("/greet", ...) // ^? { hello: string }

Type-Safe Handlers

Generic Go functions capture request and response types at compile time. json, query, header, and form tags route input automatically.

Validation Included

Struct tags like validate:"required,email" are enforced at runtime and reflected into your OpenAPI schema.

Vite & Next.js

First-class plugins that start your Go server, proxy requests, and regenerate types on every save.

File Uploads

Declare uploads with form tags. The TypeScript client gets correct multipart/form-data types automatically.

Interactive Docs

Scalar API reference at /docs and an OpenAPI spec at /openapi.json — generated, never stale.

Real-Time

HandleSSE gives you typed server push with an sse helper. HandleWS adds typed bidirectional WebSockets with a websocket helper.

One command scaffolds a full-stack Go + React, Svelte, or Next.js app with end-to-end types.

$npm create shiftapi@latest