Adding a New Module

This is the checklist to follow when creating a new module in the Koder monorepo. The goal is to avoid the drift that produced the kodaverbapoly mess, the bullqueue ambiguity, and the nexusorbit registry-squatting incident.

Before you create the directory

1. Decide which Area it belongs to

Open areas.md and find the Area that matches the nature of the module — not who consumes it. If two or more Areas seem to fit, the module is probably doing two things. Split it into two modules before proceeding.

Red flags that the Area is wrong:

  • "It serves everyone" — probably Foundation
  • "It is only relevant to X industry" — probably Industry Solutions
  • "It is a tool developers use to ship code" — probably Developer Platform
  • "It is an end-user productivity tool" — probably Suite
  • "It stores or moves data" — probably Data Platform
  • "It tells you what is happening inside something else" — probably Observability

2. Decide where it lives — directory and distribution form

The monorepo uses Area-first organization (RFC-001). The directory path encodes what the product is (Area) and how it is delivered (distribution form subdirectory), not what technology it uses.

2a. Is it a product or infrastructure?

Products have end-users (humans who interact with a UI or consume a business capability). They live under an Area directory:

Area directory Use when…
foundation/ Cross-cutting capability: identity, payments, security
suite/ End-user productivity: email, storage, design, messaging
dev/ Developer tooling: forge, IDE, terminal, package registry
vertical/ Vertical solution: fintech, health, legal, agro

Infrastructure has no direct end-user — it is consumed by other modules. It lives under a technologyfunction directory (`ai, infra, observe, data, core, sdk, lang, linux/`). The rest of this guide does not apply to infrastructure modules.

2b. What is the delivery model?

A product root (<area>/<product>/) contains one subdirectory per delivery form:

Subdirectory Delivery model Who runs it
platform/ SaaS — Koder hosts Koder infrastructure
app/mobile/ Installable app — Android + iOS User's phone
app/desktop/ Installable app — Linux + macOS + Windows User's computer
app/tv/ Installable app — TizenOS + WebOS User's TV
app/web/ Self-hosted web frontend User's server

Create only the subdirectories that exist or are actively planned. A pure SaaS engine needs only platform/. A pure mobile app needs only app/mobile/.

app/mobile/ and app/desktop/ are each independent Flutter projects (own pubspec.yaml). When mobile and desktop share most of their UI, a single Flutter project at app/ root (with android/, ios/, linux/, etc. as siblings) is also acceptable — document the choice in the product README.

2c. Does it need the engine + product split?

Ask: *is this going to be a white-label SaaS that third-party customers will license to build their own products on top?*

  • Yes → you need two names, two product roots in the same Area directory

    (<area>/<engine>/platform/ + <area>/<product>/), and must read engine-product-pattern.md before picking names. Pick both names upfront. Do not defer.

  • No → one name is fine. Examples of legitimately single-name modules:

    products/dev/flow/ (git forge), engines/lang/koda (IDE), infra/data/kdb/ (database).

Note — apps/ and platform/ are deprecated. Do not create new modules there. They will be dissolved as existing modules migrate to Area directories (RFC-001, Phase 2).

3. Pick the name(s) responsibly

Run these checks before committing to a name:

Check How
Does a module with this name already exist? ls foundation/ suite/ dev/ vertical/ apps/ platform/ infra/ ai/ observe/ core/ sdk/ lang/ linux/ data/ | grep -i <name>
Does this name collide with a market-recognized brand? Search GitHub and general web for "<name>" saas and "<name>" software
Does it collide with a concept that Koder will want in the future? Think about what you would want to call a package registry, a queue system, a payment gateway — do not squat on those names
Is it a homophone of another Koder product? Say the name out loud alongside the five nearest Koder products. If you hesitate, pick differently
Does it pronounce cleanly in pt-BR, en-US, and es-ES? Test it
Four to six letters? Five is best

If you hit two or more "no" answers, pick a different name.

Creating the module

4. Create the directory and initial files

Replace <area> with the Area directory (foundation, workspace, dev, or industry) and <name> with the product name.

For a SaaS product (backend only):

mkdir -p <area>/<name>/platform/{cmd,internal,docs,backlog/{pending,in-progress,done}}

For a product with a mobile app:

mkdir -p <area>/<name>/platform/{cmd,internal}
mkdir -p <area>/<name>/app/mobile
# then: cd <area>/<name>/app/mobile && flutter create .

