Skip to content

Repository Structure

Purpose

This document defines the mono-repo strategy for the Farmer1st platform, optimized for AI-first development and enabling "demo in a box" for sales teams.

Current State

Decision: Single Mono-Repo

All code, infrastructure, and GitOps manifests live in one repository.

github.com/farmer1st/farmer1st

Rationale

Factor Why Mono-Repo Wins
AI-first development AI sees entire codebase; can reason about and modify related code atomically across services, apps, and infrastructure
Solo + AI team No team boundaries to isolate; multi-repo overhead provides no benefit
Atomic changes Change API + all consumers + deployment manifests in one commit
Demo in a box Sales clones one repo, runs docker compose up, has full working stack
Refactoring Rename a type → AI updates all references everywhere
No version hell Everything is always compatible; no cross-repo version matrix
Simpler onboarding One repo to clone, one set of tooling to learn

Trade-offs Accepted

Trade-off Mitigation
Larger repository Git is efficient; use sparse checkout if needed
Everyone sees everything CODEOWNERS + branch protection for sensitive paths
Deployment history mixed with code Git filtering, ArgoCD history, conventional commits
More complex CI Path-based triggers, affected detection tooling

Repository Structure

farmer1st/
│
├── apps/                               # Frontend applications
│   ├── farmer-pwa/                     # React PWA for farmers
│   │   ├── src/
│   │   ├── public/
│   │   ├── Dockerfile
│   │   ├── package.json
│   │   └── vite.config.ts
│   │
│   └── stakeholder-portal/             # React portal for stakeholders
│       ├── src/
│       ├── public/
│       ├── Dockerfile
│       ├── package.json
│       └── vite.config.ts
│
├── services/                           # Backend services (Python)
│   │
│   ├── user-management/                # User domain
│   │   ├── bff/                        # GraphQL BFF
│   │   │   ├── src/
│   │   │   ├── tests/
│   │   │   ├── Dockerfile
│   │   │   └── pyproject.toml
│   │   ├── auth-service/
│   │   │   ├── src/
│   │   │   ├── tests/
│   │   │   ├── Dockerfile
│   │   │   └── pyproject.toml
│   │   ├── profile-service/
│   │   └── preferences-service/
│   │
│   ├── access-management/              # Access/relationships domain
│   │   ├── bff/
│   │   ├── invitation-service/
│   │   ├── fga-service/
│   │   └── entity-service/
│   │
│   ├── surveys/                        # Surveys domain
│   │   ├── bff/
│   │   ├── survey-service/
│   │   ├── response-service/
│   │   └── analytics-service/
│   │
│   └── payments/                       # Payments domain
│       ├── bff/
│       ├── points-service/
│       ├── payout-service/
│       └── provider-service/
│
├── packages/                           # Shared code
│   ├── shared-types/                   # Cross-service TypeScript/Python types
│   ├── api-clients/                    # Generated API clients
│   ├── ui-components/                  # Shared React components
│   └── common-utils/                   # Shared utilities
│
├── platform/                           # Platform service configurations
│   ├── supertokens/                    # Auth server config
│   │   └── config.yaml
│   ├── openfga/                        # Authorization model
│   │   ├── model.fga
│   │   └── tuples/
│   ├── temporal/                       # Workflow definitions
│   │   └── ...
│   └── unleash/                        # Feature flag setup
│       └── ...
│
├── infra/                              # Infrastructure & deployment
│   │
│   ├── terraform/                      # Cloud infrastructure (IaC)
│   │   ├── modules/                    # Reusable TF modules
│   │   │   ├── vpc/
│   │   │   ├── eks/
│   │   │   ├── rds-postgresql/
│   │   │   ├── elasticache-redis/
│   │   │   ├── msk-kafka/
│   │   │   └── cloudflare-tunnel/
│   │   └── environments/               # Per-environment configs
│   │       ├── cloudflare/             # All CF resources
│   │       ├── aws-dev/
│   │       ├── aws-staging/
│   │       └── aws-prod/
│   │
│   ├── k8s/                            # GitOps manifests (Kustomize)
│   │   ├── base/                       # Base manifests
│   │   │   ├── user-management/
│   │   │   ├── access-management/
│   │   │   ├── surveys/
│   │   │   ├── payments/
│   │   │   └── platform/               # SuperTokens, OpenFGA, etc.
│   │   └── overlays/                   # Environment-specific
│   │       ├── local/                  # Local k8s (Kind/Minikube)
│   │       ├── dev/                    # farmer1st.dev
│   │       ├── staging/                # farmer1st.tech
│   │       └── prod/                   # farmer1st.org
│   │
│   └── docker/                         # Local dev Dockerfiles
│       ├── postgres/
│       ├── redis/
│       └── kafka/
│
├── tools/                              # Developer & sales tooling
│   │
│   ├── seed-data/                      # Demo data scenarios
│   │   ├── scenarios/
│   │   │   ├── cocoa-cooperative/      # West Africa cocoa coop demo
│   │   │   │   ├── users.json
│   │   │   │   ├── farms.json
│   │   │   │   ├── cooperatives.json
│   │   │   │   ├── relationships.json  # OpenFGA tuples
│   │   │   │   └── surveys.json
│   │   │   ├── coffee-brand/           # Coffee brand (Nestlé) demo
│   │   │   └── small-farm/             # Single farmer demo
│   │   └── seed.py                     # Seed script
│   │
│   └── scripts/                        # Dev utilities
│       ├── setup.sh                    # First-time setup
│       ├── reset-db.sh                 # Reset local databases
│       └── generate-clients.sh         # Generate API clients
│
├── .github/
│   ├── workflows/
│   │   ├── ci.yml                      # Lint, test, build
│   │   ├── deploy-dev.yml              # Auto-deploy to dev
│   │   ├── deploy-staging.yml          # Deploy to staging
│   │   └── deploy-prod.yml             # Deploy to prod (manual)
│   ├── CODEOWNERS                      # Protect sensitive paths
│   └── dependabot.yml
│
├── docker-compose.yml                  # 🎯 Full stack local dev
├── docker-compose.override.yml         # Local overrides (gitignored)
├── docker-compose.demo.yml             # Demo-specific config
├── Makefile                            # Common commands
├── README.md
├── CLAUDE.md                           # AI assistant instructions
└── .gitignore

