Deft
Ask AI

Search

Search skills, authors and topics

INSANE0777 / awwwards-skills

motion-authoring

Use when a converted project needs its motion authored: turning a motion manifest and inert skeletons into real per-section motion with a parity check. Covers timeline topology, intent mapping, reduced motion, and the verification gate.

Install

npx skills add https://github.com/INSANE0777/awwwards-skills --skill motion-authoring

Motion authoring — from measured manifest to real motion

Runs only when the user chose a converted project and authored motion. The generator gives you structure, inert skeleton mounts, and motion.manifest.json (measured triggers, pageTriggers, initial-hidden hints). Authoring is the step where those mounts become real motion and the build is proven against the reference. This is the N2 dogfood recipe (nesil: one 31.21 s master scrub, exact 25,650 px parity).

Profile note: this skill's tools are analyze_page_structure, analyze_scroll_map, build_motion_manifest and retained build_project. Examples below use 1.x names (default full). On AWWWARDS_MCP_PROFILE=v2, use inspect_page {request:{kind:"structure", url}}, analyze_motion {request:{kind:"scroll", url, compact:false}} and build_motion {request:{kind:"manifest", bands, scrollCensus}}; build_project stays flat. The census must be compact:false — a compact census has no anims[] and cannot feed build_motion. Full mapping: v2-routing.md [blocked].

0. Read the reference, not just the census

The census tells you what moves and roughly when; its selectors are structural paths, not your ids/classes. Read the site's own motion script when available and treat the census as corroboration: real trigger count, pins, scrub ratio, duration, easing vocabulary, stagger delays, which animations are CSS keyframes vs GSAP vs native scroll timelines. Use anims[] to verify coverage — never to derive timelines.

1. Decide the topology before writing code

One question: one master timeline or independent section triggers?

  • One master scrub (tall spacer, fixed stage, single scrubbed trigger) → author a page-level journey module with one labelled timeline; section modules become thin slice builders that add to it. Do NOT split into seven independent ScrollTriggers — overlap and hand-offs change.
  • Independent section triggers → one timeline per section module keyed by the manifest's triggers[]; the skeletons already have the shape (gsap.context, measured constants, refresh).

Rows with start: null are CSS keyframes or unowned rows — provenance, not an instruction to build a timeline each.

2. Manifest contract

motion.manifest.json is evidence, not an authoring file:

  • consume as generated; never add hand rows or flip measured
  • record counts verbatim (sections, sectionTriggers, pageTriggers)
  • record authored code separately (files + before/after) and keep the delivered manifest hash equal to a fresh generation; if you must add rows, mark them authored and say so — never measured: true
  • pageTriggers belong to the page-level module, not to a section
  • No build yet? build_motion_manifest({ bands, scrollCensus, sections? }) scaffolds this manifest shape straight from analyze_page_structure + analyze_scroll_map (+ optional {label, selector?} overrides). Its envelope is measured: false and DOM initial-state hints are empty (no markup), so author from the census triggers and record authored code as below — never flip the scaffold to measured: true by hand.

3. Intent map (what to port, what to skip)

IntentPortSkip
Loader introhero sequence from the site's timeline (name, cursor travel, lid, kicker, role, face)analytics, spinners
Master journeyone scrubbed timeline, section set times, --bg tweens, labelled sectionsunrelated scripts
Canvas/dustcanvas sized to stage, DPR clamp, bounded count, velocity push, cleanupunused particle/WebGL libs
Cursoridle tween, intro hand-off, end-state handoverOS cursor replacement
Audioloop element, volume ramp, toggle, visibilitychange pauseautoplay assertions
Ruler/progressone control per label, head position = progresscustom scrollbar
Copy/formsclipboard + fallback, status resetserver-side behavior absent from the page
Reduced motionhead boot + CSS class; authored code returns before GSAP"lite" variants nobody asked for

4. Target surfaces (do not double-load GSAP)

TargetSurfaceRule
Nextvendor globals via SiteScripts (before MotionRoot), authored hooks/modulesno import gsap in authored code; bounded wait for window.gsap/ScrollTrigger
Vitewindow.gsap/ScrollTrigger/Lenis from kept classic tags copied to dist/src/scriptsno import gsap
Astrosame globals, is:inline vendor tags; page script first, then sectionsno import gsap

Generated skeletons import npm gsap; replacing that with the kept global avoids two copies. An unused gsap dependency may remain — harmless, do not import it.

5. Authoring order

Page-level first (loader → journey → cursor → audio → ruler), then sections that own independent triggers. Keep the same lock discipline as the section loop: author a section, re-run its section gate (captured geometry + screenshots + explicit checks), lock it, next. verify_build is aggregate whole-page evidence, not a per-section score.

6. Verification gate (all must pass)

  • Every target builds (vite build, astro build, next build + start probe).
  • Desktop 1440×900 at the band anchors (8 stops): scrollHeight ±1 %, identical visible section ids, fonts, 0 console/page errors/404s.
  • Mobile 390×844 smoke: no horizontal overflow, same anchors/visible sections, 0 errors.
  • Reduced motion: head class applied, fixed stage disabled, no overflow, page readable.
  • Authored proof: zero references to the dropped site scripts in source and build trees; only the kept vendor libs; SiteScripts before MotionRoot.

Failure modes

SymptomCauseFix
Page inert after authoringauthored code started before libswait for globals / keep SiteScripts first
Two GSAP runtimes / odd easingnpm import + vendor globaluse the kept global only
Hand-offs changedmaster scrub split into per-section triggersone page-level journey, sections slice it
Manifest "measured" but wronghand rows edited in placeregenerate, or mark authored rows explicitly
Motion fine, page broken on mobiledesktop-only authoringrun the 390 smoke every iteration