Svelte + Fastify + tRPC monorepo (TypeScript) using pnpm workspaces.
Franz, this is the starter you can reuse for your own projects. The repo gives you a clean split between a web client (Svelte + Vite) and an API server (Fastify + tRPC) with shared type safety via generated types.
npm i -g pnpm
)pnpm install
pnpm dev
pnpm -r --filter ./frontend --filter ./backend build
pnpm --filter ./backend start
.
├─ backend/
│ ├─ server.ts # Fastify bootstrap + tRPC mount + static files
│ └─ src/
│ ├─ router.ts # appRouter: greeting, auth, etc.
│ ├─ routes/auth.ts # login/logout, cookie management
│ ├─ context.ts # request context (cookies, session)
│ ├─ sessions.ts # in-memory session store
│ └─ env.ts # productionMode flag
├─ frontend/
│ └─ src/
│ ├─ lib/client.ts # tRPC client pointed at /api
│ ├─ App.svelte # demo calls to the API
│ └─ env.ts # simple dev/prod flag
└─ pnpm-workspace.yaml # declares frontend and backend packages
/api
in the backend. In dev, Vite proxies /api
to http://localhost:3000
so you can call /api
from the Svelte app without worrying about CORS. In prod, Fastify serves the built frontend and the API under the same origin.http://localhost:5173
and http://127.0.0.1:5173
. Safari’s localhost cookie quirk is handled automatically.pnpm --filter ./backend dev
(or start
for prod).http://<your-mac-ip>:3000/api
from your device/simulator.URLSession
out of the box if you keep the same base URL and allow default cookie storage.backend/src/routes/auth.ts
and backend/src/context.ts
for tokens; the rest of the stack stays the same.backend/src/router.ts
(or create a new file in backend/src/routes/
and include it in appRouter
).name
fields in frontend/package.json
and backend/package.json
).backend/src/routes/auth.ts
with your real logic.rm -rf .git && git init
to start fresh.pnpm install
pnpm dev
pnpm -r --filter ./frontend --filter ./backend build
pnpm --filter ./backend start
If anything feels unfamiliar, ping me—happy to tailor this to your next app, Franz.