moveslow.info
This site. A few things about how it works.
the stack
SvelteKit on a DigitalOcean droplet, behind Cloudflare. Content in a managed Postgres database. No CMS — posts are seeded by script, or written directly through an MCP server during Claude sessions.
adapter-node, pm2the paper
The background is a WebGL fragment shader — fractional Brownian motion noise layered to simulate cotton-rag paper fiber, plus the faint horizontal lines left by a wire mesh in handmade paper (called the laid finish). Both effects are kept subliminal: you feel texture without consciously registering it.
The texture drifts imperceptibly over time so it never reads as a static image. The constants below control exactly how much of each effect you see — and you can change them live.
u_grain_amp = 0.016u_grain_scale = 80u_laid_amp = 0.003u_drift = 0.00040the reader
Posts use a two-voice format: sections alternate between hallie (warm) and claude (cool). The reader keeps the current section fully opaque and lets everything else fade and blur as you scroll — so you're always reading one voice at a time, but you can feel the whole conversation around it.
The fade/blur system is pure CSS driven by an Intersection Observer. No layout reflows, no JS animation loops.
the graph
Content is stored in a knowledge graph built on alkahest — a small TypeScript library for reasoning over sets of support. Every post, explainer, and work item is a node. Relationships between them are labeled edges with confidence scores.
Right now most edges are HAS_SECTION — the graph knows which sections belong to which post, and in what order. As the site grows, semantic edges like REFERENCES and RESPONDS_TO will connect ideas across pieces.
hover a node to see its edges — solid lines are HAS_SECTION, dashed are REFERENCES
Alkahest also runs an inference loop called Otter — a forward-chaining reasoner that takes the current set of support and derives new edges. When two posts share a tag, Otter proposes a shares-tag:language edge with a confidence score. A human reviews and keeps or discards it. The graph learns without being told.
the mcp layer
An MCP server at /api/mcp exposes the graph to Claude. During writing sessions, Claude can call add_item, add_edge, add_section, and query — reading from and writing to the graph in real time. This is how most of the reader content gets authored: in conversation, with Claude as co-writer.
The endpoint requires a bearer token, so it's not open to the public — but the graph it produces is what the site runs on.