Graphden Tutorial

Step-by-step introduction to graphden: text lessons, most of them paired with a guided in-editor tour (the ▶ column below).

Audience: someone who can program but has never seen graphden before. Each lesson assumes the previous ones and nothing else from the project docs.

How to read this

  • Read lessons in order on first pass.
  • Each lesson has a Goal (what you'll be able to do at the end), Concepts (vocabulary introduced), and Try it (something concrete to type into the running editor).
  • If a concept needs deeper detail than the lesson gives, the lesson links into ARCHITECTURE.md, PACKAGES.md, or wherever it lives.

Lessons

Read them top to bottom — the table is in teaching order, in the same five chapters the in-editor picker uses, and the numbering is sequential in that order: the number is the file name, the deep link (?tutorial=16), and the tour's :id. Inserting a lesson mid-sequence renumbers everything after it — that is a mechanical, repo-wide search-and-replace (ids appear only in file names, links, tour :ids and prose references), so keep the numbers honest rather than appending out of order.

Basics

# Lesson Status
01 Anatomy of a fn-def ✅ written · ▶ interactive
02 Reading a card — rows, unfolding, closed cards, descriptions ✅ written · ▶ interactive
03 Parents and inheritance — single parent, then multiple ✅ written · ▶ interactive
04 Slots and bindings — what they are at the data level ✅ written · ▶ interactive
05 Free arguments and how they propagate ✅ written · ▶ interactive
06 Lists — seed, append, close ✅ written · ▶ interactive
07 Optional, required and sealed — what a slot decides beside its value ✅ written · ▶ interactive
08 Types — atomic, refinement, record, union, variant, list ✅ written · ▶ interactive

Composing

# Lesson Status
09 Higher-order functions and :fn-typed slots ✅ written · ▶ interactive
10 Composing pages from components ✅ written · ▶ interactive
11 The :custom-script escape hatch ✅ written · ▶ interactive
12 State — cells, swap, and a graph-native cache ✅ written · ▶ interactive
13 Recursion: loops without cycles ✅ written · ▶ interactive
14 Live fragments: htmx from the graph ✅ interactive + written

Running it

# Lesson Status
15 Executing a fn — free-arg form, history, cancel ✅ written · ▶ interactive
16 Effects and the :secret type-marker ✅ written · ▶ interactive
17 Tests — the tests namespace ✅ written · ▶ interactive
18 Debugging: traces, the call tree, and catching a request ✅ written · ▶ interactive
19 When something breaks, and when it just repeats: the problem filters ✅ written · ▶ interactive

The editor

# Lesson Status
20 Finding your way: kind filters and the Inspector ✅ written · ▶ interactive
21 Working without the mouse — keyboard & accessibility ✅ written · ▶ interactive
22 Filters and views — look at the part of the graph you mean ✅ written · ▶ interactive
23 Branches — fork, edit, diff, merge ✅ written · ▶ interactive
24 Review — propose, approve, protected merge ✅ written · ▶ interactive
25 Editing the editor: asset overrides ✅ written · ▶ interactive
26 Version history: what changed, and going back ✅ written · ▶ interactive

Your organization

# Lesson Status
27 Members — managing who is in your org ✅ written · ▶ interactive
28 Grants — who may touch what ✅ written · ▶ interactive
29 Roles — capabilities as a bundle ✅ written · ▶ interactive
30 Apps — publishing a fn as a public site ✅ written · ▶ interactive
31 Packages — namespaces, fns.edn, impls.clj, deps ✅ written
32 Distributing packages — publish, install, update, fork ✅ written · ▶ interactive
33 Working across organizations ✅ written · ▶ interactive
34 Working offline: a local instance, git snapshots, push/pull ✅ written
35 HTTP handlers and persistent services ✅ written · ▶ interactive
36 Signing up & signing in: your account ✅ written · ▶ interactive
37 Plans & tiers — what the cloud grants each account ✅ written · ▶ interactive
38 HTTP calls by function identity ✅ written · ▶ interactive
39 Queues — asynchronous work between services ▶ interactive + ✅ written
40 The Marketplace: themes, keyboard layouts, and what others published ✅ written · ▶ interactive
41 The package lifecycle — both sides of a version ▶ interactive + written
42 AI clients and API tokens: the graph over /mcp ✅ written · ▶ interactive

▶ interactive — the lesson also exists as a guided in-editor tour: open the editor with ?tutorial=NN (the landing demo link does this for Lesson 01), or pick “Interactive tutorial” in the account-chip menu — in an organization workspace the lesson runs on its own tutorial-NN-* branch, and ending it offers branch deletion = full rollback. The tour's step scripts live in the graph (app.tour/_tour-lessons) and are drift-guarded by tools/browser-test/edit-tutorial-tour*.test.js — keep the written lesson's “Try it” section and the tour steps in sync when either changes.

The catalogue remembers what you have read (in your browser, not in the graph) and marks it ✓ done. That mark is yours: the ↺ beside a finished lesson takes it back off, and Clear progress in the catalogue's footer clears the whole history at once, behind a confirmation. Lessons have editions (:version in the tour script, bumped when a lesson's flow changes): a lesson you finished that has since changed is chipped updated until you take it again, a lesson that was not in the catalogue the last time you opened it is chipped new, and the account-chip menu counts both on its “Interactive tutorial” row. The catalogue's header counts what you have done, what this session can run, and how many lessons there are. Finishing a lesson offers what to read next right there — the lesson that follows, plus the first one you have not read when that is a different lesson — and starting it from the dialog cleans the finished lesson up first (deleting its branch, or the rows it created).

