How a software factory is shaped so a new product is a folder of content, and why the seam between engine and site is a CSS custom property.

The requirement in one sentence

A brochure site in five minutes, a membership site in ten. Not a template you copy and then fix for a week; a folder that compiles, with the login doors, the billing, the gating and the assistant already there, and only three things left to write: content, brand CSS, configuration.

One copy, on disk, in the same commit

Every site imports the same canon through an npm workspace. There is no publish step, no vendored copy, no mirror: a security fix to the login door reaches every site in the commit that makes it. The analogy is a franchise kitchen: one recipe book, many storefronts, and when the recipe changes the change is in every kitchen tonight.

Two axes keep the inside of the canon honest. A ring model says which file may import which (inward only: a decision never imports a database client). A frame list says which files a brochure site gets (the shell, the sections, SEO, chat) and which it never compiles (a session, a ledger, a webhook).

The seam is a token

Structure is canon, brand is the site. The canon's CSS declares layout, dimensions and mechanism and reads tokens it never defines: the text colour, the background, the one highlight, the trim. The site declares those four values and never declares structure. A guard asserts both directions: no brand literal in the canon, and every bare token the canon reads is declared by the site, because a missing token silently drops the whole property.

Four named colours, no more. Every other colour is a mix of those four. A rebrand is four lines; a fifth colour is a decision with a name.

Derived, never declared

The roster of sites is read off the disk. The list of guards is the directory. The sitemap is built from the routes. The factory inventory, the architecture chart and the contents of each site are generated from the tree and checked on every build; a number typed into a document is a bug, because it rots the moment the tree moves.

site  = content + brand tokens + configuration
                     │
                     ▼ (one alias, one workspace)
canon = engine (auth · billing · gating · ai) + frame (shell · sections · seo · chat)
                     │
              rings: inward imports only     frame list: what a brochure site compiles

all writing