Monorepo RFC 001 area first directory structure

RFC001 — AreaFirst Directory Structure

Field Value
Status *ccepted*(20260416)
Author(s) Rodrigo (with Claude as scribe)
Date 20260416
Affects All modules in apps/, platform/; top-level monorepo structure
Depends on docs/stack/areas.md, docs/stack/engine-product-pattern.md

1. Summary

Replace the current technologybased toplevel directories (apps/, platform/) with Area-based directories that match the 9 competency areas of the Koder Stack. Within each Area, every product becomes its own root directory containing all distribution forms (platform/, app/mobile/, app/desktop/, app/tv/) as subdirectories.


2. Problem

The current monorepo top-level mixes two incompatible classification criteria:

apps/        ← technology (Flutter)
platform/    ← technology (Go / SaaS)
ai/          ← area
infra/       ← area
observe/     ← area
data/        ← area

This inconsistency causes three recurring problems:

2.1 Products split across two directories

A product with a SaaS backend and a Flutter app ends up in two separate directories with no formal relationship between them:

platform/kmail/   ← SaaS webmail backend
apps/kmail/       ← (hypothetical) Flutter client

These cannot coexist with the same name under the current structure (names must be unique across the monorepo), forcing either a naming collision or a confusing suffix like kmail-mobile.

2.2 The classification question has no clear answer

When creating a new module, the question "does this go in apps/ or platform/?" has no clean answer for products that are simultaneously a SaaS backend and an installable app. The existing docs define:

  • apps/ = "Aplicações com UI (Dart/Flutter, desktop, mobile)"
  • platform/ = "Produtos e backends SaaS"

A product that is both — a webmail that Koder hosts and a native app users install — fits neither cleanly.

2.3 Distribution form is not the same as product identity

apps/ and platform/ classify by how something is delivered, not what it is. As products gain new distribution forms (SaaS → self-hosted → mobile → TV), the classification becomes arbitrary. The same product must live in multiple directories or the directory loses its meaning.


3. Proposal

3.1 Dissolve apps/ and platform/

Remove apps/ and platform/ as top-level directories. Their contents move to Area directories (see §3.2).

3.2 Introduce Area directories for products

Create four new top-level directories corresponding to the Koder Stack Areas that contain products (as opposed to infrastructure):

New directory Covers
foundation/ Identity, payments, billing, security — cross-cutting capabilities
suite/ End-user productivity: email, storage, design, messaging, calendar
devplatform/ Developer tools: forge, terminal, IDE, package registry
vertical/ Vertical solutions: fintech, health, legal, agro, education

The existing infrastructure Area directories remain unchanged:

Directory Stays as-is
ai/ AI infrastructure (gateway, runtime, voice, RAG, eval)
infra/ Network, security, edge, fleet, DNS
observe/ Monitoring, logging, APM, uptime
data/ Databases, queues, search
core/ Shared libraries and services
sdk/ SDKs (Go, JS, Python, Dart)
lang/ Koder Koda and KMD
linux/ Koder Linux distro and desktop
brand/ Brand assets
docs/ Documentation
context/ Configuration, specs, policies

3.3 Product-root structure

Within each Area directory, every product gets a single root directory. All distribution forms live inside that root as subdirectories:

<area>/<product>/
├── platform/        ← SaaS backend (Go). Koder hosts this.
├── app/
│   ├── mobile/      ← Flutter: Android + iOS
│   ├── desktop/     ← Flutter: Linux + macOS + Windows
│   ├── tv/          ← JavaScript: TizenOS + WebOS
│   └── web/         ← Self-hosted web frontend (if applicable)
└── site/            ← Landing page

Rules:

  • Not every product needs every subdirectory. A pure SaaS product has only platform/.

    A pure mobile app has only app/mobile/. Add subdirectories only when the distribution form actually exists or is actively planned.

  • platform/ inside a product root is the Go backend (SaaS or self-hosted server).

    It is not the same as the old top-level platform/ directory.

  • app/mobile/ and app/desktop/ are each independent Flutter projects

    (pubspec.yaml at their respective roots), allowing different UI layouts while sharing business logic via a shared/ Dart package when needed.

  • site/ is the product landing page, following the existing rule that landing pages

    live inside the product repo.

3.4 Engine + product pairs

When a product follows the engine + product split pattern, both the engine and the product live in the same Area, as sibling product roots:

suite/
├── raven/             ← engine (B2B whitelabel email platform)
│   └── platform/      ← Go backend only
└── kmail/             ← product (B2C flagship email client)
    ├── platform/      ← SaaS webmail backend (Go + JS)
    ├── app/
    │   ├── mobile/
    │   └── desktop/
    └── site/

3.5 Infrastructure modules

Modules in ai/, infra/, observe/, data/ are components, not products. They do not follow the product-root structure — they keep their current flat layout:

ai/
├── gateway/        ← Go service
├── runtime/        ← Go service
└── voice/          ← Go service

infra/
├── jet/            ← Go web server
└── mesh/           ← network config

4. Example: full migration of email modules

*efore:*

platform/raven/
platform/kmail/
(no Flutter email client exists yet)

*fter:*

suite/
├── raven/
│   └── platform/          ← Go engine (moved from platform/raven/)
└── kmail/
    ├── platform/          ← Go SaaS webmail (moved from platform/kmail/)
    ├── app/
    │   ├── mobile/        ← Flutter: Android + iOS (new)
    │   └── desktop/       ← Flutter: Linux + macOS + Windows (new)
    └── site/              ← landing page (moved from platform/kmail/site/)

5. Go module paths

Go module paths must be updated to match the new directory structure.

*efore:*module koder.dev/platform/kmail *fter:*module koder.dev/suite/kmail/engine

The go.work file at the monorepo root must be updated to include all new paths.


6. Migration plan

Phase 0 — Freeze (Day 0)

  • No new modules created in apps/ or platform/ after RFC is accepted.
  • New modules go directly to the correct Area directory.

Phase 1 — Infrastructure (Week 1)

  • Create the four new Area directories (foundation/, suite/, devplatform/, vertical/).
  • Update CLAUDE.md and docs/stack/adding-a-module.md with the new structure.
  • Update docs/stack/areas.md to reflect the directory mapping.

Phase 2 — Migrate by Area (Weeks 2–5, one Area per week)

  • Move each module to its Area directory using git mv.
  • Update go.mod paths and go.work entries.
  • Update all cross-module import paths.
  • Update koder-jet site entries and DNS if affected.
  • Update CI/CD pipelines.

Phase 3 — Remove empty directories (Week 6)

  • Once all modules are migrated, remove apps/ and platform/.
  • Update all remaining references (scripts, docs, context files).

Rollback

Each module migration is an independent git mv commit. Any individual move can be reverted without affecting others.


7. Impact

Affected area Change required
go.work All Go module paths updated
go.mod (each module) Module declaration updated
Cross-module imports All `koder.dev/platform

Source: ../home/koder/dev/koder/meta/docs/stack/rfcs/monorepo-RFC-001-area-first-directory-structure.md