Engineering · 3 min read
Project structure
How our repos are laid out: each product owns its own, its README is the map, and the map stays true.
There's no single Flagon codebase to map. Each product owns its own repo (or repos), laid out however suits it, and the team that owns the product owns the layout too. So this page isn't a map. It's the rules every map follows, so that when you land in any of our repos you know where the map is, and you can trust it.
The README is the map
Every repo's README is the source of truth for that repo. Not this handbook, not a wiki, not the person who set it up. A good README answers, in order:
- What this is, in a sentence or two, and where it runs.
- Where things are: a short layout, one line per top-level directory, saying what lives there.
- How to run it, from a fresh clone (the bar for that is in developing locally).
- How to check a change before you push it.
- How it ships.
If a newcomer has to ask a person any of those, the README has a bug.
Group by what changes together
When pieces of a product change together, they live together, so a change that crosses them lands in one reviewable pull request instead of several that have to merge in a careful order. That usually means one repo per product, with its apps, services and shared packages side by side. When pieces don't change together, they don't need to share a repo just because the same company owns them.
Two real maps
g1t is one repo holding everything it ships, hosted on g1t itself:
apps/web the site: server-rendered React on a Worker, holds no data
apps/docs the documentation site, with the API explorer
apps/api the REST API and MCP server (Rust)
services/* identity, repos, work, events, runner: one Worker and database each
crates/* Rust shared by the services, and the program that runs in a sandbox
packages/* TypeScript contracts and the shared design tokensThis website is a single Next.js app, and its repo, flagon, is about as small as a map gets:
content/handbook the handbook, one .mdx per page, grouped in folders by department
content/blog the blog, one .mdx per post
src/app routes
src/components site chrome and MDX rendering
src/lib content loaders and configBoth READMEs carry these maps, and both are more current than this page will ever be. Read the README, not this.
How to find your way in
The fastest way to understand a repo isn't to read the whole tree, it's to follow one request end to end. Pick something small and trace it: the page that renders it, the call it makes, the thing that owns the data behind that call, and back. In g1t that means a route in apps/web asking a service for something; here it means a URL resolving to an .mdx file through a loader in src/lib. One thread like that teaches you more than an afternoon of browsing, and it makes who owns the data concrete instead of abstract.
If a change doesn't have an obvious home, that's worth surfacing in review, not silently forcing. The usual question is which side of the data boundary it belongs on: is this logic that belongs with the thing that owns the data, or is it presentation? When that's unclear, the confusion is information.
Keeping the map true
Structure rots when nobody tends it. If you move things, update the README in the same pull request. A map that quietly stops matching the territory is worse than no map, because people trust it and get lost. Keeping it honest is part of owning what you build.