Architecture principles
Six load-bearing principles. Every framework decision is auditable against them.
1. Screaming architecture
The file tree says what the system does, not what it's built with.
✅ Right
modules/submissions/
modules/enrollments/
modules/billing/
apps/learnflow/❌ Wrong
src/services/
src/controllers/
src/utils/
src/middleware/A new contributor opens the repo and sees the business: submissions, enrollments, billing. Not: services, controllers, utils. The tech is the medium, not the message.
2. Self-identifying files
Every filename reveals role + context. No naked types.ts, index.ts, utils.ts.
✅ Right
submit-answer.action.tssubmission.actor.tssubmissions.events.tsauto-grade.reaction.tssubmissions-by-student.projection.ts
❌ Wrong
actions.ts(which actions?)service.ts(what does it do?)types.ts(whose types?)index.ts(everything goes here)
A file's role should be obvious from git diff filename alone.
3. Conservation of meaning
Names preserve the user's reality through every layer. Code is the last link in a chain that starts with the persona narrative and runs through the brief, the journey, the event, the action, the handler.
✅ Right
The product brief says "Avi submits his answer to a Hebrew Letters exercise." The event is submissions.answer-submitted. The action is submissions.submit-answer. The handler is submit-answer.handler.ts. Open any file — Avi's reality is intact.
❌ Wrong
submissionEntity.create()— what is an "entity"?processFormSubmission()— the user didn't submit a form, they submitted an answerrecordTransaction()— Avi doesn't think in transactions
4. One-author coherence
Every file looks like the same person wrote it. Naming, structure, comment style, error message tone, file organization.
Drift is the enemy. Drift = different files in the same codebase reading differently for the same reason. Most often introduced when team grows or LLMs touch code without context.
Counter-drift practice:
- Conventions live in
AGENTS.md+ code review - Scaffold tools (
nwire scaffold module <x>) inherit the canonical shape from a reference module - One person owns "the way" — even temporarily
5. Artisan engineering
Engineers AND artists. Every decision traces to "why this serves the user."
If you can't say why a primitive exists in terms of someone's lived experience (Avi confused → Avi clear; Dina overloaded → Dina informed), the primitive is in the wrong place.
The framework's own design follows this: defineAction exists because the user types a command. defineActor exists because a single submission has a lifecycle. stuckThresholds exists because Dina needs to know something is stuck before she misses an SLA.
6. Modeling ⊥ deployment
Domain code never imports from wires.
modules/submissions/knows nothing about HTTP, queues, CLI, cronwires/know how to expose modules to a transporttopologies/describe which apps run where- Actions, events, actors look identical regardless of runtime mode
A submit-answer test runs in-process. The same submit-answer ships over HTTP, over a queue worker, over a webhook handler. Same code; the wire chooses.
This is what makes the topology composer work — you can swap monolith for split deployment without rewriting domain code.
How they compose
Principle 1 (screaming) + principle 2 (self-identifying) → a tree where every file is its own descriptor. You stop needing a README to find things.
Principle 3 (meaning) + principle 4 (coherence) → a codebase that reads like one well-written essay. Onboarding shrinks.
Principle 5 (artisan) is the why behind every other principle. If a decision doesn't trace to user value, the answer is "don't ship it."
Principle 6 (modeling ⊥ deployment) is what makes Nwire's primitives the right shape — they describe what the system IS, separately from how it runs.
Audit
amit-architecture-review is a project skill that audits any folder / file / PR against the six principles. Run it on a structural change:
claude --skill=amit-architecture-review --target=modules/billing/The skill walks the artifact and reports principle violations with concrete remediation suggestions.
See also
__docs__/architecture/principles.md— the full canonical doc with examples and bad-vs-good comparisons- Concepts → Why Nwire — these principles applied