master
Download ZIP Propose a change
Name Last commit message Last updated
docs Publish 0.1.2 · AdityaAngajala 3mo ago
screenshots Set hero asset · AdityaAngajala 3mo ago
src Publish 0.3.0 · AdityaAngajala 2mo ago
install.sh Publish 0.3.0 · AdityaAngajala 2mo ago
package.json Publish 0.3.0 · AdityaAngajala 2mo ago
page.json v0.3.0: add tiling reveal and field router v9 · AdityaAngajala 2mo ago
readme.html Publish 0.3.0 · AdityaAngajala 2mo ago
README.md Publish 0.3.0 · AdityaAngajala 2mo ago
SKILL.md Publish 0.3.0 · AdityaAngajala 2mo ago
uninstall.sh Publish 0.1.0 · AdityaAngajala 3mo ago

Circuit Trace Generators

Two independent, dependency-free generators that draw the Adom Nitrogen hero background (procedural PCB traces, vias, and routed light) as seeded SVG.

Both recreate the reference artwork's visual grammar rather than copying its path data, and both were measured off the same original:

Reference constant Value
Routing pitch 7.895 units (150 / 19)
Trace stroke 1.58 units, #151b25
Via annulus 3.34 outer / 1.76 inner
Board #0d1117
Routed-light palette #00e6dc 60%, #64abff 25%, #c5b3ff 15%

They diverge on the thing that matters most: how the board is filled. One routes a torus and tiles forever; the other routes one continuous field at the mount's real size. Pick by whether you want a repeatable texture or a bespoke backdrop.

Tiling router Field router
Fill strategy one 900×450 tile, repeats in both axes one continuous field, no repeat
Router A* nets between placed terminal formations flow field and vortex trace packing
Wrap torus occupancy grid (no seam, no crossings) reserved grid nodes (no crossings)
Headless output generate-tile.mjs writes an SVG tile generateCircuitField() returns geometry
Motion signal fountain or progressive reveal three reveal modes and five ambient systems
Entry file circuit-background.js or circuit-background-reveal.js circuit-background-v9.js
Live demo classic tile and tile reveal v9 field

Both ship createCircuitBackground(mount, options) returning { regenerate, exportSvg, destroy }, both are seeded (the same seed and dimensions give identical geometry), and both honour prefers-reduced-motion.

All three demos run live, hosted on this page. These are the real src/ engines, served by the wiki straight from this page's repo, so they need no container and will not go dark:


1. Tiling router: circuit-background.js

Tiling router output, seed "traces", tiled across 1200x600, click to launch the live demo

▶ Launch the live tiling-router demo · the real engine: drag the twelve generation sliders, switch presets, click the board for a signal burst.

An occupancy-grid router run on a torus, so the 900×450 tile it emits repeats in both axes with no visible seam and no two traces ever cross. That makes its output usable directly as a CSS background-image with background-repeat: repeat.

How a tile is built

  1. placeFormations scatters terminal groups (via ladders and rows) across the grid. These are the pads everything else routes between.
  2. routeNets runs A* between pins, weighted by a turn penalty (higher means longer, calmer runs) and a weave preference for 2-lane neighbour spacing, with a matching cramp aversion to 1-lane spacing outside bundles.
  3. replicateWalk adds translated-copy bundle followers, so neighbouring traces bend together the way a real bus does, re-routed in bundle mode when blocked.
  4. tapCombs and routeStubs add comb and stub motifs as punctuation.
  5. sealEnd enforces the via mandate: every trace starts and ends on a via, trimming blocked ends with per-step claim tracking. A wrap-aware checker passes with zero bare ends.

Tuning

Twelve generation knobs, all exposed as sliders in the demo and as kebab-case flags on the CLI:

density, formations, busWidth, turnPenalty, weave, cramp, horizontalBias, netReach, jogBias, stubChance, inlineViaChance, combs

Motion: the signal fountain

Every signal is mortal. A passive spawn timer (signalInterval, 240 ms) is the fountain: each tick, if the census is under maxSignals (12), one new signal appears near the cursor. pickStart scores the actual launch pad by pointer distance plus spawnRadius jitter, falling back to a whole-board spread when the pointer idles past 4 s. A signal runs to a trace-end via, then rolls its chain's survival: survivors hop to a nearby via (hopRadius 440) inheriting speed, colour, and survival rate, and the rest die so the timer refills next tick. Equilibrium census is roughly spawn rate times life.

Passive and clicked chains decay at separate rates, hopSurvival 0.4 against burstSurvival 0.72, so a clicked burst keeps its own longer life for the whole chain. colorDrift (0.18 per hop) crossfades a leg, and maxBurstSignals (25) is a hard ceiling.

Animation presets: None (the page default, a static board), Fireflies, Swarm, Cursor sparks, Slow streams.

Tiling router demo with the Swarm preset running and the generation panel open

The demo splits its knobs into two panels, Generation tuning and Animation tuning, each with its own reset scoped to just its own sliders.

Headless CLI

node generate-tile.mjs --seed traces --out tile.svg
node generate-tile.mjs --seed foo --turn-penalty 0.8 --bus-width 1.4 --combs 0 --transparent > tile.svg

Seed traces yields 334 traces and 482 vias per tile. Run with --help for the full flag list.

API

import {
  generateCircuitTile, tileSvg, pathData, createCircuitBackground,
} from "./circuit-background.js";

const tile = generateCircuitTile({ seed: "traces", turnPenalty: 0.8 });
const svg = tileSvg(tile, { background: "#0d1117" });

