Search

Search Kavel...

Documentation menu

Project Structure

A Bun + Turbo monorepo: two Cloudflare Workers apps and the shared packages that tie them together.

text
my-app/
├── apps/
│   ├── api/                  Hono API on Cloudflare Workers
│   │   ├── src/
│   │   │   ├── db/           Drizzle schema + client
│   │   │   ├── lib/          integrations (auth, email, stripe…)
│   │   │   ├── orpc/         oRPC procedure implementations
│   │   │   └── index.ts      worker entry + routing
│   │   ├── migrations/       generated D1 migrations
│   │   └── wrangler.jsonc    Workers + D1 config
│   └── web/                  TanStack Start app on Workers
│       └── src/
│           ├── components/   UI + feature components
│           ├── routes/       file-based routes
│           └── paraglide/    generated i18n runtime
├── packages/
│   ├── backend-contract/     oRPC contract (shared types)
│   ├── ui/                   Base UI components + brand config
│   └── transactional/        react-email templates
├── messages/                 i18n message catalogs
└── turbo.json                task pipeline

Apps

  • apps/api: the Hono API worker. Routes live in src/index.ts; business logic is exposed as oRPC procedures in src/orpc. Data access uses Drizzle against D1.
  • apps/web: the TanStack Start web app, also a Worker. File-based routes in src/routes render server-side and hydrate on the client.

Packages

  • @my-app/backend-contract: the oRPC contract. It declares procedure inputs and outputs with Zod, and both apps depend on it, so a change to the contract is a compile error on both sides until fixed.
  • @my-app/ui: shared Base UI components, the global stylesheet, and your Config.brand settings.
  • @my-app/transactional: react-email templates, rendered to HTML by the email module.

Packages are namespaced under your project name. Import them with the alias, e.g. @my-app/ui/components/ui/button.

The oRPC contract flow

Adding an API endpoint touches three places, all fully typed:

  1. Declare the procedure in packages/backend-contract (name, Zod input/output).
  2. Implement it in apps/api/src/orpc.
  3. Call it from the web app through the typed backend client, autocomplete and type checking included.

Which folders exist depends on the modules you selected, see Modules.