Repository root
chalo-kumbh/
├── apps/
│ ├── web/ # Next.js 15
│ ├── mobile/ # Expo (planned)
│ └── api/ # Node 20 + Hono
├── packages/
│ ├── ui/ # planned — bespoke web UI package
│ ├── db/ # Drizzle schema + migrations
│ ├── types/ # Shared TypeScript types
│ ├── validators/ # Zod — shared web + mobile + api
│ ├── config/ # planned — shared eslint/tsconfig/tailwind
│ └── utils/ # currency, dates, geo
├── docker/ # planned — see single-host-deployment.html
│ ├── Dockerfile.web
│ ├── Dockerfile.api
│ └── docker-compose.yml
├── .github/workflows/ # planned — CI/CD
│ ├── deploy-web.yml
│ ├── deploy-api.yml
│ └── mobile-eas.yml
├── turbo.json
├── package-lock.json
└── package.json
Design principles
-
Single Zod source —
packages/validatorsimported by API handlers and client forms. Avoidapps/api/src/validatorsduplicates that drift. -
Schema-driven types — Drizzle in
packages/db; export inferred types intopackages/typeswhere helpful. - Typed API client — Hono RPC client (or OpenAPI codegen) from a shared entry so web and mobile break compile-time if responses change.
-
Cart state — same Zustand logic on web and
mobile; persistence differs (
localStoragevs MMKV). -
UI package —
packages/uiis web-only: bespoke components and patterns from the cultural design language. Native screens stay inapps/mobilewith the same token roles. -
One Stripe webhook receiver — prefer
apps/apifor signature verification and idempotent state updates. Do not mirror the same webhook on Next unless there is an explicit forwarding reason.
Web app route groups
Next.js App Router groups isolate layouts and concerns:
(marketing)— public pages: home, about, gallery, contact.(booking)— packages, cart, checkout, confirmation.(auth)— login, register, OTP.(dashboard)— authenticated: my bookings, profile.-
app/api/— reserve for edge cases only (e.g. OAuth callbacks). Prefer Stripe webhooks on the Hono API.
Mobile (Expo Router)
File-based routes under apps/mobile/app/:
(tabs)/— home, packages, bookings, profile.packages/[slug].tsx— detail.booking/— cart, checkout, confirmation.auth/— login, register.
API application
Suggested layering under apps/api/src/:
routes/— HTTP surface, thin.controllers/— parse request, call services.services/— business rules, transactions.middleware/— auth, CORS, rate limit, logging.lib/db.ts— re-export from@chalo-kumbh/db(single pool).
Database connection
Instantiate Drizzle/Neon in one place (the db package or a single api import). Multiple ad-hoc connections cause pool exhaustion under load.