If a tab closes or reloads before cleanup finishes, its lesson and creation ledger remain in this browser. Open Interactive tutorial in the account menu to continue the saved step or choose End lesson & clean up. Returning on another branch leaves the lesson paused; recovery switches back to its original context before cleanup. Reloading a cleanup dialog restores that decision, including a failed deletion that can be retried. Choosing another lesson first asks whether to delete or keep the pending lesson's work. Keep branch and Keep & close end the tracked session and retain the data; later lessons do not claim a retained branch for rollback. Sessions saved by an older editor use their recorded items for cleanup; their legacy branch name alone cannot authorize a full branch rollback. Cleanup pauses when the original account or organization cannot be verified, or the original branch is unavailable. Cancel retains the saved session; Keep & close ends tracking without deleting graph data. Inspect any remaining branch from the branch menu.

Every tour is the SHOWN half of its lesson; the written lesson is the whole of it — the model behind the steps, the branches of the topic the tour does not walk (cardinality and per-branch services in 35, closure capture in 09, …), the same thing as fn-defs, and a "what we glossed over" list. The tour says so at the hand-over: its last step links to the written lesson and says in one line what the text adds, and the catalogue repeats that line under every lesson you have marked ✓ done (the ↗ on any row opens the text). The two lessons without a tour are listed in the catalogue too, as text only rows that open the text — so the catalogue is the whole tutorial, not just the part the editor can walk. The link target is https://graphden.dev/tutorial/ plus the lesson's file name; a deployment serving its own copy of the lessons (a translation, an intranet mirror) sets GRAPHDEN_TUTORIAL_BASE to it.

Two lessons have no tour: 31 works with package files on disk and startup sync; 34 requires a second instance and external deployment tools. 14 practices live fragment updates through an isolated HTML handler preview; 39 practices queue retries and recovery when persistent services are available. 41 practices author and consumer on two owned branches; 42 practices account token creation, scopes and revocation, while external registry and MCP client setup remain in their written lessons. Both text-only lessons sit in the chapter their subject belongs to, which is why the ▶ column is worth reading.

The organization tours declare what they need (:requires): a capability such as manage-users or publish-packages, or a named deployment condition. Lessons 35 and 38 require an authenticated temporary HTTP host; ordinary cloud accounts can publish finite handlers without a dedicated executor or service quota. Lesson 14 also needs an account browser session, an isolated apps domain and manage-apps access: it creates its own app host and removes that exact route before its lesson graph and branch. Lesson 30 needs those same prerequisites; it creates an Apps route, serves typed HTML through the branch preview, and explains ordinary publication after a reviewed merge into main. Persistent services still require the existing self-hosted/dedicated capability. The cross-org tour needs organizations, and asset overrides need a single-tenant instance. A missing condition leaves the lesson visible but disabled with a reason on its row.

Lesson 25 edits personal UI graphs on both cloud and self-hosted installations (:requires "personal-ui-graphs"). A protected ordinary resolver finds the current profile's editor graph or shared defaults. Personalize creates inherited role children; the lesson binds the menu view's free theme input while keeping shared helpers and unrelated components. The full bundle remains an advanced compatibility tool. Creating and editing graphs still requires ordinary permissions. The separate Source files panel edits shared frontend assets and remains self-hosted/platform-only because those writes affect every user of the instance.

New lessons are added as features ship. If a lesson would document a feature that doesn't yet exist or behaves differently from how it's described, it stays ⏳ planned until the gap closes.

Earlier end-to-end worked example

Once you've worked through the Basics and Composing chapters (lessons 01–14) plus Services (lesson 35), Building an API-poller shows an earlier composition: a scheduled service that calls an external HTTP API with a vault-backed bearer token and writes each result into your own Postgres table — built entirely from fn-defs, no Clojure. It needs alignment with the current secret-flow contract before it is a working end-to-end recipe; read its status note first.

How to contribute a lesson

A lesson is a short focused walkthrough of one concept. Keep:

  • ~60-150 lines of markdown total
  • One concrete worked example you can paste into the running editor
  • Concepts introduced explicitly named (so future lessons can refer)
  • No prerequisites beyond the previous lessons in this index

Avoid:

  • Re-explaining what earlier lessons already covered (link to them)
  • Duplicating reference material that lives in docs/*.md (link)
  • "Why we did it this way" rationale — that belongs in PHILOSOPHY.md and gets linked, not pasted