ByteBite Docs
Architecture

Monorepo Structure

Current bootstrap layout vs intended architecture as features are added.

Status: Accepted

Goal

ByteBite uses a TypeScript monorepo with clear boundaries between deployable applications, shared packages, infrastructure, and documentation.

The structure is optimized for:

  • independent deployments
  • strict separation of frontend and backend responsibilities
  • shared schemas and domain logic
  • Docker-based development and production
  • straightforward future extraction of services only when justified

Current structure

This is what exists now. Product slices: Tenant → Restaurant → Domain → Storefront, Menu → Storefront, Cart → Storefront, Checkout → Order, Accept / Reject + timeout, Kitchen → Status, Menu → Object Storage, Restaurant → weekly opening hours, Hours → Checkout-Gate, Auth → Login, Auth → Dashboard-Gate, Notifications → SMS/E-Mail clients, Notifications → Order-Events (SMS on accept, reject, timeout, ready), then Delivery → Zones + checkout, then Menu → Sizes, then Order pause, then Restaurant → profile. Payments are not implemented. Dashboard mutations still use the path (ADR-021); session.restaurantId is not this slice. /dashboard/* requires a staff session.

Empty feature folders are not created in advance. Modules are added when the feature exists.

bytebite/
├── apps/
│   ├── landing/             # Next.js: public Coming Soon page for the apex host
│   ├── storefront/          # Next.js App Router: tenant storefront + menu + cart + checkout + confirmation
│   ├── dashboard/           # Vite SPA + weekly hours + logo + menu CRUD + media uploads + accept/reject + kitchen + delivery zones + staff login gate + /admin placeholder
│   ├── api/                 # Fastify: health, tenant plugin, Better Auth /auth, storefront menu/cart/checkout/hours + dashboard menu/orders/hours/uploads + timeout scheduler + optional Twilio status stub
│   └── docs/                # Fumadocs (canonical documentation)
├── packages/
│   ├── db/                  # Drizzle client, restaurants, domains, menu + cart + order + hours + Better Auth tables, migrations, seeds
│   ├── domain/              # Hostname, tenant context, menu visibility, storage keys, cart/checkout/accept/kitchen/hours rules, order/payment/delivery/notification vocab, staff session shape
│   ├── auth/                # Better Auth factory, STAFF_ROLES, session shape (userId, role)
│   ├── schemas/             # Shared Zod contracts (health, storefront, menu, cart, order, hours, auth)
│   ├── types/               # Brands / staff roles not inferred from Zod
│   ├── config/              # parseEnv + base env schema
│   ├── observability/       # pino + Sentry init
│   └── notifications/       # Twilio SMS + SES e-mail clients (SMS on accept/reject/timeout/ready; no-op without credentials)
├── infrastructure/
│   ├── docker/              # App Dockerfiles (dev + prod targets)
│   ├── traefik/dev/         # Local file-provider routing
│   ├── traefik/prod/        # Placeholder for Dokploy Traefik
│   ├── dokploy/             # Placeholder
│   └── scripts/             # Placeholder
├── compose.yml
├── compose.dev.yml
└── README.md

API modules that exist

  • apps/api/src/modules/health/ — /health, /health/db
  • apps/api/src/modules/storefront/ — restaurant, menu, cart, checkout, and hours routes
  • apps/api/src/modules/menu/ — catalog queries and mutations
  • apps/api/src/modules/cart/ — guest cart queries and mutations
  • apps/api/src/modules/hours/ — weekly opening-window queries and atomic replace
  • apps/api/src/modules/profile/ — public restaurant profile read and replace
  • apps/api/src/modules/delivery/ — zones, suggestions, quote, Mapbox address provider
  • apps/api/src/modules/orders/ — checkout snapshot (hours-gated, pickup or delivery), tenant-scoped order reads, accept/reject, kitchen status, timeout tick, transactional SMS on accept/reject/timeout/ready
  • apps/api/src/modules/notifications/ — optional POST /webhooks/twilio/status stub (no order writes)
  • apps/api/src/modules/dashboard/ — operator menu CRUD, media uploads, hours, order accept/reject, and kitchen writes (ADR-021 path context)
  • apps/api/src/modules/media/ — object-storage upload helper and GET /media/*
  • apps/api/src/plugins/auth.ts — Better Auth handler at /auth/* (browser /api/auth/*)
  • apps/api/src/plugins/dashboard-auth.ts — staff session required for /dashboard/* (401 without a cookie)
  • apps/api/src/modules/tenancy/ — hostname lookup against restaurant_domains

What is explicitly not implemented yet

  • session.restaurantId cutover (path remains tenant authority)
  • Customer accounts
  • Payments, realtime, checkout SMS, e-mail sends (no customer_email on orders)
  • Menu extras and allergens (sizes are in Menu sizes)
  • Custom-domain verification / onboarding UI
  • Staging/production B2 media and CDN

Intended structure as features are added

The following is target architecture. Do not treat it as a file checklist of the current repo.

As slices land, expect feature modules under the API (modules/restaurants, modules/domains, …), Storefront app/ + features/, Dashboard src/features/, and Drizzle tables under packages/db/src/schema/. Integrations (Stripe, Twilio, SES, Mapbox, object storage) stay backend-side, out of packages/domain.

Dashboard routing lives at apps/dashboard/src/app/router.tsx (not a src/routes/ tree).

A future apps/admin or packages/ui extraction is allowed only when actual complexity or duplication justifies it. Neither exists today, by design.

Boundaries

Storefront

Next.js for SSR, SEO, tenant branding, menu, cart, checkout, account and tracking UI. It calls the API (same-origin /api in the browser) and does not own ByteBite business rules.

Dashboard

React + Vite SPA for restaurant operations and the initial ADMIN area. shadcn/ui lives directly under apps/dashboard/src/components/ui. Browser API calls use same-origin /api.

API

Fastify is the central backend and business-logic application layer. Integrations with Stripe, Twilio, AWS SES, Mapbox and object storage stay backend-side.

Docs

Fumadocs is the only maintained documentation source (apps/docs/content/docs). Development uses docs.bytebite.test; production will use docs.getbytebite.co behind Traefik BasicAuth.

Shared packages

  • packages/domain: framework-independent business rules
  • packages/db: Drizzle schema, migrations, client and seeds
  • packages/schemas: shared Zod contracts
  • packages/auth: Better Auth factory, roles, staff session shape (userId, role; no session.restaurantId)
  • packages/types: only types not sensibly inferred from schemas
  • packages/config: shared config conventions
  • packages/observability: logging/Sentry
  • packages/notifications: Twilio SMS + AWS SES clients (optional env; SMS from accept/reject/timeout/ready; e-mail unused)

Explicit decisions

  • No packages/ui initially.
  • Dashboard uses shadcn/ui locally.
  • Storefront owns its own UI components.
  • ADMIN starts as a protected section of Dashboard.
  • Backend structure is feature/domain oriented.
  • A future apps/admin or packages/ui extraction is allowed only when actual complexity or duplication justifies it.

On this page