DEV Community

Gabriele Bolognese
Gabriele Bolognese

Posted on

Devlog day 5

2026-08-08

  • 40 commits, +9917/−362, about 253 file changes, across six areas of work.
  • Type checking stayed at 0 errors and lint at the 127 baseline through every commit.
  • Anything touching GPU rendering or pointer behaviour is verified by structure only (Node harnesses plus guards), so it still needs a browser to confirm by feel.

  • Figma time-saver milestones M17 to M22 (6 commits):

  • Outline Text (M17): turns a text layer into editable letter shapes that can be moved point by point.

  • Batch rename (M19, Ctrl+R): renames a multi-selection at once using tokens, numbering and pattern matching.

  • Freehand draw tool (M18, Shift+P).

  • Rulers with tick marks and labels, plus snapping to whole pixels while dragging (M20).

  • Linked colour styles (M21): change a colour once and every layer using it updates. Shape and text fill and stroke read the style first, before the material overlay is applied.

  • Outline stroke, and combining shapes in a way that keeps holes intact (M22).

    • Hard part: preserving holes through a boolean means tracking even-odd winding, not just unioning outer rings.
  • Self-driving tutorial, phases 1 to 5 (4 commits):

  • A tutorial that builds a complete title-card scene by operating the real editor (chapters 1 to 10), with a spotlight overlay on the interface and a prompt on first open.

    • Hard part: it runs the actual store actions rather than a scripted fake, so each step has to tolerate real state and undo — a canned animation would drift from the editor.
  • Landing-page deep links (3 commits):

  • Buttons on the landing page open the editor at /?template=<id>, loading a fresh project that plays on open and can be edited. First one is a tuned particle hero.

    • Hard part: the splash overlays the app while WebGPU warms and pre-rolls ~8 frames before playing, so the first (heaviest) frames happen behind it. And seeding has to wait until the async scene-load actually swaps the composition reference, or it lands on the wrong doc and gets overwritten.
  • Animation template library (9 commits):

  • "Use this" inserts a working animation at the playhead, including the timing and motion, not only the artwork.

  • 24 or more templates: scenes (beach, forest, night), weather (sunset, rain, city, snow), creative (galaxy, phone chat, pen, clock, fireworks, rocket, coffee, confetti, spinner), and four showcases: Chain Reaction (Rube Goldberg, 200 balls), Departure Board (split-flap flip wave, parallax planes, rain matte), Bar Chart Race (pre-computed reordering), Recursive Editor (FlashFX animating a video editor).

  • An "All" button that inserts every template one after another.

  • Number: verify:anim-templates, 132 checks.

    • Hard parts: templates are authored 0-based and rebased to the playhead (rescaled if the comp fps differs from the authoring fps). The Recursive Editor lives or dies on cursor believability — the cursor engine is a bezier arc + ballistic velocity + overshoot + dwell + sub-pixel noise + icon swaps. The bar-race reorder is baked because a live reorder needs a per-frame sort the keyframe model can't express.
  • AI chat panel, mockup (2 commits):

  • A side panel that can be toggled on, in the style of VS Code and Copilot. It takes the right 20% of the screen and compresses the layout in every mode except preview.

  • Assistant replies without borders, a loading state while thinking, streaming text, and a response timer. Composer buttons are placeholders (add file, from Drive, image, and others).

  • Internal: a streamResponse() seam and canned reply now, so a real model drops in later with no UI change.

  • GPU procedural pattern engine, phases 1 to 3 (6 commits):

  • A new generativePattern layer that draws patterns on the graphics card at full resolution (waves, plasma, kaleidoscope, mosaic and 7 more, 11 types total) with a palette editor.

  • The layer has bounds and can be moved, resized and masked like a rectangle, with animatable controls (scale, rotation, warp, contrast) and blending with the layer below.

  • Number: verify:pattern, 16 checks; blend-with-below is 4 GPU pipeline variants (normal/add/multiply/screen).

    • Hard parts: the config's type whitelist was hard-coded to the original 4 types, so every new type silently parsed back to plasma (caught by the harness: 'plasma' !== 'clouds'). Blend can't read the scene texture progressively, so each mode is a separate pipeline whose fragment output form is matched to its blend state.
  • Timeline layer-name column (2 commits):

  • The layer-name column doubles in width in Edit mode, then sizes itself, growing to fit the busiest track up to a limit.

  • Number: clip counts computed O(N) via a Map, not per-track-per-render.

  • 2.5D system, camera and 3D layers, M0 to M3 plus M6 and M2 (8 commits):

  • The start of After Effects style cards positioned in space. Built so a 2D project renders byte-identical at every step: the depth fields default to 0 and the GPU path is switched on by an is3D flag.

  • M0: a matrix core plus optional Z position and X/Y rotation on Transform.

  • M1: a camera layer that resolves to view and projection each frame. The default camera frames the composition 1:1 at any zoom, so a single layer switched to 3D does not jump.

  • M3: the 3D toggle on a layer, plus X, Y and Z position and rotation rows in the inspector.

  • M2: the renderer projects each 3D layer through the camera in the shader (added to the image, shape, text and pattern uniforms) and sorts by depth, far to near, with 2D layers holding their existing order.

  • Numbers: verify:mat4 9, verify:camera3d 17, verify:scene3d 5.

    • Hard part: the y-down handedness trap. The default camera was flipping both screen axes versus the renderer's y-down convention, and the first harness only checked magnitudes so it passed anyway. Fixed with a −Y comp-up vector and pinned with signed-parity assertions (top-left → (−1,+1), etc.). The GPU projection itself is browser-unverifiable, so it's additive + guarded (zero-init is3D flag → 2D layers can't be affected) and all the hard math — parity, foreshortening, painter order — is proven in Node.

Top comments (0)