Skip to content

Commit 4bb5f85

Browse files
committed
Add Claude project context documentation
1 parent ec67084 commit 4bb5f85

10 files changed

Lines changed: 478 additions & 1 deletion

CLAUDE.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# UX Methods
2+
3+
## Identity & scope
4+
5+
This repository is **UX Methods** — Andy Fitzgerald's personal knowledge-graph project, published at [uxmethods.org](https://www.uxmethods.org/). It is **separate from his Elemeno Health work**. Do not assume Elemeno conventions, schemas, tooling choices, or codebase patterns carry over here; treat this project on its own terms.
6+
7+
## What UX Methods is
8+
9+
UX Methods provides a roadmap between and across the practices of user experience design. Its goal is to help UX practitioners arrive at purposeful, high-impact, user-centered design outcomes.
10+
11+
The web has no shortage of techniques, tools, and tips on how to "do" UX. Very few resources, however, explain how to use UX methods _together_, in a coordinated and purposeful way, to create holistic solutions. UX Methods fills that gap by:
12+
13+
- Assembling concise, reliable descriptions of UX method goals, steps, and outcomes
14+
- Highlighting the meaningful relationships between methods so practitioners can craft holistic, purpose-driven project plans
15+
- Collecting and contextualizing in-depth how-tos, case studies, and research from trustworthy sources on the web
16+
17+
## Project goal — knowledge graph maturation
18+
19+
UX Methods today uses a light taxonomy to coordinate methods. The active goal is to build on that foundation so the content collection, external resources, and semantic models become a **proper knowledge graph** that delivers significant value above and beyond the sum of its parts.
20+
21+
Specifically:
22+
23+
- Use knowledge-graph approaches to enrich content, sharpen the expression of ideas, and improve the user experience
24+
- Build and demonstrate a skillset focused on generating new value and insight through the combination of structured, composable content and formal, domain-specific semantics
25+
- **Preferred (not required):** make use of OWL, SPARQL, and semantic inference
26+
- **Optional, where helpful:** SHACL, R2RML, and OTTR templates
27+
28+
When proposing changes to the graph layer, lean into these technologies rather than ad-hoc procedural workarounds; that's the demonstration this project exists to provide.
29+
30+
## Repository layout
31+
32+
Monorepo (pnpm workspaces — see `pnpm-workspace.yaml`):
33+
34+
- **`studio/`** — Sanity Studio. Source of truth for content: methods, disciplines, external resources, and the inputs/outputs (IO) taxonomy. Schemas in `studio/schemaTypes/`.
35+
- **`astro/`** — The public uxmethods.org website, built with Astro from Sanity content. Supports Sanity Visual Editing for real-time previews.
36+
- **`graph/`** — Knowledge graph assets (see "KG architecture" below for layer details).
37+
- **`functions/`** — Sanity Functions.
38+
- **`sanity.blueprint.ts`** — Sanity blueprint config.
39+
40+
**Triplestore:** Apache Jena **TDB2** behind a **Fuseki** front end, hosted on a Raspberry Pi at home and exposed publicly through nginx + a Cloudflare Tunnel at `fuseki.uxmethods.org`. The active production dataset is `/ds`; two experimental inference datasets (`/ds-owl`, `/ds-rdfs`) are configured but currently empty. Read endpoint (`/ds/query`) is open; write endpoints (`/ds/data`, `/ds/update`) are gated at nginx by an `X-API-Token` header. Astro queries Fuseki at build time; the export scripts in `graph/scripts/` push named graphs via the Graph Store Protocol. **See [graph/INFRASTRUCTURE.md](graph/INFRASTRUCTURE.md) for the full deployment, dataset, auth, and cleanup-backlog details.**
41+
42+
**URI policy:** taxonomy concepts use hash URIs (`https://uxmethods.org/taxonomies/io#<conceptId>`); ontology terms and method instances use slash URIs. The concept-scheme IRI doubles as the named-graph IRI. See [ADR 0002](docs/decisions/0002-uri-policy-hash-vs-slash.md).
43+
44+
**Query convention:** the `/ds` dataset has `unionDefaultGraph` disabled — queries that touch taxonomy triples must use explicit `GRAPH <…> { … }` clauses. See [ADR 0003](docs/decisions/0003-explicit-graph-clauses.md).
45+
46+
## KG architecture — three layers
47+
48+
The single most important architectural decision in this project: the graph is deliberately separated into three layers that evolve at different speeds. Preserve this separation when proposing changes.
49+
50+
### 1. Ontology (TBox) — curated, stable
51+
52+
- File: `graph/ontologies/uxmethods-core.ttl`
53+
- Contains: classes, object properties, utility alignments (notably **PROV**).
54+
- Edited by hand. Versioned. This is the **stable semantic contract** that downstream tools depend on.
55+
56+
### 2. Taxonomy (SKOS) — generated from Sanity, replaceable
57+
58+
- Generated file: `graph/build/io-taxonomy.ttl`
59+
- Inputs/outputs modeled as `skos:Concept` instances.
60+
- Concept scheme IRI: `https://uxmethods.org/taxonomies/io`
61+
- Concept IRIs: `https://uxmethods.org/taxonomies/io#<conceptId>`
62+
- Generator: `graph/scripts/push-io-taxonomy.js` — fetches scheme + concepts via GROQ, writes Turtle, optionally PUTs to Fuseki via Graph Store Protocol into the named graph above (using `X-API-Token` header).
63+
64+
### 3. Methods data (ABox) — generated from Sanity, replaceable
65+
66+
- Generated file: `graph/build/methods-data.ttl`
67+
- Method IRIs: `https://uxmethods.org/method/<Slug>` (e.g. `…/method/Wireframing`).
68+
- Methods are linked to SKOS concepts via `uxm:usesInput` / `uxm:producesOutput`.
69+
- Generator: `graph/scripts/method-export.js`.
70+
71+
**Generated artifacts are disposable.** Regenerate from Sanity whenever content changes. Only TBox files in `ontologies/` are hand-curated. Both generators emit `owl:Ontology` headers so Protégé imports them by logical IRI without "physical URI" warnings — preserve this when modifying the exporters.
72+
73+
## Local prototyping (Protégé workspace)
74+
75+
Open one file in Protégé and the whole integrated KG comes with it:
76+
77+
- `graph/ontologies/workspace.ttl` — wrapper ontology that imports the core ontology, the IO taxonomy export, and the methods export.
78+
- `graph/ontologies/catalog-v001.xml` — maps the logical IRIs of those imports to local files in the repo.
79+
80+
When iterating locally, point Protégé at `workspace.ttl` and register the catalog. Don't edit generated files in `build/` — change the source in Sanity and re-run the exporter.
81+
82+
**Snap SPARQL vs built-in SPARQL — important trap:**
83+
- Protégé's **Snap SPARQL plugin queries over inferred facts** (it runs against the reasoner's materialized model).
84+
- Protégé's **built-in SPARQL tab queries asserted triples only** — inferred edges (from property chains, etc.) will not appear.
85+
86+
If a query "works in Snap SPARQL but returns nothing in the built-in tab," that's the reason. This is a preview of the same question we'll face in Fuseki: inference-at-query-time vs derived-graph materialization (see below).
87+
88+
## Method-to-method relationships
89+
90+
Methods are connected through the **inputs/outputs (IO) taxonomy**. A concept that is an _output_ of one method is an _input_ to another (e.g. "user's mental model" is an output of contextual research and an input to navigation design). This IO model is the seed the larger knowledge graph builds on — keep it intact when proposing schema or ontology changes.
91+
92+
### SPARQL-based relationship logic
93+
94+
Today the site computes relationships via SPARQL joins:
95+
96+
- **Upstream methods:** "who produces what I need" (their outputs match my inputs).
97+
- **Downstream methods:** "who needs what I produce."
98+
- **Weights:** `COUNT(DISTINCT ?shared)` over shared IO concepts.
99+
- **Multi-origin variant:** a UNION/`VALUES` query that runs for one or many origin methods at once.
100+
101+
Reference query: `graph/queries/method-output-enables-method-input.rq`.
102+
103+
### Inference work in progress
104+
105+
Some of this join logic is being moved into ontology semantics:
106+
107+
- Object properties `uxm:hasUpstreamMethod` and `uxm:hasDownstreamMethod` are defined in the core ontology.
108+
- **OWL property chain axioms** let a reasoner infer these edges from `usesInput` / `producesOutput` + shared concepts.
109+
110+
Note that plain RDFS inference will **not** apply OWL property chains — you need an OWL-capable entailment regime (OWL RL or rules).
111+
112+
## Open architectural decision — how inference runs in production
113+
114+
There are two viable production paths. Both are real; the project hasn't committed yet.
115+
116+
### A. Query-time inference in Fuseki
117+
Configure Fuseki with an OWL-capable reasoner so `hasUpstreamMethod` / `hasDownstreamMethod` appear as entailments at query time. Simpler conceptually; performance and entailment-regime selection are the questions.
118+
119+
### B. Materialized derived graph (currently the pragmatic favorite)
120+
A scheduled step computes upstream/downstream edges, weights, and optional explanations (which shared concepts caused each link), and writes them into a derived named graph (e.g. `https://uxmethods.org/graph/derived`). UI queries hit asserted triples only — extremely fast, easy to explain, easy to debug.
121+
122+
When making suggestions in this area, weigh both options honestly; don't quietly default to one. The "fast product value + strong foundation" framing tends to favor (B) once performance matters, but (A) is the more semantically pure demonstration.
123+
124+
## Future direction — richer plan semantics
125+
126+
Longer-term, methods may be modeled as structured **plans** (steps, prerequisites, outputs) using **P-Plan** / **PROV Plan**, with executions and case studies mapped onto those plans. Not active work yet; flag it if proposed changes would constrain that direction.
127+
128+
## Working principles for this repo
129+
130+
- **Lean into formal semantics.** This project exists to demonstrate KG approaches — prefer OWL/SPARQL/SHACL solutions over ad-hoc procedural workarounds when working on the graph layer.
131+
- **Stable IRIs and predicates.** Downstream tools (eventual plan builder / stack generator) depend on them. Don't rename casually.
132+
- **Generated vs curated.** Treat `graph/build/*` as disposable. Treat `graph/ontologies/*` as the contract.
133+
134+
## Where to find things
135+
136+
- **[graph/README.md](graph/README.md)** — local development: IRI conventions, named-graph strategy, Protégé workflow, exporter script usage, troubleshooting.
137+
- **[graph/INFRASTRUCTURE.md](graph/INFRASTRUCTURE.md)** — production deployment: topology diagram, Fuseki datasets, endpoints, auth, GSP, and the operational cleanup backlog.
138+
- **[docs/decisions/](docs/decisions/README.md)** — architecture decision records (ADRs). Significant choices like the three-layer separation, URI policy, the `unionDefaultGraph` stance, and the open production-inference question live here with their rationale.
139+
- **[astro/CLAUDE.md](astro/CLAUDE.md)** — how the site talks to Sanity and Fuseki, current SPARQL integration shape, and the conventions to follow when adding queries.
140+
141+
When adding new context that isn't a fit for any of these, prefer extending one of them over creating yet another doc. New ADRs are fine and encouraged for significant decisions.

