One store. Every object in it is stored once, under one slug, and every page is a rendering of its object. A page embeds other objects by reference; editing the referenced object changes every page that embeds it. Nothing is copied between pages.
Writes go through one REST contract (linked below): add, read, edit, delete, query. Every edit is checked against the object's current hash. Every object carries a SHA-256 hash, and the export manifest lists all of them.
The demo — two objects, four surfaces
Below are two stored objects embedded by reference: a person and a house. On the person's own page, the house appears under "Prior address." On the house's own page, the person appears under "Prior resident." One person object, one house object, one stored relationship — rendered from both sides. The house's Zillow, Redfin, and realtor listings are three further objects, stored separately from the house.
Canonical layer: 582 published objects in 61 kinds. Largest kinds: standard 88, procedure 85, article 58, essay 35, technical 32, life-event 24, publication 24, collection 21, systems 21, social_profile 18.
Atlas layer, counted by kind through the query API: permits 356,695 · parcels 96,253 · people 6,658 · organizations 938 · counties 59 · cities 27.
Total queryable objects: 461,212 or more — the Atlas has no kind census, so its kinds were counted by querying 30 kind names; any kind not queried is not in this sum. Draft and unpublished records are excluded from every count above.
Live queries — these pages are query results, not documents
Current residents of Vichy Avenue — executes against the graph; returns 0, because the stored Vichy residence is prior and the query asks for current.
POST /api/jarticles adds an object (201; duplicate slug 409). GET /api/jarticles/<slug> returns the record and its hash. PATCH /api/jarticles/<slug> edits it, carrying the current hash in If-Match (stale hash: 412). DELETE removes it under the same rule. POST /api/jarticles/query queries by kind, by field, and by typed relationship — for example, people connected by resides_at to houses on a named street, current relationships only.
A test person was added through the contract (HTTP 201, version 1, hash issued), read back, appended to by PATCH (HTTP 200, version 2, new hash; the appended fact verified in the record), deleted under its hash (HTTP 200), and read again (HTTP 404). Add, read, append, delete — each step confirmed by the next.
the whole object this page is drawn from, as JSON · Open JSON
{
"schema":"https://miscsubjects.com/schemas/jarticle.json",
"status":"published",
"slug":"the-graph",
"title":"The Graph",
"kind":"article",
"body": [
"# The Graph\n\nOne store. Every object in it is stored once, under one slug, and every page is a rendering of its object. A page embeds other objects by reference; editing the referenced object changes every page that embeds it. Nothing is copied between pages.\n\nWrites go through one REST contract (linked below): add, read, edit, delete, query. Every edit is checked against the object's current hash. Every object carries a SHA-256 hash, and the export manifest lists all of them.",
"## The demo — two objects, four surfaces\n\nBelow are two stored objects embedded by reference: a person and a house. On the person's own page, the house appears under \"Prior address.\" On the house's own page, the person appears under \"Prior resident.\" One person object, one house object, one stored relationship — rendered from both sides. The house's Zillow, Redfin, and realtor listings are three further objects, stored separately from the house.",
{
"type":"entity",
"ref":"cyrus-massoumi"
},
{
"type":"entity",
"ref":"337-melrose-avenue"
},
"## Scale — measured 2026-11-04\n\nCanonical layer: **582 published objects in 61 kinds.** Largest kinds: standard 88, procedure 85, article 58, essay 35, technical 32, life-event 24, publication 24, collection 21, systems 21, social_profile 18.\n\nAtlas layer, counted by kind through the query API: **permits 356,695 · parcels 96,253 · people 6,658 · organizations 938 · counties 59 · cities 27.**\n\nTotal queryable objects: **461,212 or more** — the Atlas has no kind census, so its kinds were counted by querying 30 kind names; any kind not queried is not in this sum. Draft and unpublished records are excluded from every count above.",
"## Live queries — these pages are query results, not documents\n\n- [Current residents of Vichy Avenue](https://miscsubjects.com/graph/query/people-on-vichy-avenue) — executes against the graph; returns 0, because the stored Vichy residence is prior and the query asks for current.\n- [All Gmail addresses on the graph](https://miscsubjects.com/graph/query/gmail-addresses) — returns 1.\n- [All LinkedIn profiles on the graph](https://miscsubjects.com/graph/query/linkedin-profiles)\n- [People at DSCO](https://miscsubjects.com/a/dsco-people)\n- [Export manifest — every published object's id, kind, and hash](https://miscsubjects.com/graph/manifest.json)",
"## The contract\n\n`POST /api/jarticles` adds an object (201; duplicate slug 409). `GET /api/jarticles/<slug>` returns the record and its hash. `PATCH /api/jarticles/<slug>` edits it, carrying the current hash in `If-Match` (stale hash: 412). `DELETE` removes it under the same rule. `POST /api/jarticles/query` queries by kind, by field, and by typed relationship — for example, people connected by `resides_at` to houses on a named street, current relationships only.\n\nFull contract: [graph-rest-contract/1](https://miscsubjects.com/graph/contract.json). The same operations run from any Google Sheet: [the Sheets guide](https://miscsubjects.com/a/graph-from-google-sheets).",
"## Receipt — the write cycle, executed 2026-11-04\n\nA test person was added through the contract (HTTP 201, version 1, hash issued), read back, appended to by PATCH (HTTP 200, version 2, new hash; the appended fact verified in the record), deleted under its hash (HTTP 200), and read again (HTTP 404). Add, read, append, delete — each step confirmed by the next."
],
"type":"article",
"created":"2026-11-05T02:20:37.032Z",
"updated":"2026-11-05T02:20:37.032Z",
"version":1,
"hash":"7e8ea59fd4f451889dd6fd65f773b5fa497f7838ab58b0f85c4e905dd00f3572",
"theme":"https://miscsubjects.com/article-theme.json",
"styling": {
"scope":"shared",
"theme_ref":"https://miscsubjects.com/article-theme.json"
},
"page":"https://miscsubjects.com/a/the-graph",
"json":"https://miscsubjects.com/a/the-graph.json",
"markdown":"https://miscsubjects.com/a/the-graph.md",
"calls": [
{
"what":"this article as a page (no key)",
"method":"GET",
"url":"https://miscsubjects.com/a/the-graph",
"headers": {}
},
{
"what":"this article as its object (no key)",
"method":"GET",
"url":"https://miscsubjects.com/a/the-graph.json",
"headers": {}
},
{
"what":"this article as Markdown (no key)",
"method":"GET",
"url":"https://miscsubjects.com/a/the-graph.md",
"headers": {}
},
{
"what":"the object with its hash, drafts too",
"method":"GET",
"url":"https://miscsubjects.com/api/jarticles/the-graph",
"headers": {
"x-terminal-key":"<YOUR_TERMINAL_KEY>"
}
},
{
"what":"one piece and that piece’s hash",
"method":"GET",
"url":"https://miscsubjects.com/api/jarticles/the-graph/at?path=facts",
"headers": {
"x-terminal-key":"<YOUR_TERMINAL_KEY>"
}
},
{
"what":"grep: every key or value that matches, with the path to change it",
"method":"GET",
"url":"https://miscsubjects.com/api/jarticles/the-graph/grep?q=owner",
"headers": {
"x-terminal-key":"<YOUR_TERMINAL_KEY>"
}
},
{
"what":"change pieces (set, merge, delete, append, insert, move); if-match is the hash",
"method":"PATCH",
"url":"https://miscsubjects.com/api/jarticles/the-graph",
"headers": {
"x-terminal-key":"<YOUR_TERMINAL_KEY>",
"content-type":"application/json",
"if-match":"<hash from the read>"
},
"body": {
"ops": [
{
"op":"set",
"path":"facts.example",
"value":1
}
]
}
},
{
"what":"replace the whole object",
"method":"PUT",
"url":"https://miscsubjects.com/api/jarticles/the-graph",
"headers": {
"x-terminal-key":"<YOUR_TERMINAL_KEY>",
"content-type":"application/json",
"if-match":"<hash>"
},
"body": {
"slug":"the-graph",
"title":"…"
}
},
{
"what":"fetch every source, hash what came back and check the quote is in it",
"method":"POST",
"url":"https://miscsubjects.com/api/jarticles/the-graph/verify",
"headers": {
"x-terminal-key":"<YOUR_TERMINAL_KEY>",
"content-type":"application/json"
},
"body": {}
},
{
"what":"an Obsidian-style command",
"method":"POST",
"url":"https://miscsubjects.com/api/jarticles/cli",
"headers": {
"x-terminal-key":"<YOUR_TERMINAL_KEY>",
"content-type":"application/json"
},
"body": {
"command":"backlinks",
"file":"the-graph"
}
}
],
"entities": {
"the-graph": {
"id":"the-graph",
"label":"The Graph",
"type":"article",
"page":"https://miscsubjects.com/a/the-graph",
"json":"https://miscsubjects.com/a/the-graph.json"
},
"cyrus-massoumi": {
"id":"cyrus-massoumi",
"label":"Cyrus Geav Massoumi",
"type":"person",
"page":"https://miscsubjects.com/a/cyrus-massoumi",
"json":"https://miscsubjects.com/a/cyrus-massoumi.json"
},
"337-melrose-avenue": {
"id":"337-melrose-avenue",
"label":"337 Melrose Avenue, Mill Valley",
"type":"house",
"page":"https://miscsubjects.com/a/337-melrose-avenue",
"json":"https://miscsubjects.com/a/337-melrose-avenue.json"
}
},
"relationships": {
"upward": {
"total":0,
"offset":0,
"limit":50,
"items": [],
"next":null
},
"downward": {
"total":0,
"offset":0,
"limit":50,
"items": [],
"next":null
},
"sideways": {
"total":0,
"offset":0,
"limit":50,
"items": [],
"next":null
},
"references": {
"total":2,
"offset":0,
"limit":50,
"items": [
{
"ref":"337-melrose-avenue",
"predicate":"references",
"subject":"the-graph",
"object":"337-melrose-avenue"
},
{
"ref":"cyrus-massoumi",
"predicate":"references",
"subject":"the-graph",
"object":"cyrus-massoumi"
}
],
"next":null
},
"referenced_by": {
"total":0,
"offset":0,
"limit":50,
"items": [],
"next":null
}
},
"hierarchy": {
"paths": [],
"order":"subject to parent to ancestor",
"complete":true,
"cycles": [],
"limits": {
"depth":12,
"objects":250
},
"unresolved_refs": []
},
"reference_contract": {
"canonical_id":"slug",
"entity_lookup":"entities[ref]; # resolves to this object via self_ref",
"self_ref":"the-graph",
"entity_fields":"page and json are canonical object links; source_url is the external source",
"directions": {
"upward":"Parents and collections containing this object; predicate distinguishes location from membership.",
"downward":"Objects naming this object as their parent, container or collection.",
"sideways":"Associations and objects sharing a direct parent.",
"references":"Objects referenced by this record.",
"referenced_by":"Published articles referencing this record."
},
"predicates": {
"part_of":"Declared parent hierarchy.",
"located_in":"Location asserted on this object.",
"associated_parcel":"Associated parcel, a separate object with its own jurisdiction and facts.",
"member_of":"Collection membership, not geographic containment.",
"included_in":"Editorial nesting, not geographic containment.",
"shares_parent":"Shares the identified parent; no other relationship is implied.",
"related_to":"An association with no more specific predicate recorded."
},
"scope":"Published article objects; Atlas inventories have their own counted, paged links. An association does not transfer facts or jurisdiction. An absent neighborhood means no neighborhood relationship is recorded."
},
"hash_spec": {
"algorithm":"sha256",
"encoding":"lowercase hexadecimal",
"scope":"stored record; hash is also the write concurrency token",
"included_keys": [
"body",
"created",
"kind",
"schema",
"slug",
"status",
"title",
"type",
"updated",
"version"
],
"field_overrides": {
"schema":"jarticle/1"
},
"canonicalization":"Select included_keys from this response, apply field_overrides, recursively sort object keys using JavaScript Object.keys().sort(), retain array order, serialize primitives with JSON.stringify, join without whitespace, hash UTF-8 bytes.",
"updated_included":true,
"generated_fields":"All fields absent from included_keys are excluded. Relationship counts and theme references are generated and can change without changing the stored-record hash."
}
}