Backprop Flow

A feed-forward neural-network visualisation that animates the two passes of training: activations flowing left → right (forward), then gradients flowing right → left (backward). One layer cursor drives the entire timeline — in auto mode it cycles forward then backward, so the user just presses play to see a full step.

Forward pass. Layer 1 of 4 activation highlighted.
Forward passlayer 01 / 04
0.330.390.27inputhidden 1hidden 2output
Customize
Architecture
3-4-4-2
Pass
auto
0
Playback

Installation

npx shadcn@latest add https://craftbits.dev/r/backprop-flow.json

Usage

import { BackpropFlow } from "@craft-bits/core";
 
<BackpropFlow layers={[3, 4, 4, 2]} />

Pass your own activations and gradients from a real training loop:

<BackpropFlow
  layers={[3, 4, 2]}
  activations={[
    [0.1, 0.5, 0.9],
    [0.3, 0.7, 0.2, 0.8],
    [0.6, 0.4],
  ]}
  gradients={[
    [0.01, 0.02, 0.005],
    [0.04, 0.08, 0.06, 0.05],
    [0.3, 0.4],
  ]}
/>

Drive playback from outside the component:

const [layer, setLayer] = useState(0);
 
<BackpropFlow
  layers={[3, 4, 2]}
  direction="forward"
  currentLayer={layer}
  onCurrentLayerChange={setLayer}
  playing={false}
/>

Understanding the component

  1. One cursor, two passes. The currentLayer cursor advances 0 → N during the forward pass and N → 0 during the backward pass. In auto mode the cursor span is 2N, so a single integer drives the whole animation — forward and backward are slices of the same timeline.
  2. Same DOM for both passes. Forward and backward share the same nodes and edges; only the active-edge highlight, label, and stroke direction change. Switching direction is purely a style flip — no remount, no DOM churn.
  3. Synthesised values when shape-only. Pass layers={[3,4,2]} with no activations / gradients and the component renders deterministic placeholder values that mimic real-world shapes (gradients shrink toward earlier layers — the vanishing-gradient intuition).
  4. SPRINGS.smooth on the active edge / node. Layer transitions use the smooth spring from @craft-bits/core/motion so the cursor settles rather than snaps.
  5. Reduced-motion fallback. With prefers-reduced-motion: reduce, the diagram renders fully lit on mount with no autoplay and no per-layer animation.
  6. Auto layout from layers alone. Node positions are derived from the layer-shape array — change the architecture and the diagram re-flows. No coordinates to maintain.

Props

PropTypeDefaultDescription
layersreadonly number[]Neuron count per layer (left → right). Required.
activationsreadonly (readonly number[])[]Forward-pass values per layer. Synthesised if omitted.
gradientsreadonly (readonly number[])[]Backward-pass values per layer. Synthesised if omitted.
direction'forward' | 'backward' | 'auto'Controlled direction. Pair with onDirectionChange.
defaultDirection'forward' | 'backward' | 'auto''auto'Uncontrolled initial direction.
onDirectionChange(direction) => voidFires when the direction toggle cycles.
currentLayernumberControlled cursor. Pair with onCurrentLayerChange.
defaultCurrentLayernumber0Uncontrolled initial cursor.
onCurrentLayerChange(layer) => voidFires on tick and on manual scrub.
playingbooleanControlled play state. Pair with onPlayingChange.
defaultPlayingbooleantrueUncontrolled initial play state.
onPlayingChange(playing) => voidFires when play / pause flips.
playSpeednumber600Milliseconds between layer advances.
transitionTransitionSPRINGS.smoothSpring for active-edge / node transitions.
classNamestringMerged onto the root <div> via cn().

Accessibility

  • The figure is role="figure" with aria-label="Backpropagation flow visualization".
  • An aria-live="polite" summary announces the current pass and active layer whenever the cursor advances.
  • The play / pause button is aria-pressed; the label flips between "Play flow" and "Pause flow".
  • The direction toggle's aria-label names the current direction and that clicking will cycle.
  • The scrubber is a native <input type="range"> with an explicit aria-label, so keyboard arrows nudge the cursor and screen readers narrate the value.
  • Color is never the only signal — pass label, active-layer count, and value labels are all textual.
  • prefers-reduced-motion: reduce renders the network fully lit on mount and disables autoplay.

Credits

  • Extracted from: craftingattention (app/src/lessons/primitives/viz/BackpropFlow.tsx). Stripped the lesson-specific Widget chrome, predict-quiz, multi-step narration heuristics, slider-bound a/b/c inputs, and the bespoke a × b + c → σ computation graph. Generalised to an arbitrary layers: number[] feed-forward network with controlled / uncontrolled state pairs for direction, currentLayer, and playing.