astro/CLAUDE.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Astro — UX Methods website
2+
3+
This is the public site (`uxmethods.org`) and the preview/SSR build (`preview.uxmethods.org`). It pulls **content** from Sanity (GROQ) and **method-to-method relationships** from Fuseki (SPARQL).
4+
5+
For project-wide context, see the root [CLAUDE.md](../CLAUDE.md). For environment setup, env vars, and dev/preview/build commands, see [README.md](README.md). For the Fuseki deployment specifics, see [../graph/INFRASTRUCTURE.md](../graph/INFRASTRUCTURE.md).
6+
7+
## Two data sources
8+
9+
- **Sanity (GROQ)** — methods, disciplines, external resources, IO taxonomy concept labels. Source of truth for content. Reads use `@sanity/client` via `src/sanity/lib/load-query`.
10+
- **Fuseki (SPARQL)** — semantic relationships between methods. Reads use plain `fetch` POSTs to `https://fuseki.uxmethods.org/ds/query` with `Content-Type: application/sparql-query` and `Accept: application/sparql-results+json`.
11+
12+
The read endpoint is unauthenticated. The Astro build never writes to Fuseki — only the `graph/scripts/*` exporters do.
13+
14+
## Where the Fuseki integration lives today
15+
16+
The only page that queries Fuseki right now is `src/pages/method/[slug].astro`. It:
17+
18+
1. Fires a `getStaticPaths` GROQ query to enumerate method slugs.
19+
2. In parallel, runs one global SPARQL query (`getSharedOutput`) that computes shared input/output counts across **all** method pairs, then filters client-side per page.
20+
21+
This works but is not the long-term shape. Two known gaps, both tracked in [../graph/INFRASTRUCTURE.md](../graph/INFRASTRUCTURE.md) cleanup backlog:
22+
23+
- **The query is global, not method-scoped.** A `TODO` in the file notes the intent to narrow it. Method-scoped queries (and direct joins against SKOS concepts in their named graph) are the planned direction.
24+
- **The predicates don't currently match the curated ontology.** The live query uses `uxmo:hasInput` / `uxmo:hasOutput` in the namespace `https://uxmethods.org/ontology/`. The curated ontology (`graph/ontologies/uxmethods-core.ttl`) and the current exporter (`graph/scripts/method-export.js`) use `uxm:usesInput` / `uxm:producesOutput` in `https://uxmethods.org/ontologies/uxmethods-core#`. **Verify which vocabulary is actually loaded in Fuseki before changing either side** — the query may match older data that hasn't been re-exported under the new predicates.
25+
26+
## SPARQL conventions to follow when modifying or adding queries
27+
28+
- **Use explicit `GRAPH <…> { … }` clauses** when reading the IO taxonomy. The `/ds` dataset has `unionDefaultGraph` disabled, so named-graph triples are invisible from the default graph. See [../docs/decisions/0003-explicit-graph-clauses.md](../docs/decisions/0003-explicit-graph-clauses.md).
29+
- **Don't assume inference at query time.** The production inference strategy is unresolved (see [../docs/decisions/0004-production-inference-strategy.md](../docs/decisions/0004-production-inference-strategy.md)). Today, queries should derive relationships from asserted `usesInput`/`producesOutput` (or whatever current data uses) rather than relying on entailed `hasUpstreamMethod` / `hasDownstreamMethod`.
30+
- **Prefer method-scoped queries over global ones.** Bind the current method's IRI via `VALUES ?method { <…> }` rather than computing relationships across the entire graph and filtering in JS.
31+
- **Result mapping lives next to the query.** See `transformKgData` / `mapMethods` in `src/pages/method/[slug].astro` for the existing shape.
32+
33+
## Auth between Astro and Fuseki
34+
35+
The page reads from `/ds/query`, which is open. `KG_AUTH` is declared in the env (`PUBLIC_*` for the env, `KG_AUTH=` for the secret) and historically intended for write paths — but Astro doesn't write to Fuseki, so it isn't currently sent on any request. If you ever wire Astro to a protected endpoint, the header is `X-API-Token: <token>` (see [../graph/INFRASTRUCTURE.md](../graph/INFRASTRUCTURE.md)).
36+
37+
## Build modes (cheat sheet)
38+
39+
`README.md` is canonical; the short version:
40+
41+
- **SSG / production build:** `astro build` against published Sanity content. Reads Fuseki at build time. Static output served by nginx.
42+
- **SSR preview:** `preview.uxmethods.org`, draft perspective, Sanity stega + overlays for Visual Editing.
43+
- **Local published mode:** `pnpm dev` with `.env.published.local`.
44+
- **Local drafts mode:** `pnpm preview` with `.env.drafts.local` and a Sanity read token.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# 0001 — Three-layer KG separation (TBox / SKOS / ABox)
2+
3+
**Status:** accepted
4+
5+
## Context
6+
7+
UX Methods needs to evolve a thin coordinating taxonomy into a real knowledge graph without entangling stable semantics with content-derived facts. Content (methods, IO concepts) is authored in Sanity and changes frequently; the semantic model of "what a method is and how it relates to its inputs and outputs" changes much less often.
8+
9+
If curated semantics and exported content end up in the same file or load path, every content edit risks bleeding into the contract, and every contract change risks invalidating exported data without anyone noticing.
10+
11+
## Decision
12+
13+
The graph is split into three layers, each owned by a different mechanism:
14+
15+
1. **Ontology (TBox)**`graph/ontologies/uxmethods-core.ttl`. Curated by hand, version-controlled, treated as a stable contract. Includes alignments such as PROV.
16+
2. **Taxonomy (SKOS)**`graph/build/io-taxonomy.ttl`. Generated by `graph/scripts/push-io-taxonomy.js` from Sanity. Disposable.
17+
3. **Methods data (ABox)**`graph/build/methods-data.ttl`. Generated by `graph/scripts/method-export.js` from Sanity. Disposable.
18+
19+
Both generators emit `owl:Ontology` headers so Protégé imports them by logical IRI rather than physical file path.
20+
21+
## Consequences
22+
23+
- **Regenerate, don't edit.** Hand-edits to files in `graph/build/` are not allowed; they will be overwritten on the next export. Behavioural changes to generated data are made by editing Sanity content or the exporter scripts.
24+
- **Stable contract surface.** Downstream tools (eventual plan builder / method-stack generator) depend on stable IRIs and predicates from the ontology layer. Renames in the TBox are breaking changes.
25+
- **Independent evolution.** Schema work in Sanity does not require ontology changes; ontology refactors do not require content republishing (beyond a re-export).
26+
- **Local prototyping works.** `graph/ontologies/workspace.ttl` plus a Protégé catalog wraps all three layers into one merged model for SPARQL iteration.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# 0002 — URI policy: hash for taxonomy, slash for ontology and instances
2+
3+
**Status:** accepted
4+
5+
## Context
6+
7+
The project mints IRIs for three different kinds of resources: SKOS concepts in the IO taxonomy, ontology terms (classes and properties), and method instances. Picking hash (`…#term`) vs slash (`…/term`) URIs has implications for HTTP dereferenceability, partitioning of triples on the web, and how Fuseki named graphs line up with scheme IRIs.
8+
9+
## Decision
10+
11+
Use a **mixed** strategy:
12+
13+
- **Taxonomy (SKOS concepts):** **hash URIs.**
14+
- Concept scheme IRI: `https://uxmethods.org/taxonomies/io`
15+
- Concept IRIs: `https://uxmethods.org/taxonomies/io#<conceptId>`
16+
- The concept-scheme IRI doubles as the Fuseki **named graph IRI** for the taxonomy. They intentionally match.
17+
- **Ontology terms (classes, properties):** **slash URIs** under an ontology namespace (current canonical: `https://uxmethods.org/ontologies/uxmethods-core#…`; an older `https://uxmethods.org/ontology/…` namespace is still present in some live data and is part of the alignment cleanup).
18+
- **Method instances:** **slash URIs**, e.g. `https://uxmethods.org/method/<Slug>`.
19+
20+
## Consequences
21+
22+
- **One HTTP fetch returns the entire taxonomy.** Hash URIs share a base document, which is appropriate for SKOS — concepts are usually consumed as a set.
23+
- **Named-graph IRI doubles as scheme IRI.** Writers and queries can refer to the same string for both purposes, reducing the chance of drift.
24+
- **Methods and ontology terms can dereference individually** when slash URIs are eventually backed by per-resource HTTP responses.
25+
- **The mixed model is acceptable and intentional.** Don't "normalize" one side to match the other on aesthetic grounds.
26+
- **Predicate-namespace drift exists today.** The live Astro query uses an older `…/ontology/…` namespace; the curated ontology uses `…/ontologies/uxmethods-core#…`. Aligning these is tracked in the infrastructure cleanup backlog, not by changing the policy here.

0 commit comments

Comments
 (0)