Project structure
Where things live, and the conventions each directory follows.
repository
grovia/
├── .env # the only local env file — every key commented
├── setup.js # first-run installer
├── turbo.json # build / dev / lint / type-check pipelines
├── pnpm-workspace.yaml # apps/*, e2e; native-script allowlist
├── apps/
│ ├── web/ # Next.js 16 storefront (:3000)
│ ├── admin/ # Next.js 16 dashboard + seller portal (:3001)
│ └── api/ # Express 5 REST API + worker (:8000)
│ └── data/demo/ # the demo store: collections, 244 images, manifest
├── e2e/ # Playwright end-to-end test
├── documentation/ # offline HTML help file
├── README.md · DEPLOYMENT.md · CHANGELOG.md · LICENSE
└── _.github/workflows/ # CI — rename to .github to switch it onapps/web
| Path | Role |
|---|---|
src/app/(storefront)/ | Every page with the header/footer chrome |
src/app/(auth)/ | Sign-in surfaces with a minimal layout — no nav to leave by |
src/app/api/auth/oauth/complete/ | Finishes a social sign-in: redeems the API's one-time ticket and sets the session cookie |
src/lib/api.ts | The only fetch layer for public reads |
src/lib/auth/ | Server actions, cookie, session, return-to |
src/data/catalog.ts · cms.ts | Typed reads mapped from API DTOs |
src/data/content.ts | What the API does not model: nav, FAQ, locales, delivery slots |
src/store/ | Zustand: user, cart, wishlist, ui, currency |
src/components/ui/ | shadcn primitives on Grovia tokens (lowercase filenames) |
src/proxy.ts | Next 16 middleware — cookie-presence check only |
apps/admin
| Path | Role |
|---|---|
src/app/(dashboard)/ | Every authenticated screen; [screen] serves the registry |
src/app/setup · signin · forbidden | Outside the dashboard group — no chrome |
src/lib/api-client.ts | apiList normalises the API's varied list envelopes |
src/data/resources.ts | The CRUD registry — a screen is a descriptor, not a page |
src/data/nav.ts | Sidebar information architecture |
apps/api
| Path | Role |
|---|---|
server.ts | Middleware stack, CORS allowlist, route mounts |
config/env.ts · roles.ts · uploadService.ts | Env loading, the role model, ImageKit/Cloudinary |
middleware/authMiddleware.ts | protect, admin, staff, authorize(...), optionalAuth |
models/ · controllers/ · routes/ | One trio per resource — brandModel / brandController / brandRoutes |
scripts/ | demoImport (pnpm run seed), demoExport, createAdmin, apiCheck, e2eReset, idempotent migrate:* scripts |
data/demo/ | The demo store: one JSON file per collection, the images, and a manifest |
tsconfig.build.json | What dist/ emits — excludes tests, scripts and *.check.ts |
Conventions
- Backend files are
camelCase; Next apps usePascalCasecomponents, lowercase route folders, and shadcn's lowercase names insidecomponents/ui/. apps/apiimports use.jsextensions even from.tssource (NodeNext ESM).- Next apps import from
@/*for everything undersrc/. - Two-space indent, double quotes, trailing commas, semicolons.