Skip to content

Project structure

How the BabyMart monorepo is laid out, the root scripts, Turborepo tasks, CI, and how this docs site is built.

BabyMart is one repository with five apps (four products plus these docs) and three shared packages. pnpm links them together as a workspace, and Turborepo runs their tasks in the right order and caches the results. To see how the apps talk to each other at runtime, read the Architecture overview.

  • Directoryapps/
    • Directoryweb/ Storefront: Next.js 16 App Router (port 3000)
      • Directoryapp/ routes, layouts, API route handlers
        • …
      • Directorycomponents/
        • …
      • Directorylib/ API helpers, stores, Stripe and Firebase clients
        • …
      • proxy.ts route protection for /user, /auth and /success
    • Directoryadmin/ Admin dashboard: Vite + React (port 5173)
      • Directorysrc/pages/ dashboard pages
        • …
      • Directorysrc/components/
        • …
      • vercel.json
    • Directoryapi/ API: Express 5 + Mongoose (port 8000)
      • server.ts entry point
      • src/app.ts middleware and route mounting
      • Directorysrc/modules/ one folder per domain (auth, orders, payments…)
        • …
      • Directorymodels/ Mongoose models
        • …
      • Directoryroutes/ controllers/ legacy domains not yet moved into modules
        • …
      • Directoryscripts/ seed and maintenance scripts
        • …
      • Directorytests/ Vitest + in-memory MongoDB
        • …
    • Directorymobile/ React Native 0.88 app, outside the pnpm workspace
      • …
    • Directorydocs/ This site: Astro + Starlight (port 3002)
      • …
  • Directorypackages/
    • Directorytypes/ @babyshop/types: shared TypeScript interfaces
      • …
    • Directoryui/ @babyshop/ui: components, design tokens, BrandLogo
      • …
    • Directoryconfig/ @babyshop/config: API, payment and app constants
      • …
  • Directoryscripts/ seed-data.js and export-data.js for the demo catalogue
    • …
  • Directorycollection/ POSTMAN_COLLECTION.json
    • …
  • Directoryfunctions/ Firebase Cloud Functions (order emails); no app calls them
    • …
  • Directorydataconnect/ Firebase Data Connect scaffold; not used by the apps
    • …
  • Directoryimages/ source images for the catalogue seed scripts
    • …
  • Directorydocs/ older Markdown guides (SETUP, BASICS, PRODUCTION_READY…)
    • …
  • package.json root scripts
  • pnpm-workspace.yaml apps/, packages/, !apps/mobile
  • turbo.json task pipeline

The shared packages are explained on Shared packages, and each app has its own page under Apps.

Run these from the repository root with pnpm <script>. They are defined in package.json.

Script What it does
pnpm dev Starts the storefront, admin, API and docs in parallel.
pnpm dev:web / dev:admin / dev:api / dev:docs Starts one app.
pnpm dev:all Runs dev in every workspace package.
pnpm build Builds every package and app with Turborepo.
pnpm build:packages Builds only @babyshop/types, @babyshop/ui and @babyshop/config.
pnpm run setup pnpm install, then build:packages.
pnpm type-check Runs TypeScript in every package.
pnpm lint Runs ESLint in every package.
pnpm test Runs the Vitest suites (API, storefront, admin).
pnpm format Prettier on every .ts, .tsx and .md file.
pnpm clean Deletes build output (.next, dist).
pnpm webhook:web Forwards Stripe events to the storefront’s /api/stripe-webhook.
pnpm webhook:api Forwards Stripe events to the API’s /api/payments/webhook.

| pnpm mobile:install | npm install inside apps/mobile (the app is outside the pnpm workspace). | | pnpm dev:mobile / pnpm ios / pnpm android | The mobile app’s start, ios and android npm scripts. |

turbo.json defines how tasks depend on each other:

Task Depends on Cached Notes
build ^build (the packages it imports build first) Yes Outputs .next/**, dist/**, build/**. Env vars that change the build (NEXT_PUBLIC_*, VITE_*, Stripe and Firebase keys) are part of the cache key.
dev — No Long-running (persistent).
start build No Runs the production servers.
lint, test, type-check ^build Yes Shared packages build first, so dist/ types exist.
clean — No

^build is why @babyshop/types builds before the storefront: the storefront imports its compiled output.

Two GitHub Actions workflows live in .github/workflows/:

  • ci.yml runs on every push to main, on pull requests, and on demand. It uses Node 22, then runs pnpm install --frozen-lockfile, type-check, lint, test, build and pnpm audit --audit-level high.
  • deploy.yml deploys the storefront to Vercel with the Vercel CLI when apps/web, the lockfile, package.json or turbo.json change on main. It needs the VERCEL_ORG_ID, VERCEL_PROJECT_ID and VERCEL_TOKEN repository secrets.

CI does not test the mobile app, because it is outside the workspace.

The docs app (apps/docs, package @babyshop/docs) is an Astro site built on the Starlight docs theme, with Tailwind CSS v4 and shadcn/ui components.

  • Pages are MDX files in apps/docs/src/content/docs/. Each file’s path is its URL.
  • apps/docs/site.config.mjs holds everything specific to BabyMart: the title, logo, header sections, landing-page hero, ⌘K suggestions and sidebar order. To add a page, create the .mdx file, then add its slug to sidebar.
  • apps/docs/WRITING_GUIDE.md sets the voice, the page template and the naming rules that every page follows.
  • Search is a ⌘K palette over every heading. It is built at /search-index.json, so it also works in pnpm dev:docs.
Terminal window
pnpm dev:docs # http://localhost:3002
pnpm --filter @babyshop/docs build # static site in apps/docs/dist
pnpm --filter @babyshop/docs check # type-check the docs