On a sage dotted canvas, a trigger and five steps drop in and wire together, the workflow goes live, and four order packets flow node to node, splitting at a branch, while a run log fills and an inspector shows a sent message.
Written and rendered by AI CSS Animations Oct 19, 2026
Node-based automation editors let people connect apps without writing code: a trigger starts a run and each step passes its data on to the next. The visual language goes back to flowcharts and to the node graphs of visual effects and audio software, and it became the standard face of integration and workflow tools. In promos the canvas does much of the explaining by itself: the boxes show which apps are involved, the wires show the order, and a packet travelling through the graph shows that the thing actually runs. Good versions keep the graph small enough to read, use real field names and values, and let a few runs play through from end to end.
Make a 10-second workflow automation demo: on a dotted canvas a trigger and five steps drop in and wire themselves together, the workflow goes live, and four order packets flow node to node, splitting at a branch, while a run log fills and a data inspector shows the message that went out.
<inputs>
If I don't give you something, use the default and don't ask.
- Product: Pipewren (fictional), a workflow automation tool. Wordmark "pipewren" beside an original mark: a filled 18px circle with a short tail stroke rising from its back at 30°, a minimal wren.
- Workflow: "Route new orders", in the workspace "Juniper & Moss".
- Nodes (kind · title · app · detail):
N1 · TRIGGER · New order · Storefront · When an order is paid
N2 · ACTION · Look up customer · CRM · Find contact by email
N3 · BRANCH · Check order total · Branch · total ≥ $250
N4a · ACTION · Alert VIP team · Team chat · #vip-orders (the Yes path)
N4b · ACTION · Add to daily digest · Email · digest@juniperandmoss.co (the No path)
N5 · ACTION · Log to sheet · Spreadsheet · Orders 2026
- Runs (order · customer · total · path · duration): #4821 · Mara Lindqvist · $318.00 · VIP alert · 1.1 s; #4822 · Tomás Rey · $64.50 · Digest · 0.9 s; #4823 · Lena Okafor · $1,240.00 · VIP alert · 1.3 s; #4824 · Ade Bello · $89.90 · Digest · 1.0 s.
- Stats: Runs today 1,282 rising to 1,286; Avg run 1.1 s; Errors 0.
- Inspector: channel "#vip-orders"; message "New VIP order #4823 · Lena Okafor · $1,240.00 · 3 items"; sent "10:42:18".
- Length: 10 seconds.
</inputs>
<direction>
- Look: a calm, tactile automation canvas, closer to a well-made drafting table than a dark control room: white cards on warm sage paper, ink wires, one tangerine accent for live data and one spruce green for success. Every node lands with a small physical settle; every packet moves at the same even, unhurried speed, so the viewer can follow one order from start to finish.
- Palette: canvas #E8ECE4 with 2px dots #C5CCBF every 28px; node cards #FFFFFF with a 1px #D3D8CC border and shadows 0 2px 0 #D3D8CC and 0 10px 24px rgba(40,50,35,0.08); ink #1F2A24; muted #6B7469; idle wires #B5AFA3; active wires ink; tangerine #EE6A2C (trigger badge, packets, the live dot); spruce #2C6E57 (Live switch, checks, the Yes pill); slate #5A6B7B (the No pill). Icon tiles, tint and glyph color: storefront #FCE3D4/#EE6A2C, CRM #DCE9F2/#3D6E93, branch #E1EDE6/#2C6E57, team chat #F6EBCB/#A07A12, email #E4E9EF/#4A5A6B, spreadsheet #DDEFE2/#2C6E57. Nothing else gets color.
- Type: Figtree 700 22px for the wordmark; Figtree 600 19px for node titles; Figtree 700 11px tracked 0.12em uppercase for the kind label; Figtree 500 for the breadcrumb (18px) and log names (15px); DM Mono 500 for node details (14px), packet labels (13px), log columns (14px) and stat values (40px), with tabular figures.
- Layout (every node is 260×112, radius 14):
- Toolbar y 36–104 across x 110–1810: the wordmark at x 110; "Workflows / Route new orders" at x 300 (the first part muted); at the right a Draft/Live switch (56×30, radius 15) with its label at x 1560, and a "Test run" ghost button at x 1680–1810.
- Nodes: N1 x 110–370, N2 x 450–710, N3 x 790–1050, all at y 470–582; N4a x 1150–1410, y 290–402; N4b x 1150–1410, y 650–762; N5 x 1510–1770, y 470–582.
- Inside a node: a 40px icon tile at (node x + 18, node y + 18), radius 10, holding an original 2px-stroke glyph (an awning for storefront, a person card for CRM, a forking line for branch, a speech bubble for chat, an envelope for email, a 3×3 grid for spreadsheet); the kind label at x + 72, baseline y + 34; the title at x + 72, baseline y + 60; the detail in muted at x + 18, baseline y + 94. A run counter sits at the node's top right ("0 runs", DM Mono 500 12px muted) and a 3px progress bar can fill along the node's bottom inner edge.
- Ports: 10px circles with a 2px border, centered on the left and right edges at the node's middle; the branch node has two outputs on its right edge, at y 506 (Yes) and y 546 (No).
- Wires: cubic Béziers from port to port with horizontal tangents (control points 90px out), 2px. N4a and N4b both wire into N5's input. The pills "Yes" and "No" (22px tall, white text) sit on their wires 40px after the branch.
- Run log: a card x 110–1050, y 830–1014 with the header "Run log" (Figtree 600 16px) and "live" beside a steady tangerine dot; rows 36px tall from y 870, with a spruce check, the order number, the customer, the total, the path and the duration in fixed columns at x 140, 180, 290, 520, 660 and 960.
- Stats card x 1150–1770, y 830–1014: three columns, "Runs today", "Avg run" and "Errors", labels in Figtree 500 15px muted at baseline y 880, values at baseline y 950.
- Packets: a 14px tangerine dot with a 2px white ring, carrying a label pill 24px above it ("#4821 · $318.00", white on tangerine, 26px tall, radius 13). A packet rides a wire by arc length (getPointAtLength) over 0.35 s (easeInOutSine), then dwells 0.18 s at the next node's input port while that node's progress bar fills tangerine; then the node's border turns spruce for 0.4 s, a 20px spruce check badge pops onto its top-right corner (scale 0 → 1, easeOutBack) and its run counter adds one. A run begins with a 0.18 s dwell on N1, so every run takes 2.3 s (0.18 s plus four legs of 0.53 s). While a packet is on a wire, that wire turns ink behind it and fades back to idle 0.3 s after the packet leaves.
- The branch: at N3, orders of $250 or more leave from the Yes port and the rest from the No port; the chosen port fills spruce (Yes) or slate (No) for 0.3 s.
- Node landing: each node drops from 16px above at 0.96 scale and fades in over 0.4 s with easeOutBack (overshoot 1.2), its shadow growing as it lands; its incoming wire then draws from the source port (stroke-dashoffset, 0.3 s, easeInOutCubic) and both ports pop in.
- Premium: a small graph you can read at a glance, real values that obey the branch rule, even packet speed, each accent color doing one job, landings that feel physical but quiet. Cheap: a dark neon flowchart, glowing wires, dozens of nodes, spinning gears, a robot mascot, packets that teleport, a rainbow of app colors.
- Banned: real company names, logos and UI copied from existing products, including real app icons for the storefront, CRM, chat, email or spreadsheet; lorem ipsum; glow; gradients on nodes; anything flashing more than 3 times per second.
</direction>
<structure>
- 0.0–0.5s: the dot grid fades in from the center outward (each dot starting by its distance from (960, 540), 0.4 s in all); the toolbar slides down 12px and fades in.
- 0.5–2.2s: nodes land in order at 0.5 (N1), 0.8 (N2), 1.1 (N3), 1.4 (N4a), 1.6 (N4b) and 1.9 s (N5), each followed by its incoming wire; N5's two incoming wires draw together; the Yes and No pills pop when their wires finish.
- 1.0–1.4s: the run log and stats cards rise 16px and fade in: "Runs today" 1,282, "Avg run" 1.1 s, "Errors" 0; the log reads "Waiting for the first run" in muted.
- 2.3–2.9s: the cursor (a black arrow with a white outline) moves to the Draft switch and clicks at 2.6 s: the knob slides right (0.25 s, easeInOutCubic), the track turns spruce and the label changes to "Live"; a toast at top center (y 128, ink fill, white Figtree 500 16px, radius 10) reads "Workflow is live · listening for new orders" from 2.7 to 4.4 s.
- 3.0–6.8s: four runs start at 3.0 (#4821), 3.5 (#4822), 4.0 (#4823) and 4.5 s (#4824). When a run reaches the end of N5, its log row slides in at the top of the log (older rows move down 36px, easeOutCubic 0.3 s) and "Runs today" adds one.
- 6.0s: the poster: all six nodes and wires; #4823's packet on the wire from N4a to N5; #4824's packet on the No wire from N3 to N4b; every node counter showing its runs so far; two rows in the log (#4822 on top); "Runs today 1,284".
- 6.3–6.8s: #4823 and #4824 finish; the log holds all four rows and "Runs today" reads 1,286.
- 6.9–7.6s: the cursor moves to N4a and hovers it at 7.2 s: the node's border turns ink and an inspector popover (x 1060–1500, y 130–270, white, radius 12, 1px #D3D8CC border, a small pointer down toward N4a) rises 8px and fades in: "Alert VIP team · last run" in Figtree 600 16px, then in DM Mono 500 14px "channel #vip-orders", "message New VIP order #4823 · Lena Okafor · $1,240.00 · 3 items" wrapped onto two lines, and "sent 10:42:18".
- 7.6–10.0s: hold; the live dot stays steady and nothing else moves.
For other lengths, add or remove runs at 0.5 s spacing; keep the leg timing and at least 1 s of hold.
</structure>
<build>
- One self-contained index.html (inline CSS and JS), a 1920×1080 (16:9) stage scaled to fit the window, designed for 60fps. No image, video, texture or model files: every icon, the cursor and the canvas are drawn in code.
- window.seek(t), t in seconds, computes every visual from t alone: no CSS transitions or CSS animations, no setTimeout/setInterval, no state carried between frames, randomness only from a seeded PRNG. Each packet's position, each node's progress, counter and check, and the log rows are all derived from the run start times and the fixed leg timing. Past the end, seek clamps to the last frame.
- Without ?render in the URL, drive seek from requestAnimationFrame so it plays in a browser (loop after a 1s end hold); with ?render, don't start that loop.
- Google Fonts via <link> are fine; await document.fonts.load() for each face before defining window.seek.
- Engine: one inline <svg> with viewBox "0 0 1920 1080" holding the canvas, nodes, wires, packets and panels; text as SVG <text>; node shadows from one shared filter. Measure each wire once at load with getTotalLength and sample it with getPointAtLength in seek; seek sets attributes (transforms, stroke-dashoffset, opacity, fills, text) directly.
</build>
<check>
Before showing me, step through one frame per second (t = 0…10): screenshot each and look at it. Fix overlaps, clipped or cramped text, and anything off-style or Banned. Check that the wires meet the ports exactly, no wire passes behind a node, packets follow the branch rule ($318.00 and $1,240.00 go Yes; $64.50 and $89.90 go No), every packet moves at the same speed, node counters and "Runs today" agree with the finished runs, the log rows line up in their columns, the toast is gone before the popover appears, the 6.0 s frame matches the poster description, nothing flashes, and the final frame shows the full graph, four log rows, "Runs today 1,286" and the inspector over N4a. Confirm seek(10) and seek(11) match, so the final frame holds.
</check> Ours, and free to use under CC0: copy it, change it, ship it. No credit needed.
A slow, ribbon-like gradient mesh flows in a skewed band behind sharp headline type, while white payment, API and chart…
A device built in three.js rises out of total darkness while a softbox reflection glides along its titanium edge, then…
A dark-mode work tool drawn in hairlines and quiet radial glows: issue rows populate, ⌘K opens a command menu, a comman…
Rounded tiles spring into a bento grid on warm paper, each acting out one feature in a small animation, then the tiles…
More like this on the motion design inspiration board: UI animation inspirationSaaS video inspirationExplainer video inspirationDiagram animation inspiration