2. Your First Architecture
This chapter walks through building a complete (small) architecture from an empty directory. By the end you’ll have three modules, one process tying them together, a diagram, and a feel for the shape of the language.
We’re going to use only the bare language — the base kinds module, facet, interface plus the top-level constructs process and view — with no standard library. Later chapters introduce richer kinds (service, command, event); Chapter 11 covers them in detail. Starting bare keeps the focus on what the language itself does, separate from convention.
We’ll model a payments domain: a customer pays, a payments service authorizes, a ledger records. Nothing else.
A package
Every project starts with a manifest. Create package.archspace:
name: shopOne line. The name identifies the package; we don’t import the stdlib yet because we’re using bare kinds only.
Chapter 12 covers the manifest in depth. For now this is enough.
Three modules
Add payments.arch in the same directory:
module Payments { team: Platform "Authorizes and captures card payments."
interface Authorize interface Capture interface Refund}
module Ledger { team: Finance "Immutable financial record of every transaction."
interface Record}
module Customer { "The person initiating the payment."}You’ve declared three modules using the bare module kind. Each has:
- A kind (
module) — the base kind of the language. - A name (
Payments,Ledger,Customer) — how the rest of your model refers to it. - A team field — who owns it (optional; not required by the bare kind).
- A description — the bare string literal. Plain markdown, plus two extensions you’ll meet in Chapter 10.
- Zero or more interfaces —
interface Authorize, etc. These are the things other modules can ask this one to do.
Customer has no interfaces. That’s fine — not every module exposes operations. (Stdlib kinds add semantic distinctions like actor for entities that only originate calls; for now everything is just module.)
Try it live — edit the source above, the diagram updates below. Hover identifiers, press F2 to rename, Ctrl/⌘ Space for completion:
Save the file and run:
archlang validate .You should see no errors. Open the directory in your editor (with the Archlang extension installed) and trigger the inline preview pane — three boxes appear, connected to nothing yet. That’s expected — we haven’t said how they interact.
The diagram looks plain because the bare module kind has no specialized rendering. Boxes labeled with names; one default widget for all three. The stdlib introduces per-kind widgets (Chapter 11); for this chapter, plain boxes are the point — they make the underlying structure obvious.
A process
Add checkout.arch:
process Checkout { Customer > Payments.Authorize Payments > Ledger.Record Customer > Payments.Capture Payments > Ledger.Record}A process is a sequence of steps. Each step has the form Caller > Callee.Interface:
- The caller (left of
>) is a module — who is making the call. - The callee (right of
>) is an interface — the specific operation being invoked.
Save and the preview updates. The diagram now has arrows. They weren’t drawn — they were derived from the process. This is the first commitment from the foreword in action: behavior is the source of structure.
Mindset shift. In most diagramming tools you draw an arrow because two services talk. In Archlang you declare a process step; the arrow appears because something declared that it talks. Delete the step and the arrow disappears. Add another step and a new arrow appears. The dependency graph is always a function of behavior.
A change
Open payments.arch and add a fourth interface:
module Payments { team: Platform "Authorizes and captures card payments."
interface Authorize interface Capture interface Refund interface Void // new}Save. The preview updates. Void shows up in the Payments node; no arrow connects it to anything because no process invokes it yet.
Now open checkout.arch and add a step:
process Checkout { Customer > Payments.Authorize Payments > Ledger.Record Customer > Payments.Capture Payments > Ledger.Record Customer > Payments.Void // new — customer cancels mid-checkout}Save. The preview updates again. Void now has an arrow into it.
You’ve added an interface and a process step in two edits and the diagram followed along. No layout to redo, no boxes to drag.
What you built
shop/├── package.archspace├── payments.arch└── checkout.archThree files, three modules, one process. A complete (if minimal) architecture written in pure bare language. Every diagram, every dependency arrow, every impact analysis that Archlang can do for you is derived from these files.
Summary
- A workspace starts with a
package.archspacemanifest naming the package. - The bare kinds
moduleandinterfaceare enough to model structure and exposed operations. - Processes are sequences of
Caller > Callee.Interfacesteps. Arrows in diagrams are derived from processes — they are not drawn directly. - The editor preview re-renders on save. The dev loop is edit file → see diagram.
What’s next
Chapter 3: Reading a Diff → — make a change to the architecture and see how Archlang shows you what changed.