For an infrastructure module (no Area, no product split):

mkdir -p <category>/<name>/{cmd,internal,docs,backlog/{pending,in-progress,done}}
# <category> = ai, infra, observe, data, core, sdk, lang, or linux

Minimum initial files (product root <area>/<name>/):

  • README.md or README.kmd — one paragraph explaining what the module is, who uses it, its AreaSector classification, and which distribution forms exist or are planned. Include a link back to `....docsstack/areas.md`.
  • icon.svg — 512×512 viewBox, follows the Koder icon style rules in CLAUDE.md (no background, 3D gradient, minimal internal details, dominant color per product). Rasterize to icon-256.png and icon-512.png with rsvg-convert.
  • platform/go.mod (if SaaS backend) — module path: module koder.dev/<area>/<name>/platform.
  • app/mobile/pubspec.yaml (if mobile app) — package name: koder_<name>.
  • backlog/pending/001-initial-scope.md — the first backlog ticket.

5. Update the stack catalog

Edit docs/platform/site/index.html and add the new module to the product catalog JavaScript array near the bottom of the file:

{ name: 'NewThing', slug: 'koder-newthing', cat: '<category>', url: 'https://newthing.koder.dev', desc: '...' }

Categories currently in use: foundation, data, infra, observe, ai, devplatform, workspace, industry, brand, saas. Use the closest match.

6. Update areas.md

Add the new Sector row under the correct Area. If it is an engine + product pair, add both rows.

7. If it is a multi-tenant SaaS with an engine + product split

Also update engine-product-pattern.md — add a row to the "Established pairs" table.

DNS and server setup (optional, only when you are ready to publish)

8. Create DNS records

# From k.lin (only IP allowed by ClouDNS for the koder.dev zone)
ssh rodrigo@181.191.210.127 -p 220 'curl -s "https://api.cloudns.net/dns/add-record.json?auth-id=52394&auth-password=XS4gsnjQqRWJ&domain-name=koder.dev&record-type=A&host=<name>&record=181.191.210.127&ttl=300"'

9. Add the site to koder-jet

Edit /etc/koder-jet/sites.toml on k.lin:

[[sites]]
domains = ["<name>.koder.dev"]
root = "/var/www/<name>.koder.dev"
gzip = true

Create /var/www/<name>.koder.dev/ with at least an index.html placeholder, then sudo systemctl restart koder-jet.

10. Deploy the landing page

Follow the rules in CLAUDE.md:

  • Landing page lives inside the module repo (platform/<name>/site/ or apps/<name>/site/), never in the separate sites/ directory
  • Always publish and announce the URL in the chat when you finish
  • Use HTTPS only, no HTTP
  • Keep default theme (light/dark) with system preference detection

Committing your work

11. Clean the index before staging

Critical rule for the monorepo — always run this before your first git add:

git reset HEAD

This prevents parallel sessions' staged files from being swept into your commit. See feedback_monorepo_parallel_sessions.md in global memory for the incident that motivated this rule.

12. Stage only your files explicitly

git add platform/<name>/ docs/stack/areas.md docs/platform/site/index.html

Never use git add -A, git add ., or git add <wide-path>/.

13. Verify what is about to be committed

git diff --cached --stat

If you see files from directories you did not touch, stop and rerun git reset HEAD then re-stage.

14. Commit with a descriptive message

Follow the repo's commit style (<scope>: <summary> on the subject line, brief body explaining what and why). Always include the co-author trailer per CLAUDE.md.

15. Push and follow the release flow

If the module is a shippable product, invoke /com_rel_syn_dpl after the commit to handle release packaging, tagging, and distribution.

Post-creation checklist

  • [ ] Area assignment added to areas.md
  • [ ] Icon follows Koder visual family (3D gradient, no background, unique dominant color)
  • [ ] README.md explains the module's identity in one paragraph
  • [ ] Ecosystem catalog (docs/platform/site/index.html) updated
  • [ ] If engine + product split applies: both modules created, both names registered in engine-product-pattern.md
  • [ ] DNS record created (only if publishing a site)
  • [ ] koder-jet site entry added (only if publishing a site)
  • [ ] Landing page deployed and URL announced in chat
  • [ ] Commit made with clean index and explicit file list
  • [ ] No parallel-session files accidentally included in the commit

When all boxes are checked, the module is a first-class citizen of the Koder Stack.