Relay

Agents that finish the job.

Fig. 1 — Relay, live captureOpen the live demo ↗12 s loop · recorded frame by frame on GPU

Field notes

A landing page for an AI agent that isn't purple: ink on warm paper, one orange. The hero is a live tool-call graph where every call leaves a wet-ink trail, tools answer when you click them, and scrolling folds the whole run into a timeline. One raw WebGL2 shader, no three.js.

  • WebGL shader
  • Scroll-driven
  • Pointer interaction
  • AI agent
  • Light theme

Relay is the site of Quirewright, a fictional agent runtime: a hero, a run log, How it works, a price list and a closing call to action. The hero draws the agent and six tools as a graph on dotted paper. A scripted run sends orange pulses down the edges, sometimes to two tools at once, and each one leaves a ragged ink trail that dries as the next call goes out. Edges lean toward the cursor, and every tool is a real button: click one and the agent pings it, and the answer is typed into the log.

Scroll and the graph folds into a single column in call order, each stop labelled with its call and timing, and a pulse replays the run down it. Below that, four How-it-works drawings ink themselves in, and the pricing is a torn till receipt. Until someone moves the mouse, scrolls or touches the page, the hero plays its own 12-second tour. Your tools, the run and the prices each live in one file, and anyone who prefers reduced motion gets a still graph that still answers clicks.

How it's built

  • One full-screen WebGL2 fragment pass draws the paper, the dotted grid, every edge, the pulses and the nodes. Each edge is a quadratic curve cut into 10 straight pieces in JavaScript and sent as a uniform array, so the shader only measures distance to segments.
  • The wet-ink trail is per edge: the shader knows how far along the edge each pixel is, lights the stretch just behind the pulse head, roughens its width with a fixed hash and adds a faint stain around it, then the whole trail fades as it dries.
  • The run is a pure function of time: heat, trails, pulses and the typed log come from the events of this loop and the last, never from a per-frame decay. Any frame can be drawn on its own, so the recorder can jump straight to it and frame 0 matches frame 12 pixel for pixel.
  • Scrolling the sticky stage sets a fold from 0 to 1. Each node slides from the graph layout to one column, curves swap their bow for arcs left of the column, and the DOM labels slide from under the node to its right, where the call and its timing fade in.
  • Tool nodes are real buttons laid over the canvas, so clicks, keyboard focus and screen readers work without hit-testing pixels; a click adds a ping event to the same timeline the scripted run uses.

Inside the prompt

Every file below is written out in full, so your agent creates the project exactly — no guessing, no missing pieces.

relay-agent/
├─ .gitignore
├─ index.html
├─ package.json
├─ tsconfig.json
├─ vite.config.ts
└─ src/
   ├─ App.tsx
   ├─ index.css
   ├─ main.tsx
   ├─ vite-env.d.ts
   ├─ components/
   │  ├─ Cta.tsx
   │  ├─ Header.tsx
   │  ├─ HowItWorks.tsx
   │  ├─ Pricing.tsx
   │  └─ Stage.tsx
   └─ lib/
      ├─ graph.ts
      ├─ loop.ts
      ├─ motion.ts
      ├─ run.ts
      ├─ shaders.ts
      └─ timeline.ts

Recut it

  • Rename the tools and their run-log labelssrc/lib/graph.ts → NODES / EDGES
  • Rewrite the agent's run and the log linessrc/lib/run.ts → STEPS
  • Move the graph or the folded columnsrc/lib/graph.ts → WIDE / TALL / nodeAt()
  • Change the plans and pricessrc/components/Pricing.tsx → PLANS
  • Rename the product and rewrite the herosrc/components/Stage.tsx → Stage()
  • Change the colours and fontssrc/index.css + src/lib/shaders.ts → @theme / PAPER, INK, ACCENT
  • Retime the demo toursrc/lib/timeline.ts → ARRIVE / PING_AT / FOLD_IN / REPLAY_AT

More in Landing Page

All landing page templates →