Ask the Path
· Part 1query() and queryAll() ask a path for things by kind — every arc, every corner, everything one circle() drew — and hand back objects that know their own geometry.
Tutorials, deep-dives, and updates about pathogen-lang — written in plain language for people who build things with code
Series · 5 parts
Drawing and designing in parallel: a form on one side, its schematic twin on the other, nothing copied between them. Queries, subscriptions, then a linkage, a front panel and a fretboard.
query() and queryAll() ask a path for things by kind — every arc, every corner, everything one circle() drew — and hand back objects that know their own geometry.
subscribe a selector to a layer and the annotations follow the drawing — the window, the ordering, the rounds, and the one closure caveat.
A four-bar linkage drawn once, and a twin that names its pivots, dimensions its links and runs the Grashof test on numbers it asked for.
A Eurorack front panel drawn in millimetres, with HP as the only parameter, that numbers its holes and prints the drill schedule the shop needs.
A fretboard placed from one scale length by the twelfth root of two, and a twin that numbers the frets, prints their distances, and fans at the end.
A practical walkthrough of Pathogen's easing curves through lambdas: build an eased t once, then feed it to ranges, amplitudes, and cycles and half-cycles, ending with a finished piece.
Pathogen has a switch statement. It borrows the keyword from JavaScript, the pattern matching from Swift, and the range cases from Ruby, then drops fallthrough. Values, ranges over numbers and angles, destructured Points and arrays, where guards, and an expression form that drops straight into a let or a path argument.
Series · 5 parts
Five posts on stroke geometry — dash(), outline(), and startAt() — from bare mechanism to three crafts built on interrupted lines: sashiko stitching, leather stitch holes, and stencil bridges. Written as a working friction log; the closing post reports what building these taught the language.
First in Broken Lines, a five-part series on stroke geometry: dash() partitions a path into its dash and gap pieces, outline() turns a stroked line into a closed, fillable shape, and startAt() decides where a closed path begins.
Second in Broken Lines: a running stitch is a dash pattern, hitomezashi is one bit of dash offset per line, and a 138 × 90 mm mend-patch template falls out of a nested loop.
Third in Broken Lines: a punch hole is a near-zero dash outlined round, negative dash offsets center the run, and two mating seams derive their holes from one shared edge — so the counts match by construction.
Fourth in Broken Lines: a stencil's islands fall out unless bridges hold them — and a bridge is a gap in a dashed centerline, outlined to the band width and cut with difference().
Closing Broken Lines: the friction log. Building sashiko, leather, and stencil artifacts against the real language filled the log — five entries became fixes — the last one landing after publication, in the session this post promised it, and the rest are on the bench with their diagnoses attached.
Series · 4 parts
Four projects that put PathBlock.cut() and segment labels to work together — papercraft, a jigsaw, a garment pattern, and a stained-glass window. Each starts from one bare mechanism and climbs to a finished composition.
First in The Cutting Room, a four-project series on cut() + segment labels: fold lines, glue tabs, named pieces, and an exploded view, all queried from the pieces themselves — not bookkept.
Part 2 of The Cutting Room: the knife is a path, so jigsaw nubs are just cubics — and after the cut, labels classify the pieces, partition marks register twin seams, and rotate() scatters everything without pivot bookkeeping.
Part 3 of The Cutting Room: draft a half-bodice with every edge named, split it at the yoke, and let the labels run the workflow — pieces identify themselves, allowances offset without losing their names, and notches land matched on both halves.
The Cutting Room finale: a rose window where the cut is the artwork — came stroked from the seam group, panes tinted by layer routing, labels from both boolean operands coexisting, and solder dots at every joint.
Series · 5 parts
PathBlocks turn SVG paths into first-class values — this series builds from the basics through sampling, corner shaping, boolean operations, and cutting shapes apart.
PathBlock.cut() slices a shape along the strokes of a second PathBlock — a knife — and returns the pieces: closed shapes healed shut along the cut, open paths severed into fragments.
Series · 7 parts
Seven short guides to the functions behind Pathogen's repeatable randomness — random-looking values that never change between runs — and the smooth curves that shape them. Each starts from a bare picture of one function and climbs to a finished composition you could ship.
First in a seven-part tour of Pathogen's deterministic stdlib: hash01 gives every whole-number label a random-looking value that is really a lookup — same label, same answer, on every machine, forever. Scatter, jitter, and texture you can ship.
Part 2 of the stdlib primers: hash11 is hash01's twin for nudges — signed, deterministic jitter in [−1, 1). Baseline wobble, tilt, and the ±20% idiom that textures the blog's glow strokes.
Part 3 of the stdlib primers: hashRange(i, min, max) is the deterministic drop-in for randomRange — put an index in front and the pick keeps its word forever. Ranges become the design's tuning panel.
Part 4 of the stdlib primers: smoothstep is a dimmer between two markers — 0 before, 1 after, a corner-free glide in between. Fades, plateaus, tapered stroke tips, and a dusk seascape with no gradients.
Part 5 of the stdlib primers: bump is one smooth hill — exactly 1 at the center you pick, exactly 0 at the spread you pick, flat everywhere it matters. Hills sum into spotlights, mountains, and the width envelopes behind the blog's glow strokes.
Part 6 of the stdlib primers: hash01 rolls dice; noise draws the smooth curve through the rolls. Pins and a glide, one frequency knob, and randomness that neighbors agree on — texture instead of jitter.
The stdlib primers finale: noise2 spreads smooth randomness across a surface — fog, terrain, warped grids, and the trick that makes a whole family of strokes flow as one. The series' three glows, compared.
'The Shape of a Stroke' ended with a glow built on a hand-rolled hash and a hand-rolled envelope. Both are now built in — and the built-in hash is a better one: bit-identical on every JavaScript engine, not just deterministic on yours. This post rebuilds the glow on hash11() and bump(), then goes somewhere the hash can't: continuous texture with noise() and a coherent 2D field with noise2().
Variable-width strokes get interesting when the width itself becomes a designed object — an envelope you can shape, compose, and reuse. This post builds a richer stroke step by step, shows where the abstraction outgrows named functions, and introduces Pathogen's new lambda expressions: {|a, b| ... } as a first-class closure.
Pathogen Studio's Export dialog ships today: three formats, an optional legend with syntax-highlighted source, and a live preview that is exactly what you download.
Pathogen paths become collections of richly defined segments — label edges and vertices where you draw them, round corners at the point of definition, and query it all back by name.
Two new PathBlock methods — variableOffset and compoundVariableOffset — turn any path into a rail for expressive, variable-width strokes. We build up from the rail model to curvature-continuous joins, filled ribbons with end caps, and a glyph-wrapped Pathogen wordmark.
Five more custom filters that close the gaps native CSS leaves open: outer/inner glow, embossed surfaces, Material-style elevation shadows, inset shadows, and pixelation — all configured by named parameters, all composable via GroupLayer.
Pathogen's custom filters are first-class language values — defined once, reused, introspected, and composed in ways native CSS filter functions can't match. A walkthrough of the pipeline, anchored by NoiseFilter.
Build Clifford attractor visualizations from scratch — iterative chaos math, efficient point rendering, color mapping strategies, and where the language hits its limits.
From Lezer migration to a full IDE experience — how we built a VS Code extension with live preview, intelligent completions, refactoring, and 16 language server features for the Pathogen SVG language.
Build a radial bar chart from scratch — annular sector geometry, data-driven loops, rotated labels, and new stdlib functions for polar data visualization.
Three stdlib functions that generate complete grid geometries — squares, equilateral triangles, and hexagons — with four visual pattern types each.
Two stdlib functions that set and rotate the pen's direction without emitting path commands — enabling tangentLine and tangentArc immediately after M, and clean z closure in PathBlocks.
Three stdlib functions that turn waypoints into G1-continuous Bézier curves — cubicSpline for explicit tangent control, quadSpline for implicit angles, and clippedQuadSpline for eccentricity dampening.
Turn font glyphs into PathBlock geometry — manual text layout, contour decomposition, per-character transforms, and boolean text cutouts.
Compose, measure, and position text before drawing — collision-free label placement for parametric SVG diagrams.
A UX bug became a language feature — bare hex codes, CSS color functions, and the percent suffix are now first-class expressions in Pathogen.
How Pathogen's gradient system flows from .pathogen source through the compiler, GPU renderer, and blog build pipeline to produce the interactive demos in this series.
What if gradient color stops were not positions on a line, but closed paths? TopoGradient uses signed distance fields and Laplace solvers to create terrain-like gradients from arbitrary contour shapes.
SVG2 proposed mesh gradients, then abandoned them. Pathogen implements both grid-based mesh gradients and scatter-based freeform gradients with GPU-accelerated rendering.
SVG has no conic gradient primitive. Pathogen adds one with partial sweeps, inner radius, direction control, and a WebGPU rendering pipeline that falls back gracefully to Canvas 2D.
How Pathogen turns SVG's linearGradient and radialGradient into programmable, composable building blocks with OKLCH interpolation, spread methods, and gradient inheritance.
How Pathogen's Color system turns SVG into a reactive medium — from OKLCH color manipulation to CSS-variable-driven theming that updates at runtime.
After solving SPA routing on CloudFlare Pages, we needed to add server-rendered and static pages alongside the SPA. New platform, new surprises — 308 redirects, stale workers, build pipeline ordering, and the art of making static and dynamic content coexist.
How programmatically created SVG elements silently produce broken output when serialized with XMLSerializer and loaded as images — and the surprisingly simple fix.
A developer's journey through documentation gaps when trying to make SPA routing work on CloudFlare Pages with subdirectory deployments.