ASAgriSense/Docs/Monorepo Structure

Architecture

Monorepo Structure

Workspace layout#

The repo uses npm workspaces with Turborepo for task orchestration. Four top-level workspace roots:

text
commodity-management-platform/
├── apps/               ← concrete entrypoints (Next.js, Hono API, Docs)
│   ├── web/            ← Next.js 16 product frontend  (port 3000)
│   ├── api/            ← Hono.js on Cloudflare Workers (port 8788)
│   └── docs/           ← This docs site               (port 3001)
│
├── be-packages/        ← backend feature modules (8 packages)
│   ├── feature-dashboard/
│   ├── feature-sms-settings/
│   ├── feature-farmer-registry/
│   ├── feature-farm-mapping/
│   ├── feature-deforestation-risk/
│   ├── feature-sustainability-programs/
│   ├── feature-surveys/
│   └── feature-eudr-compliance/
│
├── fe-packages/        ← frontend feature modules (8 packages)
│   ├── feature-auth/
│   ├── feature-sms-settings-web/
│   ├── feature-farmer-registry-web/
│   ├── feature-farm-mapping-web/
│   ├── feature-deforestation-risk-web/
│   ├── feature-sustainability-programs-web/
│   ├── feature-surveys-web/
│   └── feature-eudr-compliance-web/
│
└── shared/             ← cross-cutting packages (9 packages)
    ├── ui/
    ├── brand/
    ├── validation/
    ├── auth-permissions/
    ├── dashboard-contracts/
    ├── eudr-compliance-contracts/
    ├── swr-config/
    ├── typescript-config/
    └── eslint-config/

Boundary rules#

These rules are enforced by TypeScript path aliases and ESLint import rules. Running npm run typecheck from the root will catch any violation.

WorkspaceMay importMust not import
apps/webfe-packages/*, shared/*be-packages/* (no server code in the browser bundle)
apps/apibe-packages/*, shared/*fe-packages/* (no React in the edge worker)
fe-packages/*shared/* onlyapps/*, be-packages/*, other fe-packages/*
be-packages/*shared/* onlyapps/*, fe-packages/*, other be-packages/*
shared/*Other shared/* (with care)apps/*, be-packages/*, fe-packages/*

The four rules in plain English#

  • Apps orchestrate routing, layouts, and auth boundaries — they do not contain business logic.
  • Backend and frontend feature packages own domain behaviour. Each feature package is independently versioned and tested.
  • Shared packages expose UI primitives, brand tokens, validation schemas, and tooling — no feature logic.
  • API endpoints consume package contracts (schemas, service functions) instead of duplicating them.

Package placement guide#

If your code…Place it in
Code that accesses the database or calls external APIsbe-packages/feature-<domain>
React components or hooks for a featurefe-packages/feature-<domain>-web
Zod schemas or TypeScript types shared between API and webshared/<domain>-contracts
Cross-cutting validation (not domain-specific)shared/validation
Reusable React UI primitives (no feature logic)shared/ui
Design tokens, brand CSS, ThemeProvidershared/brand

Naming conventions#

Package typeConventionExample
Backend featurefeature-<domain>@repo/feature-farmer-registry
Frontend featurefeature-<domain>-web@repo/feature-farmer-registry-web
Shared contracts<domain>-contracts@repo/eudr-compliance-contracts
Shared utilitydescriptive noun@repo/auth-permissions

Turborepo task graph#

turbo.json defines the pipeline. Key task relationships:

TaskDepends onNotes
buildbuild (deps)Each package builds after its dependencies are built.
dev— (parallel)All dev servers start in parallel.
lintRuns ESLint independently per workspace.
typecheckbuild (deps)Needs declaration files from upstream packages.
testbuild (deps)Vitest runs after the package is built.
Deep imports are forbidden
Always import from the package barrel: import { EnrollmentWizard } from '@repo/feature-farmer-registry-web'. Never use deep paths like @repo/feature-farmer-registry-web/src/components/EnrollmentWizard. The barrel is the public API contract.

Internal package structure#

Each backend feature package follows the same internal layout:

text
be-packages/feature-<domain>/
└── src/
    ├── db/         ← Drizzle ORM schema and connection helpers
    ├── schema/     ← Zod validation schemas and inferred types
    ├── services/   ← pure business logic (no HTTP, no framework)
    ├── routes/     ← Hono route handlers (thin: validate → call service)
    └── index.ts    ← barrel export

Each frontend feature package:

text
fe-packages/feature-<domain>-web/
└── src/
    ├── components/ ← React components
    ├── hooks/      ← SWR-based data fetching hooks
    ├── services/   ← API client helpers (fetch wrappers)
    ├── types.ts    ← TypeScript types specific to this package
    └── index.ts    ← barrel export