Progressive reveal

Launch the tiling-reveal demo.

circuit-background-reveal.js grows the same tile geometry on a canvas above the static SVG. It redraws only routes that are moving or cooling, then clears the canvas after the glow reaches zero. The handoff reveals the exact SVG without a brightness dip or color jump.

Reveal styles are Etch, Flood, Sweep, Bloom, and Scatter.

See src/TILING-REVEAL.md for the measured implementation notes.


2. Field router: circuit-background-v9.js

Field router output, seed "nitrogen", one continuous 1200x600 field, click to launch the live demo

Launch the live field-router demo to switch geometry, obstacle, reveal, and ambient presets or export the current SVG.

No tile. A deterministic planar trace-packing pass fills one continuous field at the mount's real dimensions with hundreds of independent routes. A rotatable vector field plus seeded, low-frequency vortices organise long carriers, diagonal runs, and gentle swirls, and channel attraction collects nearby routes into natural local buses. Every occupied grid node is reserved, so separate traces never cross.

Version 9 separates geometry, obstacles, reveal, and ambient motion. It can avoid or outline embedded marks, reveal by time or scroll progress, and append seeded world chunks without moving existing geometry. Versions 2 through 8 remain for reference.

Tuning

fill, routeLength, horizontalFlow, flowAngle, diagonalFlow, longFlow, swirl, swirlScale, jogLength, channelAttraction, edgeDensity, featureScale

featureScale proportionally scales routing pitch, trace width, via rings, and routed-light geometry together, so the motif stays coherent at any size.

Geometry presets: Original match (the default, tuned to the reference's path count, route-length distribution, stroke, via count, and orientation mix), Dense, Diagonal sweep, Broad swirl, Sparse. Geometry presets never touch motion settings; the two preset rows are independent.

Ambient systems

Five presets are available in the demo's Animation row:

  • None mounts only the static SVG and creates no animation layer at all.
  • Adom reflection (circuit-animation-reflection.js) sends a restrained brand-color sheen across a precomposed trace mask.
  • Conductor (circuit-animation-conductor.js) is the full system: ambient currents, breathing endpoint nodes, core and halo packets, convoys, timed spatial waves, pointer wake, endpoint flashes.
  • Routed field (animationSystem: "adom", implemented in v4) is a third system, not a retune of the conductor. It drives a slow angled sweep across the board (sweepDuration 15.2 s, sweepAngle 18°) plus periodic blooms that light traces near a moving cursor, capped at three concurrent blooms.
  • Handshake (circuit-animation-handshake.js) is the restrained alternative. Each transaction charges a source via, traverses one complete trace once, settles into its destination via, and sends a dim acknowledgement back. It uses exact polyline intervals instead of wrapping dashes, never flood-lights the field, and avoids the protected hero-copy reading zone. Only maxHandshakes (3) transactions coexist, so per-frame work does not grow with geometry density. That is the reason to reach for it on a dense board.

Field router demo with the Handshake preset active and the parameter panel open

API

import { createCircuitBackground } from "./circuit-background-v9.js";

const circuit = createCircuitBackground(document.querySelector("#hero-circuit"), {
  seed: "product-launch",
  fill: 0.668,
  swirl: 0.28,
  channelAttraction: 0.78,
  obstaclePreset: "adom",
  obstacleMode: "outline-wrap",
  revealSystem: "scroll",
  continuousGeneration: true,
  animationSystem: "reflection",
  liveliness: 0.82,
  motion: true,
});

circuit.regenerate({ seed: "another-layout" });
circuit.triggerAnimation({ x: 240, y: 180 });   // in SVG coordinates
const svg = circuit.exportSvg();                 // static, no motion layers
circuit.destroy();

generateCircuitField(options) returns deterministic geometry with no DOM involvement. Each trace carries points, length, viaStart, and viaEnd, and pathData(points) turns one into SVG path data. That is how the two images on this page were rendered.

The mount needs a real width and height. The helper observes resizes, clips overflow, and leaves pointer interaction to the surrounding page.


Running the demos

On this page (no setup, always up)

All three demos are the actual src/ files, rendered by the wiki straight from this page's repo:

Surface Live on the wiki
All three, embedded on one page render/src/playground.html
Tiling router render/src/index-classic.html
Tiling reveal render/src/index-reveal.html
Field router render/src/index.html

These need no container and do not expire. They run in the render sandbox, which the engines are fine with since they use no storage or network. The playground embeds each demo as an iframe, which works because the page is public.

Locally

The two projects live in adjacent source directories and run on separate ports:

cd ~/project/circuit-generator

# Tiling router, http://localhost:8930
node serve-classic.mjs          # serves index-classic.html + circuit-background.js

cd ~/project/circuit-generator-codex

# Field router, http://localhost:8124
./serve.sh                      # serves index.html via server.js

File map

The two local source directories are combined under src/ in this package:

File Belongs to
circuit-background.js tiling router (engine)
circuit-background-reveal.js tiling router (progressive reveal)
index-classic.html, index-reveal.html tiling demos
generate-tile.mjs tiling router (CLI)
circuit-background-v9.js field router entry
circuit-geometry-v9.js, circuit-obstacles-v9.js field geometry and obstacles
circuit-reveal-*.js field reveal systems
circuit-animation-*.js field ambient systems
index.html, server.js, serve.sh field router (demo, port 8124)
TILING-REVEAL.md, FIELD-ROUTER.md full implementation notes