A "play" project exploring the seamless integration of Go gRPC and SvelteKit 5. This repository demonstrates how to bypass the traditional hurdles of gRPC-Web by using the Connect RPC protocol to achieve end-to-end type safety.
Standard gRPC uses HTTP/2 trailing headers, which browsers cannot access. Traditionally, this required a complex Envoy proxy. The Solution: This project uses Connect RPC to allow the Go server to speak a web-friendly version of gRPC that SvelteKit can consume directly (or via SSR) with zero proxy overhead and 100% TypeScript type safety.
Here is a step-by-step breakdown of the advantages and disadvantages.
β
Browser Native (No Proxies)
β
Better Debugging (cURL & DevTools)
β
Plugs into the Go Ecosystem (A Connect server is an http.Handler. You can use it with any Go router and any standard middleware you already love.)
β
Three Protocols in One (gRPC, gRPC-Web, Connect)
β Performance "Edge Cases" - for 99% of web apps, the difference is zero - Googleβs grpc-go is slightly more optimized for raw HTTP/2 framing than a standard net/http server.
β Smaller Ecosystem
β Feature Parity (Streaming) - bidirectional streaming over HTTP/1.1 is technically impossible while Connect allows it to fail silently if the network only supports HTTP/1.1.
βββ proto/ # Source of Truth (Protobuf definitions)
βββ server/ # Go Service (The "Source")
β βββ pkg/greeter/ # Auto-generated Go gRPC stubs
βββ client/ # SvelteKit App (The "Consumer")
β βββ src/gen/ # Auto-generated TypeScript Connect stubs
βββ taskfile.yml # The orchestrator
βββ buf.gen.server.yaml # Backend generation config
βββ buf.gen.client.yaml # Frontend generation config
Type-Safe Flow: Protobuf β Go Structs β TypeScript Runes.
SvelteKit 5 Integration: Leverages $state, $derived, and $props for reactive gRPC updates.
SSR Ready: gRPC calls are made in +page.server.ts to keep backend secrets secure and improve SEO.
Dual Generation: Independent buf templates for fine-grained control over server and client code.
Below are listed required tools: - Go (1.21+) - Node.js (v20+) - Buf CLI - Task (recommended)
The core of this project is the automated sync between the proto and the codebases:
# Sync both worlds
task gen-server
task gen-client
Start Go Backend:
cd server && go run main.go
Start SvelteKit:
cd client && npm run dev
The Go Handler (Connect)
Instead of standard gRPC, we wrap our service to support the Connect protocol, making it reachable via standard HTTP/1.1 or HTTP/2:
mux := http.NewServeMux()
path, handler := greeterconnect.NewGreeterHandler(&server{})
mux.Handle(path, handler)
The Svelte Load (SSR) We fetch data on the server so the browser receives fully rendered HTML, with the gRPC data already populated:
export const load: PageServerLoad = async () => {
const res = await client.getAll({});
return { todos: res.items }; // Fully typed!
};
Task,Command,Result gen-server,buf generate ...,Updates server/pkg/greeter with Go stubs. gen-client,buf generate ...,Updates client/src/gen with TS/Connect stubs.