Combination of tRPC and net/rpc. Run Fast, Move Fast, Break Nothing.

Write Go methods, get a type safe client for your frontend.

Services are just Go objects with methods on the form func (s Service) Method(ctx context.Context, input Input) (Output, error).

Github repository

Example

package main

import (
    "context"
    "net/http"
    "sync/atomic"

    "github.com/turborpc/turborpc"
)

type Counter atomic.Int64

func (c *Counter) Add(ctx context.Context, delta int64) (int64, error) {
    return (*atomic.Int64)(c).Add(delta), nil
}

func main() {
    rpc := turborpc.NewServer(turborpc.WithServerJavaScriptClient())

    _ = rpc.Register(&Counter{})

    http.Handle("/rpc", rpc)

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte(`
<!DOCTYPE html>
<html>
<head>
  <title>Counter</title>
  <script src="/rpc"></script>
</head>
<body>
  <strong id="count"></strong>
  <button id="plus">+</button>
  <button id="minus">-</button>
  <script>
    const rpc = new Counter("/rpc");

    const setCount = (v) => document.getElementById("count").innerText = v;
    document.getElementById("plus").onclick = () => rpc.add(1).then(setCount);
    document.getElementById("minus").onclick = () => rpc.add(-1).then(setCount);

    rpc.add(0).then(setCount);
  </script>
</body>
        `))
    })

    http.ListenAndServe(":3000", nil)
}

More examples