ARCHE
FamiliesDocsExamplesBlogGitHub ↗
← All posts
May 5, 2026technical2 min read

Prisma → tRPC → UI without hand-waved types

How server modules, the client package, and the web app share one contract.

The TypeScript fullstack preset’s superpower is not “full stack”—it is one type graph from the database outward. Arche wires the folders so you do not accidentally put routers in the wrong package.

The pipeline

terminal
packages/store     Prisma schema + client
       ↓
apps/server        modules/*/*.trpc.ts (procedures)
       ↓
packages/trpc      AppRouter types + createCaller (client-only)
       ↓
apps/web           trpc client + trpcCaller (RSC)

Common mistake: routers in packages/trpc

packages/trpc re-exports types. Procedures live in:

terminal
apps/server/src/modules/<feature>/*.trpc.ts

composed in apps/server/src/modules/trpc/app.router.ts.

If you define routers in packages/trpc, you pull server dependencies into the wrong layer and fight the bundle. The tRPC package doc states this loudly for a reason.

Server-side data fetching (no HTTP loopback)

terminal
const api = await trpcCaller()
const posts = await api.posts.list()

trpcCaller uses createCaller in-process—good for RSC and server actions.

Client-side fetching

terminal
trpc.posts.list.useQuery()

HTTP to NEXT_PUBLIC_API_URL with the shared AppRouter type.

Validation lives with procedures

Zod (or shared validators) at procedure boundaries. Services hold business logic; repositories touch Prisma; policies answer authorization. The Architecture page describes module layout.

When types lie

Types are only honest if you:

  • Run db:generate after schema changes
  • Rebuild server before trusting web types in CI
  • Do not cast around AppRouter with any

Arche gives you the graph—you still have to run the tasks.

Beyond TypeScript

Rust fullstack uses explicit API boundaries instead of tRPC. Convex uses its client. The “glue” idea transfers: one contract surface, thin apps.

Start here: Getting started and scaffold:

terminal
bun run dev:cli -- my-app --yes --preset=typescript-fullstack

KitsuneKode

Maintains Arche

All posts