Modular web application template
Monorepo using pnpm workspace with modular packages shared across apps:
- apps/user-application - TanStack Start consumer-facing app
- apps/data-service - Backend service for long-running tasks
- packages/data-ops - Shared DB layer (schemas, queries, auth)
Stack:
Central shared package for all database operations. Both apps consume this package for type-safe DB access.
Purpose: Single source of truth for database schemas, queries, validations, and auth config.
Core database definitions using Drizzle ORM.
schema.ts- Main application tablesauth-schema.ts- Better Auth tables (auto-generated, don't edit manually)relations.ts- Drizzle relational queries config (defines joins between tables)migrations/{env}/- Migration history per environment (dev/staging/production)
Reusable database operations exported as functions.
Example: user.ts exports getUser()
Usage: Import and call from apps - handles DB connection internally via getDb().
import { getUser } from "data-ops/queries/user";
const user = await getUser(userId);Validation schemas using Zod.
- API request/response
- Forms
- DTOs
Naming conventions:
| Purpose | Suffix | Example |
|---|---|---|
| Domain model | Schema | UserSchema |
| Request | RequestSchema | UserCreateRequestSchema |
| Response | ResponseSchema | UserListResponseSchema |
| Type | no suffix | User, UserCreateInput |
Purpose: Type-safe contracts between frontend/backend. Validates data shape at runtime.
Example: user.ts exports UserSchema schema.
setup.ts- DB client initialization (getDb()function)seed/- Data seeding utilities
Better Auth configuration.
setup.ts- Auth config (providers, plugins)server.ts- Auth server instance
- Add table to
src/drizzle/schema.ts - Add relations to
src/drizzle/relations.ts(if needed) - Generate migration:
pnpm run drizzle:dev:generate - Apply migration:
pnpm run drizzle:dev:migrate - Create queries in
src/queries/{feature}.ts - Create Zod schemas in
src/zod-schema/{feature}.ts - Rebuild package:
pnpm run build:data-ops - Import in apps: Use queries/schemas from both apps:
pnpm run setupInstalls all dependencies and builds data-ops package.
pnpm run dev:user-application # TanStack Start app (port 3000)
pnpm run dev:data-service # Hono backend service (port 8788)From packages/data-ops/ directory:
pnpm run drizzle:dev:generate # Generate migration
pnpm run drizzle:dev:migrate # Apply to databaseReplace dev with staging or production. Migrations stored in src/drizzle/migrations/{env}/.
Config files in packages/data-ops/:
.env.dev- Local development.env.staging- Staging.env.production- Production
Replace devwithstagingorproduction`.
Migrations stored in src/drizzle/migrations/{env}/.
Sample .env file with minimum number of values available - .env.example
To deploy to a Cloudflare account different from the one globally logged in on your machine:
- Copy the example env file in the root directory:
cp .env.example .env
- Fill in
CLOUDFLARE_ACCOUNT_IDandCLOUDFLARE_API_TOKENwith values from the target account.
This overrides global Cloudflare credentials for deployments without changing your machine-wide config.
Once the deployment is done, Cloudflare will response with URL to view the deployment. If you want to change the name associated with Worker, do so by changing the name in the wrangler.jsonc file.
You can also use your own domain names associated with Cloudflare account by adding a route to this file as well.
pnpm run deploy:staging:user-applicationThis will deploy the user-application to Cloudflare Workers into staging environment.
pnpm run deploy:production:user-applicationThis will deploy the user-application to Cloudflare Workers into production environment.
Once the deployment is done, Cloudflare will response with URL to view the deployment. If you want to change the name associated with Worker, do so by changing the name in the wrangler.jsonc file.
You can also use your own domain names associated with Cloudflare account by adding a route to this file as well.
pnpm run deploy:staging:data-serviceThis will deploy the data-service to Cloudflare Workers into staging environment.
pnpm run deploy:production:data-serviceThis will deploy the data-service to Cloudflare Workers into production environment.