Quickstart
ArchCode is plain text. There is nothing to install to try it, one package to install to build with it, and one file to add to a repository to keep it. Pick the way that matches where you are — each takes about five minutes.
| In the browser | nothing to install — write, drag, share a link | → open the Playground |
| In a repository | one .arch file beside the README, rendered by the engine | → jump there |
| In your editor | .arch files in VS Code, with a live preview | → jump there |
In the browser
Open the Playground. It starts with a small system already in the editor; every edit redraws the picture as you type, and every drag on the picture writes back into the text.
Replace the text with three lines of your own:
service checkout "Checkout" tech Go datastore orders_db "Orders DB" tech PostgreSQL 16 checkout writes orders_db over SQL
archcode: "0.2"
objects:
- id: checkout
kind: service
name: Checkout
attrs:
tech: [Go]
- id: orders_db
kind: datastore
name: "Orders DB"
attrs:
tech: [PostgreSQL, "16"]
relations:
- from: checkout
verb: writes
to: orders_db
over: SQL
placements: []
{
"archcode": "0.2",
"objects": [
{
"id": "checkout",
"kind": "service",
"name": "Checkout",
"attrs": {
"tech": [
"Go"
]
}
},
{
"id": "orders_db",
"kind": "datastore",
"name": "Orders DB",
"attrs": {
"tech": [
"PostgreSQL",
"16"
]
}
}
],
"relations": [
{
"from": "checkout",
"verb": "writes",
"to": "orders_db",
"over": "SQL"
}
],
"placements": []
}
Then try the things that make it an editor rather than a viewer:
- drag a card — the arrows stretch instead of being redrawn; press
pin(or⌘S) and the positions become aviewblock in your text, so the file is the picture; - click an arrow — change its verb, its protocol and its label from the panel; drag an end onto another card and the line in the text follows;
- switch the lens —
Logicalshows what talks to what,Infrastructureshows where it runs,Resourcessums what it needs; - copy link — the document travels inside the URL, compressed; no account, no server;
- export — SVG for a wiki page, PNG for a chat. Fonts are embedded, the picture looks the same everywhere.
Press ? for every key and gesture, or type help in the canvas terminal.
In a repository
A system's architecture belongs next to its code. Add one file at the root:
your-service/ ├── README.md ├── archcode.arch ← the architecture, in the notation └── src/
# archcode.arch — Orders, as it is today system orders "Orders" { service api "Orders API" tech Go service worker "Fulfilment" tech Go datastore db "Orders DB" tech PostgreSQL owned_by api broker mq "Events" { transit tech NATS } api writes db api publishes order.placed via mq worker subscribes order.placed via mq api exposes http openapi://api/openapi.yaml }
archcode: "0.2"
objects:
- id: orders
kind: system
name: Orders
- id: orders.api
kind: service
name: "Orders API"
parent: orders
attrs:
tech: [Go]
interfaces:
- verb: exposes
kind: http
pointer: "openapi://api/openapi.yaml"
- id: orders.worker
kind: service
name: Fulfilment
parent: orders
attrs:
tech: [Go]
- id: orders.db
kind: datastore
name: "Orders DB"
parent: orders
attrs:
tech: [PostgreSQL]
owned_by: [api]
- id: orders.mq
kind: broker
name: Events
parent: orders
attrs:
transit: []
tech: [NATS]
relations:
- from: api
verb: writes
to: db
- from: api
verb: publishes
to: order.placed
via: [mq]
- from: worker
verb: subscribes
to: order.placed
via: [mq]
placements: []
{
"archcode": "0.2",
"objects": [
{
"id": "orders",
"kind": "system",
"name": "Orders"
},
{
"id": "orders.api",
"kind": "service",
"name": "Orders API",
"parent": "orders",
"attrs": {
"tech": [
"Go"
]
},
"interfaces": [
{
"verb": "exposes",
"kind": "http",
"pointer": "openapi://api/openapi.yaml"
}
]
},
{
"id": "orders.worker",
"kind": "service",
"name": "Fulfilment",
"parent": "orders",
"attrs": {
"tech": [
"Go"
]
}
},
{
"id": "orders.db",
"kind": "datastore",
"name": "Orders DB",
"parent": "orders",
"attrs": {
"tech": [
"PostgreSQL"
],
"owned_by": [
"api"
]
}
},
{
"id": "orders.mq",
"kind": "broker",
"name": "Events",
"parent": "orders",
"attrs": {
"transit": [],
"tech": [
"NATS"
]
}
}
],
"relations": [
{
"from": "api",
"verb": "writes",
"to": "db"
},
{
"from": "api",
"verb": "publishes",
"to": "order.placed",
"via": [
"mq"
]
},
{
"from": "worker",
"verb": "subscribes",
"to": "order.placed",
"via": [
"mq"
]
}
],
"placements": []
}
Notice what the file does not contain: no coordinates, no shapes, no copy of the OpenAPI document — only the fact that a contract exists and where it lives (openapi://api/openapi.yaml is a pointer). That is what keeps the file reviewable in a pull request.
Render it. The reference engine is an npm package; a dozen lines turn the file into a picture you can commit or publish from CI:
npm install @archcode-io/engine@preview # 0.2 is a preview: the `preview` tag, not `latest`
// render.mjs — archcode.arch → architecture.svg
import { readFileSync, writeFileSync } from 'node:fs';
import { parse, lower, check, applyLens, layout, toSvg } from '@archcode-io/engine';
const src = readFileSync('archcode.arch', 'utf8');
const { doc, diagnostics } = parse(src);
const model = lower(doc);
for (const d of [...diagnostics, ...check(doc, model)]) console.error(`${d.severity} ${d.code} ${d.line}:${d.col} ${d.message}`);
const picture = await layout(applyLens(model, { lens: 'logical' }));
writeFileSync('architecture.svg', toSvg(picture, '', { theme: 'light' }));
node render.mjs && open architecture.svg
check is the part a linter would run: an unresolved reference, an ambiguous id or a run outside a host comes back with a line and a column, and the render still happens — a broken file yields a partial model, never a crash (§17.10).
Or the command line — the same calls without the script:
npm i -g archcode@preview archcode render archcode.arch -o architecture.svg # --theme light, --lens infrastructure, --kind deployment archcode check archcode.arch # exit 1 on errors; --strict fails on warnings too
Diagnostics come out as file:line:col severity CODE message, the shape CI and editors read.
Open it in the Playground. Paste the file, or drop it onto the editor; download .arch brings it back. A shared link carries the whole document, so a reviewer can look at the picture without cloning anything.
In your editor
The extension colours kinds, verbs and attributes, puts the diagnostics in the Problems panel, and opens a preview beside the file that redraws as you type — the Playground, docked (⌘K V, the same key as Markdown's preview).
- Download the extension — one
.vsixfile, the engine inside, nothing else to install. - Install it:
code --install-extension archcode-<version>.vsix, or in VS Code Extensions → ⋯ → Install from VSIX…. Cursor, Windsurf and VSCodium take the same file. - Open any
.archfile and press⌘K V.
The file comes from this site, not from a marketplace, so it does not update itself yet — the Open VSX and Marketplace listings follow the public preview. Completion of ids, hover and go-to-definition are next soon.
What next
- The specification — start with §2, the smallest useful document, then §4 vocabulary and §5, the worked example. Every section carries a mark: implemented, partial, reserved for v0.3, planned.
- Examples — the reference architectures, each with its source and an "open in Playground" link.
- Conformance — the spec repository ships fixtures any implementation can run:
node conformance/run.mjs --engine <your module>. - Coming from Structurizr — what carries over (almost everything structural) and what does not (styles, per-diagram layout), with a converter to follow soon.