The connections, not the parts
The Smallbox Foundation Map
The boxes on this map are the easy part — any developer can build them. What a parts list never shows is the connective tissue between them: which connections are allowed, which are deliberately forbidden, and why every responsibility has exactly one home. That is what this map documents, drawn from the production systems behind CompanyGraph and the site you are reading.
The shape
↓ one API · typed contracts ↓
↓ typed SDK clients · a contract change is a compile error ↓
The diagram refuses to draw twelve arrows into the logging box; the sentence inside it is the honest version. Position carries the rest: surfaces on top, one seam in the middle, reusable modules below it, your engine beside them.

The un-abstracted version of this map is public too: every real service behind both products, every real line, clickable — the live architecture map.
The edges — every arrow, and why it exists
Website Backend
The public site depends on one contract, not on the layout of five modules. The backend can re-wire its internals without the site noticing.
Admin Backend
Operators work the same API the product runs on — not a side door with its own rules.
In the production system this map is drawn from, the admin's TypeScript types are generated from the backend's OpenAPI spec — contract drift fails the build, not the operator.
Backend Identity
Accounts, sessions, roles, and tokens are the same problem in every product. The product keeps only a user id and asks for the rest — a product that owns its identity tables rebuilds them in the next product.
Backend Email
Product code decides when an email should exist; the email module owns how — templates, queue, retries, history. A send that goes through the queue can be seen, retried, and audited.
Backend Images
Media is a generic capability: upload, metadata, a library, a picker. Products reference an image by id and never hold bytes.
Backend Translation
Language infrastructure — providers, keys, caching — should not leak into product code. The product asks for a translation, not for a vendor.
Everything Logging
Failure visibility must survive module boundaries. Every module, the backend, and both frontends report here, so “why did this break” is one query, not one log search.
The startup heartbeats of all twelve running services — both products, frontends included — land on one admin page.
Backend Your domain engine
The deliberate slot: scoring, matching, interpretation — whatever makes the product yours. Separate scoped work, but it has a named place from day one, behind the same kind of boundary as every module.
The forbidden edges — what never happens here
Restraint is most of architecture. The arrows above say what the system does; the list below says what it refuses to do — and the refusals are why the arrows stay simple.
A frontend never calls a module directly.
The moment the UI knows a module's address, the module stops being replaceable — and authorization gets enforced in two places.
Modules never call each other. (Only infrastructure reporting to logging.)
Composition belongs in exactly one place. Module-to-module knowledge quietly rebuilds the tangle the boundaries exist to prevent.
No foreign key crosses a module boundary — references are by id only.
Each module's schema must evolve on its own clock. A cross-module foreign key welds two release cycles together.
Business rules never live in controllers.
Transport and meaning change at different speeds. A rule in a controller is invisible to every other caller.
Your product's nouns never enter a module.
A module that knows your product cannot be reused in the next one — and, in the other direction, your domain stays yours.
Email is never sent inline from a request.
An inline send has no queue, no retry, and no history. It works until the day nobody can say whether it worked.
The module catalogue
| Module | Owns | Status | Running behind |
|---|---|---|---|
| Structured backend core | Layers, typed contracts, domain model | Foundation core | CompanyGraph · Smallbox Labs |
| Identity | Accounts, sessions, roles, tokens | Running in production | Both products |
| Templates, queue, retries, history | Running in production | Both products | |
| Logging | Failures as records, heartbeats | Running in production | Both products + every frontend |
| Images | Bytes, metadata, library, picker | Running in production | Both products |
| Translation | Language infrastructure | Running in production | CompanyGraph |
| Admin pattern | Operator surfaces on the same domain model | Running in both; shared kit extraction planned | Both products |
| Billing | Subscriptions, webhooks, gated access | Proven inside CompanyGraph; not yet extracted as a module | CompanyGraph |
Foundation clients hold a licence that grows with this catalogue: every module version released — current and future — is theirs to take. The terms are on the ownership & terms page.
The parts are buildable. The connections are the argument.
Any experienced developer can build the boxes on this map — sign-in in a few weeks, an email sender in another. What the map actually documents is the way the boxes are connected. Frontend types are generated from backend contracts, so drift fails the build. Module clients are typed, so a contract change is a compile error. Failures from every box land as records on one page. One real workflow proves the pattern end to end, and orientation docs tell the next contributor why each rule exists. That connective layer is what a first hire cannot rebuild in a quarter while also shipping product — and it is why a foundation arrives as one working system rather than a parts list.
How this becomes your foundation
The package installs the relevant modules into your product and deployment, then wires one real workflow end to end through them — sign-up to email to admin to failure record — so the map above stops being a diagram and becomes your system.
Drawn from the running systems, not from a slide. When this page and production disagree, production wins — and this page gets fixed.