We often are asked how Bridge is different from trpc. They can be splitted into 2 differents branches: differences at client level and server level.
The way you would consume the client
Bridge Studio (the tool used to build the SDK of a Bridge api) is a more traditional REST codegen app. It's way of functioning is closer to something like Graphql codegen or OpenAPI Generator.
tRPC on the other hand lets you see real-time updated of your servers's routes and types. It has no build or compile steps, meaning no code generation, runtime bloat or build step. It makes it a great choice when building app as a full stack developer as everything is close.
This difference leads to other significant variances:
- tRPC couples your server & website/app more tightly: you're less likely to have missmatched versions between your server/client
- tRPC requires the backend and frontend code on the same machine (thus making it great for monorepos!)
- because it's less coupled than tRPC, Bridge lets you build any public-faced API (meant to be used by other external developers). It can be published as an NPM package.
- Bridge can build SDK in more languages. It's great for apps that have different (or multiple) languages between frontend and backend.
The way you would write your server
We can highlight some other differences in the synthax used to write your sever code.
Bridge relies more on objects while tRPC is more functional (it uses function chaining). OOP can be used with Bridge. Here is the same request with Bridge (a handler) and tRPC (a procedure).
Bridge:
ts
import { z } from "zod"import { handler } from 'bridge';const helloHandler = handler({body: z.object({ name: z.string() }),resolve: ({ body }) => `Hello ${body.name}`})
ts
import { z } from "zod"import { handler } from 'bridge';const helloHandler = handler({body: z.object({ name: z.string() }),resolve: ({ body }) => `Hello ${body.name}`})
Trpc:
ts
import { initTRPC, router } from '@trpc/server';import { z } from "zod";const appRouter = router({greet: publicProcedure.input(z.object({ name: z.string() })).query(({ input }) => ({ greeting: `hello, ${input}!` })),});
ts
import { initTRPC, router } from '@trpc/server';import { z } from "zod";const appRouter = router({greet: publicProcedure.input(z.object({ name: z.string() })).query(({ input }) => ({ greeting: `hello, ${input}!` })),});
Moreover, Bridge can be used with classes (for those who like object-oriented programmation) and its capabilities (like inheritance or polymorphisms).
ts
class Session {login: handler({// ...})}// the user class now inherits the "login" handler from the sessionclass User extends Session {getUser = handler({//...})}const routes = {// ...user: new User(),// ...}
ts
class Session {login: handler({// ...})}// the user class now inherits the "login" handler from the sessionclass User extends Session {getUser = handler({//...})}const routes = {// ...user: new User(),// ...}