Greenacres Docs

Technical Architecture

Technical documentation covering the monorepo structure, packages, and deployment.

Technical Architecture

The Greenacres Coffee Platform is built as a modern TypeScript monorepo using TurboRepo and pnpm.

Monorepo Structure

coffee/
├── apps/
│   ├── web/          # Public site + Buyer Portal (Next.js)
│   ├── admin/        # Admin Dashboard (Next.js)
│   └── docs/         # Documentation (Fumadocs)
├── packages/
│   ├── ui/           # Shared UI components (Tailwind + Shadcn)
│   ├── auth/         # Authentication logic (Firebase)
│   ├── db/           # Database schemas and utilities
│   ├── types/        # Shared TypeScript types
│   └── config/       # Shared ESLint/TS configs
└── turbo.json        # TurboRepo configuration

Apps

Web (apps/web)

The public-facing Next.js application containing:

  • Marketing Pages: Homepage, About, Contact
  • Buyer Portal: Catalog, Coffee Details, Inquiries, Profile

Port: 3000

Admin (apps/admin)

Internal administration dashboard:

  • Dashboard: Metrics and overview
  • Products: Coffee CRUD operations
  • Inquiries: Request management
  • Users: Role and access management

Port: 3001

Packages

UI (packages/ui)

Shared component library built with:

  • Tailwind CSS: Utility-first styling
  • Shadcn/ui: Accessible component primitives
  • Lucide Icons: Icon library

Key components: Button, Card, Input, Modal, Table

Auth (packages/auth)

Firebase Authentication wrapper providing:

  • useAuth() hook for client components
  • signIn(), signUp(), signOut() methods
  • Role-based access control
  • Session persistence

DB (packages/db)

Firestore data access layer:

  • Collections: users, coffees, inquiries, locations
  • Functions: getCoffees, createInquiry, updateUserRole
  • Email: Mailtrap integration for transactional emails

Types (packages/types)

Shared TypeScript interfaces:

interface CoffeePricing {
  pricePerLb: number;
  quantity?: number;
  availability: 'in_stock' | 'pre_shipment' | 'out_of_stock';
  availabilityPeriod?: string;
  terms: string; // e.g., 'FOB' or 'EXW'
  incoterm?: string; // e.g., 'FOB', 'EXW', 'CIF', 'DAP'
  logisticsLocation?: string; // e.g., 'Djibouti', 'Genoa'
  paymentTerms?: string;
  updatedAt: Date;
}

interface Coffee {
  id: string;
  name: string;
  region: string;
  grade: number;
  // ...
  referenceCode?: string;
  isTopLot?: boolean;
  images?: string[];
  videos?: string[];
  pricing?: Record<'addisAbaba' | 'trieste' | 'genoa', CoffeePricing>;
}

interface Inquiry {
  id: string;
  userId: string;
  coffeeId: string;
  status: 'pending' | 'reviewed' | 'quoted' | 'completed';
  // ...
}

Data Mapping Strategy (Offer List)

The platform bridges the gap between conventional offline PDF offer lists and a digital catalog. Based on the client's PDF format, data maps to the Coffee model as follows:

Offer List FieldFirestore FieldNotes
Coffee Name / Descriptionname, region, grade, preparationParsed to create a standardized name.
Ref No.referenceCodeInternal tracking ID (e.g., ET-YG-W1-24).
Bag Size & Quantitypricing.*.quantity (in bags)Total bags available at a specific location.
Availability (Date/Status)pricing.*.availabilityPeriod & availabilitye.g., "Jan/Feb 2026" or "In Stock".
Incoterm & Locationpricing.*.incoterm & logisticsLocationDefines the specific delivery terms per location (e.g., FOB & Djibouti).
Payment Termspricing.*.paymentTermsTypically LC/CAD or similar.
Price / kg (or lb)pricing.*.pricePerLbBase unit price for calculations.

Note: The isTopLot boolean is generally derived manually or based on specific grade/SCA score thresholds.

Database

Firebase Firestore is used as the primary database.

Collections

CollectionDescription
usersUser profiles and roles
coffeesCoffee product catalog
inquiriesSample requests from buyers
locationsDelivery location pricing
emailQueueOutbound email queue

Security Rules

Located in firestore.rules:

  • Users can only read/write their own data
  • Admins have full access
  • Public read access for coffee catalog

Deployment

Vercel

The platform is designed for Vercel deployment:

# Deploy all apps
vercel deploy

# Deploy specific app
vercel deploy --cwd apps/web

Environment Variables

Required environment variables (see .env.production.example):

NEXT_PUBLIC_FIREBASE_API_KEY=...
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=...
NEXT_PUBLIC_FIREBASE_PROJECT_ID=...
FIREBASE_ADMIN_CLIENT_EMAIL=...
FIREBASE_ADMIN_PRIVATE_KEY=...
MAILTRAP_TOKEN=...

Testing

Vitest

Unit and integration tests using Vitest:

# Run all tests
pnpm test

# Run tests for specific package
pnpm --filter @greenacres/db test

Linting

ESLint configuration shared via packages/config:

# Lint all packages
pnpm lint

# Type check
pnpm typecheck

On this page