Repository overview
How the Africa OS monorepo is organized - apps, platform packages, application modules, shared packages, and tooling.
Africa OS is a pnpm workspace monorepo. Every app, platform package, and application module is a package in the same repository, versioned together and built with shared tooling. This page explains how the pieces fit together.
The workspace map
africaos/
├── apps/ stand-alone deployable applications
├── platform/ shared platform packages (backend of record)
├── packages/
│ ├── applications/ installable application modules (the verticals)
│ └── ... shared frontend and core packages
├── tooling/ shared toolchain configuration
├── infra/ infrastructure, migrations, and database scripts
├── .patterns/ documentation and contribution standards
├── docs/ high-level architecture notes
├── nx.json Nx task orchestration
├── pnpm-workspace.yaml workspace definition and package catalog
└── package.json root scripts and shared dependencies
The workspace is declared in pnpm-workspace.yaml, which lists five globs:
packages:
- apps/*
- platform/*
- packages/*
- packages/applications/*
- tooling/*
apps/ - the deployables
These are the actual runnable applications. Only two are production-facing today; the rest are supporting or experimental.
| Package | Purpose |
|---|---|
@africaos/web |
The unified shell. A TanStack Start app that mounts every application module under an organization. This is the main product surface. |
@africaos/admin |
The admin console. A TanStack Start app for platform operations - reviewing organizations, managing the tenant lifecycle. |
@africaos/landing |
The public marketing site (TanStack Start). |
@africaos/checkback |
A small Next.js teaser/waitlist site. |
@africaos/desktop |
A Tauri v2 desktop wrapper around the web app. |
@africaos/documentation |
A separate Next.js + Fumadocs site (the older docs, superseded by the Blume knowledgebase). |
@africaos/demo |
A scratch app for trying TanStack patterns; not part of the platform. |
knowledgebase |
This documentation site, built with Blume. |
platform/ - the platform packages
These packages implement the cross-cutting platform concerns. They are the source of truth for how the system behaves. They depend on Effect and on each other, but never on application modules or on any app.
| Package | Responsibility |
|---|---|
@africaos/database |
The single gateway to PostgreSQL. Effect service over @effect/sql-pg with scoping helpers and transactions. |
@africaos/auth |
Identity and authentication. Wraps Better Auth in an Effect service; owns the only import of better-auth in the repo. |
@africaos/organizations |
The multi-tenant model: organizations, their lifecycle, memberships, and the application registry. |
@africaos/permissions |
Capability-based authorization. Permissions are application.resource.action strings. |
@africaos/request-context |
Builds the Effect runtime for one HTTP request and resolves the caller’s identity, organization, and permissions. |
@africaos/admin-auth |
Identity for the admin console, using a separate admin database schema. |
@africaos/notifications, @africaos/offline, @africaos/sdk, @africaos/search, @africaos/storage |
Placeholder packages. They exist as workspace members for future work; their index.ts exports nothing yet. |
packages/applications/ - the application modules
These are the industry verticals. Each is a self-describing module that registers itself with the platform and renders inside the unified shell. Every module has an app.config.ts that declares its metadata and capabilities.
| Package | Status |
|---|---|
@africaos/retail |
The reference implementation. Full feature: products, server functions, hooks, routes. Read this first. |
@africaos/agriculture, @africaos/government, @africaos/hospital, @africaos/logistics, @africaos/sacco, @africaos/school |
Shell modules with placeholder pages, waiting for their domains to be built. |
@africaos/shell |
Not a vertical itself - the shared shell machinery that every application module uses to mount itself. |
packages/ - shared packages
| Package | Purpose |
|---|---|
@africaos/config |
Central configuration: validated environment variables, constants, and feature flags. |
@africaos/logger |
Effect-based structured logging used across the platform. |
@africaos/ui |
The shared React component library used by the web app and application modules. |
@africaos/charts, @africaos/forms, @africaos/icons, @africaos/tables |
Reserved packages for shared chart, form, icon, and table primitives. Currently empty stubs. |
@africaos/utils, @africaos/validation |
Reserved utility and validation packages. Currently empty stubs. |
tooling/ and infra/
tooling/typescript(@africaos/typescript-config) - the sharedtsconfigbase every package extends.infra/database- everything about the database: SQL migrations, the seed datasets, and thetsxscripts (migrate.ts,seed.ts,register-apps.ts, and friends) thatpnpm db:*commands run.
How packages reference each other
Workspace packages are imported by name using the @africaos/* scope, and pnpm links them together from pnpm-workspace.yaml. Dependency versions in package.json are written as workspace:*, which pnpm resolves to the local package:
{
"dependencies": {
"@africaos/request-context": "workspace:*",
"@africaos/retail": "workspace:*"
}
}
Two versions of the same dependency may be pinned through the catalog: key in pnpm-workspace.yaml. Vite and vitest are cataloged there, so packages that need them declare vite: "catalog:" rather than repeating a version.
Dependency rules of thumb
The dependency graph is intentionally layered, and keeping it clean matters:
- apps depend on platform packages and application modules. The web app is the composition root: it wires the request context, the application registry, and the shell together.
- application modules depend on the shell, ui, and platform packages. They should not depend on the web app.
- platform packages depend on each other but never on apps or application modules.
- Nobody depends on the placeholder packages until they ship something real.
This layering keeps each application module swappable and keeps the platform independent of any single vertical.
Next steps
Now that you can find your way around, the Architecture section explains how the pieces behave at runtime.