Domain to Folder Mapping

Domain Folder K8s Namespace Purpose
User Management services/user-management/ user-management Users, auth, profiles, preferences
Access Management services/access-management/ access-management Invitations, relationships, OpenFGA
Surveys services/surveys/ surveys Survey creation, responses, analytics
Payments services/payments/ payments Points, payouts, payment providers

GitOps Strategy

Why GitOps Lives in the Mono-Repo

Benefit Description
AI context AI sees code + deployment manifests together
Atomic changes Code change + manifest update in one commit
No coordination No "which version of service X goes with which GitOps commit?"
Simpler CI One pipeline updates everything

ArgoCD Configuration

ArgoCD points to subfolders within the mono-repo:

# Example: ArgoCD Application for surveys in prod
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: surveys-prod
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/farmer1st/farmer1st.git
    targetRevision: main
    path: infra/k8s/overlays/prod/surveys
  destination:
    server: https://kubernetes.default.svc
    namespace: surveys
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Path Protection

Sensitive paths are protected via CODEOWNERS:

# .github/CODEOWNERS

# Production deployments require platform team approval
/infra/k8s/overlays/prod/       @farmer1st/platform-team
/infra/k8s/overlays/staging/    @farmer1st/platform-team

# Terraform changes require platform team approval
/infra/terraform/               @farmer1st/platform-team

# Platform services require platform team approval
/platform/                      @farmer1st/platform-team

Image Naming Convention

All container images go to GitHub Container Registry:

ghcr.io/farmer1st/farmer-pwa:v1.2.3
ghcr.io/farmer1st/stakeholder-portal:v1.2.3

ghcr.io/farmer1st/user-management-bff:v1.2.3
ghcr.io/farmer1st/auth-service:v1.2.3
ghcr.io/farmer1st/profile-service:v1.2.3

ghcr.io/farmer1st/surveys-bff:v1.2.3
ghcr.io/farmer1st/survey-service:v1.2.3
# ... etc

Local Development

See 12-local-development.md for the complete local development and demo strategy.

Quick start:

# Clone once
git clone git@github.com:farmer1st/farmer1st.git
cd farmer1st

# Start everything
make dev

# Or for sales demos
make demo scenario=cocoa-cooperative

CI/CD Flow

See 07-cicd-devops.md for complete CI/CD pipeline documentation.

High-level flow:

┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│   PR/Push    │────►│   CI Build   │────►│  Update k8s  │
│              │     │   & Test     │     │  overlays    │
└──────────────┘     └──────────────┘     └──────┬───────┘
                                                  │
                     ┌──────────────┐             │
                     │   ArgoCD     │◄────────────┘
                     │   Syncs      │
                     └──────────────┘

Migration from Multi-Repo

If migrating from existing multi-repo structure:

  1. Create new mono-repo with folder structure
  2. Use git subtree or fresh copy to bring in each repo
  3. Preserve meaningful git history where possible
  4. Update CI/CD pipelines
  5. Update ArgoCD application sources
  6. Archive old repositories

Open Questions

  • Mono-repo tooling: Nx vs Turborepo vs plain Make?
  • Python mono-repo tooling: uv workspaces?
  • Shared library versioning within mono-repo?
  • Branch strategy (trunk-based vs feature branches)?

Dependencies

  • GitHub organization with mono-repo
  • GHCR enabled for container images
  • ArgoCD configured per EKS cluster
  • Terraform Cloud workspaces

Last Updated: 2025-12-30