@nerdev/skillset 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +351 -0
- package/bin/skillset.mjs +205 -0
- package/curations/README.md +53 -0
- package/curations/TEMPLATE/WHY.md +23 -0
- package/curations/TEMPLATE/overlay/SKILL.md +6 -0
- package/curations/impeccable/WHY.md +34 -0
- package/curations/impeccable/overlay/SKILL.md +116 -0
- package/package.json +43 -0
- package/scripts/ste-gate.mjs +39 -0
- package/scripts/ste-lint.py +201 -0
- package/scripts/sync.mjs +174 -0
- package/skills/ai-agent/agent-docs-writer/SKILL.md +105 -0
- package/skills/ai-agent/agent-docs-writer/references/principles.md +73 -0
- package/skills/ai-agent/agent-docs-writer/templates/AGENTS.template.md +44 -0
- package/skills/ai-agent/agent-docs-writer/templates/README.template.md +19 -0
- package/skills/ai-agent/ultra-context-engine/SKILL.md +941 -0
- package/skills/architecture/blueprint/SKILL.md +191 -0
- package/skills/architecture/code-tour/SKILL.md +204 -0
- package/skills/architecture/progress-guard/SKILL.md +148 -0
- package/skills/architecture/search-first/SKILL.md +97 -0
- package/skills/backend/api-design/SKILL.md +456 -0
- package/skills/backend/auth/SKILL.md +596 -0
- package/skills/backend/database/SKILL.md +431 -0
- package/skills/backend/realtime/SKILL.md +670 -0
- package/skills/backend/security/SKILL.md +590 -0
- package/skills/business/brag/SKILL.md +177 -0
- package/skills/business/brag/assets/music/README.md +20 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-1-by-ende-dot-app.music-cues.json +3846 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-1-by-ende-dot-app.music-cues.md +35 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-10-by-ende-dot-app.music-cues.json +1826 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-10-by-ende-dot-app.music-cues.md +35 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-11-by-ende-dot-app.music-cues.json +2266 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-11-by-ende-dot-app.music-cues.md +35 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-12-by-ende-dot-app.music-cues.json +2806 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-12-by-ende-dot-app.music-cues.md +35 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-9-by-ende-dot-app.music-cues.json +2796 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-9-by-ende-dot-app.music-cues.md +35 -0
- package/skills/business/brag/assets/music/happy-beats-business-moves-vol-1-by-ende-dot-app.mp3 +0 -0
- package/skills/business/brag/assets/music/happy-beats-business-moves-vol-10-by-ende-dot-app.mp3 +0 -0
- package/skills/business/brag/assets/music/happy-beats-business-moves-vol-11-by-ende-dot-app.mp3 +0 -0
- package/skills/business/brag/assets/music/happy-beats-business-moves-vol-12-by-ende-dot-app.mp3 +0 -0
- package/skills/business/brag/assets/music/happy-beats-business-moves-vol-9-by-ende-dot-app.mp3 +0 -0
- package/skills/business/brag/assets/sfx/casino/card-fan-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-fan-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-place-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-place-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-place-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-place-4.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-shove-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-shove-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-shove-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-shove-4.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-shuffle.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-4.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-5.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-6.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-7.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-8.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/cards-pack-open-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/cards-pack-open-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chip-lay-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chip-lay-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chip-lay-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-collide-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-collide-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-collide-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-collide-4.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-handle-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-handle-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-handle-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-handle-4.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-handle-6.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-stack-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-stack-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-stack-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-stack-4.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-stack-5.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-stack-6.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-grab-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-grab-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-shake-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-shake-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-shake-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-throw-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-throw-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-throw-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/die-throw-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/die-throw-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/die-throw-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/die-throw-4.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_carpet_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_carpet_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_carpet_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_concrete_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_concrete_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_concrete_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_concrete_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_concrete_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_grass_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_grass_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_grass_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_grass_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_grass_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_snow_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_snow_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_snow_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_snow_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_snow_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_wood_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_wood_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_wood_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_wood_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_wood_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactBell_heavy_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactBell_heavy_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactBell_heavy_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGeneric_light_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGeneric_light_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGeneric_light_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGeneric_light_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGeneric_light_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGlass_heavy_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGlass_light_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGlass_light_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGlass_light_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGlass_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGlass_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGlass_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_heavy_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_heavy_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_heavy_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_light_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_light_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_medium_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_medium_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMining_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlank_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlank_medium_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlank_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlank_medium_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlank_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_heavy_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_heavy_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_heavy_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_heavy_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_heavy_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_light_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_light_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_light_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_light_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_light_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_medium_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_medium_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_heavy_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_heavy_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_heavy_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_heavy_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_heavy_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_medium_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_medium_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_heavy_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_heavy_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_heavy_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_heavy_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_heavy_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_medium_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_medium_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactTin_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactTin_medium_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactTin_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactTin_medium_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactTin_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_heavy_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_heavy_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_heavy_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_heavy_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_heavy_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_light_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_light_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_light_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_light_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_light_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_medium_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_medium_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/bong_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/click_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/click_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/click_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/click_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/click_005.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/drop_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/drop_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/drop_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/error_005.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/error_006.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/glitch_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/glitch_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/select_008.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/switch_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/switch_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/switch_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/switch_005.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/switch_006.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/switch_007.ogg +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-001.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-002.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-003.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-004.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-005.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-006.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-007.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-008.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-009.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-010.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-011.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-012.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-013.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-014.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-015.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-016.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-017.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-018.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-019.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-020.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-021.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-022.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-023.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-024.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-025.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-026.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-027.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-028.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-029.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-030.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-031.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-032.wav +0 -0
- package/skills/business/brag/assets/sfx/sfx-analysis.json +15584 -0
- package/skills/business/brag/assets/sfx/sfx-analysis.md +75 -0
- package/skills/business/brag/assets/sfx/ui/click1.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/click2.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/click3.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/click4.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/click5.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/mouseclick1.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/rollover1.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/rollover2.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/rollover4.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/rollover5.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch1.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch10.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch11.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch12.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch13.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch14.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch15.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch16.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch17.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch18.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch19.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch2.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch20.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch21.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch22.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch23.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch24.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch25.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch26.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch27.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch28.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch29.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch3.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch30.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch31.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch32.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch33.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch34.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch35.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch36.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch37.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch38.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch4.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch5.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch6.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch7.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch8.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch9.ogg +0 -0
- package/skills/business/brag/references/audio.md +307 -0
- package/skills/business/brag/references/step-1-inspect.md +133 -0
- package/skills/business/brag/references/step-2-plan.md +234 -0
- package/skills/business/brag/references/step-3-compose.md +210 -0
- package/skills/business/brag/references/step-4-deliver.md +168 -0
- package/skills/business/brag/references/tones.md +231 -0
- package/skills/business/brag/scripts/analyze_music_cues.py +309 -0
- package/skills/business/brag/scripts/pyproject.toml +14 -0
- package/skills/business/brag/scripts/uv.lock +819 -0
- package/skills/business/copywriting/SKILL.md +178 -0
- package/skills/business/customer-research/SKILL.md +259 -0
- package/skills/business/freelancing/SKILL.md +679 -0
- package/skills/business/launch/SKILL.md +273 -0
- package/skills/business/marketing-psychology/SKILL.md +364 -0
- package/skills/business/pricing/SKILL.md +233 -0
- package/skills/business/resume-revamp-jake-ats/SKILL.md +64 -0
- package/skills/business/startup-founder/SKILL.md +400 -0
- package/skills/business/startup-founder/references/funding.md +48 -0
- package/skills/business/startup-founder/references/further-reading.md +132 -0
- package/skills/business/startup-founder/references/gtm-tools.md +57 -0
- package/skills/business/startup-founder/references/legal-india.md +36 -0
- package/skills/business/startup-founder/references/marketing/README.md +16 -0
- package/skills/business/startup-founder/references/marketing/cold-email.md +172 -0
- package/skills/business/startup-founder/references/marketing/competitors.md +245 -0
- package/skills/business/startup-founder/references/marketing/customer-research.md +276 -0
- package/skills/business/startup-founder/references/marketing/free-tools.md +168 -0
- package/skills/business/startup-founder/references/marketing/launch.md +343 -0
- package/skills/business/startup-founder/references/marketing/marketing-plan.md +270 -0
- package/skills/business/startup-founder/references/marketing/pricing.md +237 -0
- package/skills/business/startup-founder/references/marketing/product-marketing.md +250 -0
- package/skills/business/startup-founder/references/validation.md +267 -0
- package/skills/devops/deployments/SKILL.md +339 -0
- package/skills/devops/git-ci/SKILL.md +372 -0
- package/skills/devops/performance/SKILL.md +523 -0
- package/skills/devops/testing/SKILL.md +558 -0
- package/skills/engineering/code-review/SKILL.md +149 -0
- package/skills/engineering/coding-standards/SKILL.md +229 -0
- package/skills/engineering/product-engineering/SKILL.md +219 -0
- package/skills/engineering/senior-engineer-prompts/SKILL.md +145 -0
- package/skills/engineering/tdd-workflow/SKILL.md +178 -0
- package/skills/engineering/verification-loop/SKILL.md +199 -0
- package/skills/nerdev/nerdev-abstraction/SKILL.md +412 -0
- package/skills/nerdev/nerdev-docs/SKILL.md +527 -0
- package/skills/nerdev/nerdev-docs/templates/adr-template.md +39 -0
- package/skills/nerdev/nerdev-docs/templates/contributing-template.md +140 -0
- package/skills/nerdev/nerdev-docs/templates/deploy-template.md +426 -0
- package/skills/nerdev/nerdev-docs/templates/design-template.md +105 -0
- package/skills/nerdev/nerdev-docs/templates/incident-template.md +66 -0
- package/skills/nerdev/nerdev-monorepo/SKILL.md +522 -0
- package/skills/quality/output-skill/SKILL.md +49 -0
- package/skills/quality/unslop/SKILL.md +67 -0
- package/skills/ui/animaxxing/SKILL.md +58 -0
- package/skills/ui/animaxxing/agents/openai.yaml +7 -0
- package/skills/ui/animaxxing/references/effect-restoration.md +26 -0
- package/skills/ui/animaxxing/references/motion-vocabulary.md +142 -0
- package/skills/ui/animaxxing/references/recipes/blast-off.md +119 -0
- package/skills/ui/animaxxing/references/recipes/particle-effects.md +718 -0
- package/skills/ui/animaxxing/references/recipes/particle-field.md +428 -0
- package/skills/ui/animaxxing/references/recipes/route-letters.md +205 -0
- package/skills/ui/animaxxing/references/recipes/speak-in.md +181 -0
- package/skills/ui/animaxxing/references/recipes/split-entrances.md +345 -0
- package/skills/ui/animaxxing/references/recipes/wave.md +144 -0
- package/skills/ui/animaxxing/references/text-stability.md +68 -0
- package/skills/ui/animaxxing/references/verification.md +44 -0
- package/skills/ui/ask-animation/SKILL.md +178 -0
- package/skills/ui/ask-base-ui/SKILL.md +400 -0
- package/skills/ui/ask-cmdk/SKILL.md +315 -0
- package/skills/ui/ask-command-menu/SKILL.md +262 -0
- package/skills/ui/ask-drawer/SKILL.md +235 -0
- package/skills/ui/ask-form/SKILL.md +229 -0
- package/skills/ui/ask-gsap/SKILL.md +435 -0
- package/skills/ui/ask-modal/SKILL.md +145 -0
- package/skills/ui/ask-motion/SKILL.md +339 -0
- package/skills/ui/ask-rhf/SKILL.md +388 -0
- package/skills/ui/ask-sonner/API.md +64 -0
- package/skills/ui/ask-sonner/SKILL.md +88 -0
- package/skills/ui/ask-table/SKILL.md +253 -0
- package/skills/ui/ask-tanstack-table/SKILL.md +490 -0
- package/skills/ui/ask-toast/SKILL.md +163 -0
- package/skills/ui/ask-vaul/SKILL.md +291 -0
- package/skills/ui/ask-virtual-list/SKILL.md +304 -0
- package/skills/ui/ask-virtuoso/SKILL.md +332 -0
- package/skills/ui/email-craft/SKILL.md +258 -0
- package/skills/ui/frontend-craftsmanship/SKILL.md +462 -0
- package/skills/ui/gsap-astro/SKILL.md +56 -0
- package/skills/ui/gsap-astro/agents/openai.yaml +7 -0
- package/skills/ui/gsap-astro/references/client-router-navigation.md +139 -0
- package/skills/ui/gsap-astro/references/initialization.md +87 -0
- package/skills/ui/gsap-astro/references/motion-system.md +152 -0
- package/skills/ui/gsap-astro/references/scripts-and-islands.md +65 -0
- package/skills/ui/gsap-astro/references/verification.md +44 -0
- package/skills/ui/gsap-core/SKILL.md +254 -0
- package/skills/ui/gsap-frameworks/SKILL.md +266 -0
- package/skills/ui/gsap-nextjs/SKILL.md +51 -0
- package/skills/ui/gsap-nextjs/agents/openai.yaml +7 -0
- package/skills/ui/gsap-nextjs/references/app-router-navigation.md +189 -0
- package/skills/ui/gsap-nextjs/references/initialization.md +87 -0
- package/skills/ui/gsap-nextjs/references/motion-system.md +158 -0
- package/skills/ui/gsap-nextjs/references/verification.md +40 -0
- package/skills/ui/gsap-nuxt/SKILL.md +56 -0
- package/skills/ui/gsap-nuxt/agents/openai.yaml +7 -0
- package/skills/ui/gsap-nuxt/references/initialization.md +87 -0
- package/skills/ui/gsap-nuxt/references/motion-system.md +161 -0
- package/skills/ui/gsap-nuxt/references/navigation.md +145 -0
- package/skills/ui/gsap-nuxt/references/page-transitions.md +107 -0
- package/skills/ui/gsap-nuxt/references/verification.md +42 -0
- package/skills/ui/gsap-performance/SKILL.md +79 -0
- package/skills/ui/gsap-plugins/SKILL.md +433 -0
- package/skills/ui/gsap-react/SKILL.md +136 -0
- package/skills/ui/gsap-react-router/SKILL.md +55 -0
- package/skills/ui/gsap-react-router/agents/openai.yaml +7 -0
- package/skills/ui/gsap-react-router/references/initialization.md +87 -0
- package/skills/ui/gsap-react-router/references/motion-system.md +158 -0
- package/skills/ui/gsap-react-router/references/react-router-navigation.md +165 -0
- package/skills/ui/gsap-react-router/references/route-lifetime.md +74 -0
- package/skills/ui/gsap-react-router/references/verification.md +42 -0
- package/skills/ui/gsap-scrolltrigger/SKILL.md +296 -0
- package/skills/ui/gsap-sveltekit/SKILL.md +54 -0
- package/skills/ui/gsap-sveltekit/agents/openai.yaml +7 -0
- package/skills/ui/gsap-sveltekit/references/initialization.md +87 -0
- package/skills/ui/gsap-sveltekit/references/motion-system.md +156 -0
- package/skills/ui/gsap-sveltekit/references/page-lifetime.md +63 -0
- package/skills/ui/gsap-sveltekit/references/sveltekit-navigation.md +160 -0
- package/skills/ui/gsap-sveltekit/references/verification.md +41 -0
- package/skills/ui/gsap-tanstack-router/SKILL.md +56 -0
- package/skills/ui/gsap-tanstack-router/agents/openai.yaml +7 -0
- package/skills/ui/gsap-tanstack-router/references/initialization.md +87 -0
- package/skills/ui/gsap-tanstack-router/references/motion-system.md +160 -0
- package/skills/ui/gsap-tanstack-router/references/route-lifetime.md +66 -0
- package/skills/ui/gsap-tanstack-router/references/tanstack-navigation.md +156 -0
- package/skills/ui/gsap-tanstack-router/references/verification.md +41 -0
- package/skills/ui/gsap-timeline/SKILL.md +107 -0
- package/skills/ui/gsap-utils/SKILL.md +284 -0
- package/skills/ui/gsap-vanilla/SKILL.md +63 -0
- package/skills/ui/gsap-vanilla/agents/openai.yaml +7 -0
- package/skills/ui/gsap-vanilla/references/cross-document-navigation.md +54 -0
- package/skills/ui/gsap-vanilla/references/initialization.md +87 -0
- package/skills/ui/gsap-vanilla/references/motion-system.md +150 -0
- package/skills/ui/gsap-vanilla/references/page-load.md +96 -0
- package/skills/ui/gsap-vanilla/references/spa-navigation.md +70 -0
- package/skills/ui/gsap-vanilla/references/verification.md +41 -0
- package/skills/ui/house-style/SKILL.md +366 -0
- package/skills/ui/imagegen/SKILL.md +49 -0
- package/skills/ui/imagegen/references/brandkit.md +48 -0
- package/skills/ui/imagegen/references/image-to-code.md +56 -0
- package/skills/ui/imagegen/references/mobile.md +58 -0
- package/skills/ui/imagegen/references/web.md +63 -0
- package/skills/ui/impeccable/SKILL.md +116 -0
- package/skills/ui/impeccable/reference/adapt.md +318 -0
- package/skills/ui/impeccable/reference/adapt.native.md +58 -0
- package/skills/ui/impeccable/reference/android.md +46 -0
- package/skills/ui/impeccable/reference/animate.md +89 -0
- package/skills/ui/impeccable/reference/audit.md +137 -0
- package/skills/ui/impeccable/reference/audit.native.md +139 -0
- package/skills/ui/impeccable/reference/bolder.md +33 -0
- package/skills/ui/impeccable/reference/clarify.md +94 -0
- package/skills/ui/impeccable/reference/colorize.md +86 -0
- package/skills/ui/impeccable/reference/craft-floor.md +44 -0
- package/skills/ui/impeccable/reference/craft.md +5 -0
- package/skills/ui/impeccable/reference/critique.md +806 -0
- package/skills/ui/impeccable/reference/degraded/asset-producer.md +37 -0
- package/skills/ui/impeccable/reference/degraded/documenter.md +24 -0
- package/skills/ui/impeccable/reference/degraded/finish-reviewer.md +38 -0
- package/skills/ui/impeccable/reference/degraded/manual-edit-applier.md +92 -0
- package/skills/ui/impeccable/reference/delight.md +70 -0
- package/skills/ui/impeccable/reference/distill.md +111 -0
- package/skills/ui/impeccable/reference/doctor.md +54 -0
- package/skills/ui/impeccable/reference/document.md +416 -0
- package/skills/ui/impeccable/reference/extract.md +69 -0
- package/skills/ui/impeccable/reference/generate.md +101 -0
- package/skills/ui/impeccable/reference/harden.md +345 -0
- package/skills/ui/impeccable/reference/hooks.md +111 -0
- package/skills/ui/impeccable/reference/init.md +131 -0
- package/skills/ui/impeccable/reference/ios.md +51 -0
- package/skills/ui/impeccable/reference/layout.md +84 -0
- package/skills/ui/impeccable/reference/live-setup.md +104 -0
- package/skills/ui/impeccable/reference/live.md +325 -0
- package/skills/ui/impeccable/reference/new-work.md +145 -0
- package/skills/ui/impeccable/reference/onboard.md +234 -0
- package/skills/ui/impeccable/reference/operate.md +61 -0
- package/skills/ui/impeccable/reference/optimize.md +258 -0
- package/skills/ui/impeccable/reference/overdrive.md +127 -0
- package/skills/ui/impeccable/reference/polish.md +105 -0
- package/skills/ui/impeccable/reference/quieter.md +99 -0
- package/skills/ui/impeccable/reference/routing.md +24 -0
- package/skills/ui/impeccable/reference/shape.md +59 -0
- package/skills/ui/impeccable/reference/typeset.md +80 -0
- package/skills/ui/impeccable/reference/visualize.md +46 -0
- package/skills/ui/impeccable/scripts/VERSION +1 -0
- package/skills/ui/impeccable/scripts/command-metadata.json +98 -0
- package/skills/ui/impeccable/scripts/data/font-index-failures.json +121 -0
- package/skills/ui/impeccable/scripts/data/font-index.json +1 -0
- package/skills/ui/impeccable/scripts/impeccable +206 -0
- package/skills/ui/impeccable/scripts/impeccable.cmd +214 -0
- package/skills/ui/impeccable/scripts/live-browser-dom.js +167 -0
- package/skills/ui/impeccable/scripts/live-browser-ignores.js +242 -0
- package/skills/ui/impeccable/scripts/live-browser-session.js +144 -0
- package/skills/ui/impeccable/scripts/live-browser.js +13510 -0
- package/skills/ui/impeccable/scripts/modern-screenshot.umd.js +14 -0
- package/skills/ui/motion/SKILL.md +207 -0
- package/skills/ui/pick-ui-library/SKILL.md +85 -0
- package/skills/ui/product-messaging/SKILL.md +163 -0
- package/skills/ui/product-site/SKILL.md +465 -0
- package/skills/ui/prototype/PICKER.md +197 -0
- package/skills/ui/prototype/SKILL.md +98 -0
- package/skills/ui/refero-design/SKILL.md +534 -0
- package/skills/ui/refero-design/agents/openai.yaml +4 -0
- package/skills/ui/refero-design/references/anti-ai-slop.md +292 -0
- package/skills/ui/refero-design/references/color.md +563 -0
- package/skills/ui/refero-design/references/copywriting.md +222 -0
- package/skills/ui/refero-design/references/craft-details.md +525 -0
- package/skills/ui/refero-design/references/example-workflow.md +264 -0
- package/skills/ui/refero-design/references/icons.md +166 -0
- package/skills/ui/refero-design/references/mcp-tools.md +258 -0
- package/skills/ui/refero-design/references/motion.md +504 -0
- package/skills/ui/refero-design/references/typography.md +737 -0
- package/skills/ui/refero-design/references/visual-workflow.md +105 -0
- package/skills/ui/style-animaxxing/SKILL.md +48 -0
- package/skills/ui/style-animaxxing/agents/openai.yaml +7 -0
- package/skills/ui/style-animaxxing/references/motion-vocabulary.md +51 -0
- package/skills/ui/style-animaxxing/references/tokens.md +288 -0
- package/skills/ui/style-animaxxing/references/typography-and-layout.md +149 -0
- package/skills/ui/style-animaxxing/references/verification.md +38 -0
- package/skills/ui/typography-picker/SKILL.md +305 -0
- package/skills/ui/ui-core/SKILL.md +345 -0
- package/skills/ui/ui-core/references/accessibility.md +85 -0
- package/skills/ui/ui-core/references/build.md +666 -0
- package/skills/ui/ui-core/references/copy.md +70 -0
- package/skills/ui/ui-core/references/dark-mode.md +76 -0
- package/skills/ui/ui-core/references/direction.md +99 -0
- package/skills/ui/ui-core/references/redesign.md +74 -0
- package/skills/ui/ui-core/references/responsive.md +77 -0
- package/skills/ui/ui-core/references/styles.md +42 -0
- package/skills/ui/ui-core/references/system.md +190 -0
- package/skills/ui/ui-core/references/verify.md +37 -0
- package/skills/ui/ui-engineering/SKILL.md +436 -0
- package/skills/ui/ui-engineering/references/avatars.md +74 -0
- package/skills/ui/ui-engineering/references/card-patterns.md +66 -0
- package/skills/ui/ui-engineering/references/floating-actions.md +65 -0
- package/skills/ui/ui-engineering/references/navigation.md +81 -0
- package/skills/ui/ui-engineering/references/overlays.md +74 -0
- package/skills/ui/ui-engineering/references/pagination.md +71 -0
- package/skills/ui/ui-engineering/references/progress-indicators.md +77 -0
- package/skills/ui/ui-engineering/references/quality-bar.md +293 -0
- package/skills/ui/ui-engineering/references/search.md +68 -0
- package/skills/ui/ui-engineering/references/tailwind-architecture.md +81 -0
- package/skills/ui/ui-theme-picker/SKILL.md +522 -0
- package/skills/ui/ui-theme-picker/references/component-sources.md +223 -0
- package/skills/ui/ui-theme-picker/references/styles.md +298 -0
- package/skills/ui/vitepress-docs/SKILL.md +439 -0
- package/skills/ui/vitepress-docs/references/components.md +333 -0
- package/skills/ui/vitepress-docs/references/layout.md +128 -0
- package/skills/ui/vitepress-docs/references/tokens.md +87 -0
- package/skills/ui/vitepress-docs/references/typography.md +76 -0
- package/skills/workflow/careful/SKILL.md +48 -0
- package/skills/workflow/context-restore/SKILL.md +69 -0
- package/skills/workflow/context-save/SKILL.md +96 -0
- package/skills/workflow/health/SKILL.md +99 -0
- package/skills/workflow/learn/SKILL.md +95 -0
- package/skills/workflow/office-hours/SKILL.md +136 -0
- package/skills/workflow/ship/SKILL.md +95 -0
- package/vendor.json +80 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Page lifetime
|
|
2
|
+
|
|
3
|
+
Read this to know when a page mounts, updates in place, or unmounts, how the Svelte 5 lifecycle fits GSAP, and how Svelte's own transitions coexist with it.
|
|
4
|
+
|
|
5
|
+
## Reuse versus remount
|
|
6
|
+
|
|
7
|
+
SvelteKit renders a route as a pyramid: root layout, nested layouts, page. A navigation swaps only the levels whose component changed.
|
|
8
|
+
|
|
9
|
+
- Same route, new params or search params: the `+page.svelte` is reused. Its `data` and `page` update; `onMount`, `onDestroy`, and effects without a changed dependency do not run.
|
|
10
|
+
- Different route under the same layouts: the page unmounts and the new one mounts. The shared layouts stay, with their state, timelines, and listeners.
|
|
11
|
+
- A route that breaks out of a layout with `+page@` or a group: the layouts below the break remount too.
|
|
12
|
+
- `invalidate` and `invalidateAll` re-run `load` and update props. Nothing remounts.
|
|
13
|
+
- Shallow routing with `pushState` changes `page.state` only.
|
|
14
|
+
|
|
15
|
+
So a page intro tied to `onMount` plays once per mount, not once per visit. Two fixes:
|
|
16
|
+
|
|
17
|
+
- **`afterNavigate` in the page, the default for GSAP.** It fires on mount and after every navigation while the page stays mounted, with `type`, `from`, and `to`. Compare `from?.url.pathname` with `to?.url.pathname`, adding params when they mean a different screen, and skip when only search params changed. The page keeps its state and the DOM already holds settled values, so kill the previous timeline first and write initial state with `set` or `fromTo`, never a `from` tween that trusts a fresh node.
|
|
18
|
+
- **`{#key page.url.pathname}` around `{@render children()}` in the layout.** Every pathname change destroys and recreates the page, so `onMount` intros replay and `in:` and `out:` directives on the wrapper play. Use it when the page must be re-instantiated anyway or the effect is a Svelte transition. It discards page state and inner scroll positions, and it remounts on param changes, which is what the docs offer for that case.
|
|
19
|
+
|
|
20
|
+
Do not key the whole layout on `page.url`. That remounts the shell and its chrome on every navigation.
|
|
21
|
+
|
|
22
|
+
## Layouts and the controller
|
|
23
|
+
|
|
24
|
+
The root `+layout.svelte` mounts once per document and outlives every client-side navigation. That makes it the home of the route transition controller: one `bind:this` route container around `{@render children()}`, the navigation hooks, the phase in `$state`, and the cover. Nested layouts persist for their subtree and are the place for section-level chrome motion.
|
|
25
|
+
|
|
26
|
+
Pages register intro and outro builders with the controller through context or a shared module and unregister in their teardown. The controller calls the outgoing page's outro from `onNavigate` and the incoming page's intro from `afterNavigate`. A page that registers nothing gets the container-level default.
|
|
27
|
+
|
|
28
|
+
Hooks registered in a page are removed when it unmounts. A `beforeNavigate` in a page sees the navigation away from that page. An `afterNavigate` in a page sees its own arrival and every navigation while it stays mounted.
|
|
29
|
+
|
|
30
|
+
## Svelte 5 lifecycle for GSAP
|
|
31
|
+
|
|
32
|
+
- `onMount` with a synchronous callback returning cleanup, or `$effect` returning teardown, both run only in the browser after the DOM exists. `gsap-frameworks` covers the `gsap.context` and `revert` pattern. Use it unchanged.
|
|
33
|
+
- `$effect` re-runs when state it read synchronously changes, running its teardown first. An effect that reads `page.url`, `data`, or `navigating` re-runs on navigation, reverting and rebuilding the context, including on search-param changes. Read those values inside `afterNavigate` or through `untrack`, not in the effect body, unless the rebuild is intended.
|
|
34
|
+
- `bind:this` values are `undefined` during initialization. Read them in an effect or `onMount`.
|
|
35
|
+
- `$effect.pre` runs before the DOM update it is scheduled with. `tick()` resolves after pending changes are applied. Use them to measure before and after an update. `beforeUpdate` and `afterUpdate` do not exist in runes mode.
|
|
36
|
+
- `{@attach}` runs a function in an effect when its element mounts, again when state it reads changes, with an optional teardown. It suits per-element GSAP setup that must follow an element through `{#each}` blocks.
|
|
37
|
+
- Store the phase in `$state` and render a data attribute from it. Do not infer the phase from opacity or DOM presence.
|
|
38
|
+
- `onDestroy` runs during server rendering. Keep GSAP out of it, or guard with `browser`.
|
|
39
|
+
|
|
40
|
+
## Combining engines
|
|
41
|
+
|
|
42
|
+
Svelte transitions, GSAP, and View Transitions can share a page but not a node.
|
|
43
|
+
|
|
44
|
+
- A `transition:`, `in:`, or `out:` directive drives its node through the Web Animations API or a `tick` function. A GSAP tween on the same node writes the same properties and one of them loses. Put the directive on a wrapper and GSAP inside it, or use one engine.
|
|
45
|
+
- When a block with an `out:` directive is removed, every element in the block stays in the DOM until every outro in it finishes, and the new content is inserted at once, so old and new are in flow together. Use that when the effect is a crossfade in a stacked container. Avoid it when GSAP owns the outro: the block lingers past the GSAP end state after the router has moved on.
|
|
46
|
+
- Directives are local by default: one plays when its own block is created or destroyed, including when the router swaps a page whose root carries it, but not when an outer `{#if}` in the same component toggles. Add `|global` only when that outer toggle should play it.
|
|
47
|
+
- Svelte transitions ignore `@media (prefers-reduced-motion)` rules that zero CSS durations. Zero their `duration` from `prefersReducedMotion.current` in `svelte/motion` and take the GSAP reduced path in the same condition.
|
|
48
|
+
- `svelte/animate` on `{#each}` items and GSAP Flip solve the same problem. Pick one per list.
|
|
49
|
+
- View Transitions snapshot whatever the DOM shows, including a half-finished directive or a GSAP end state. Start them only after both have reached the state you want photographed.
|
|
50
|
+
|
|
51
|
+
## Conditional content
|
|
52
|
+
|
|
53
|
+
`{#if}` removes a block synchronously unless a directive inside it is outroing. For GSAP-driven show and hide, keep the node mounted with a presence controller: render while `visible || leaving`, play the outro, and clear `leaving` from the end callback. For a plain fade, `out:fade` on the block is the presence controller and needs no GSAP.
|
|
54
|
+
|
|
55
|
+
A shallow-routed modal is a presence controller with history as its close. Open with `pushState`, close by playing the outro and then calling `history.back()`, and treat the resulting `popstate` as the removal, not as a page navigation. Undo scroll locks, key listeners, and focus in the modal's teardown, which also covers a back navigation you did not initiate.
|
|
56
|
+
|
|
57
|
+
## SSR and hydration
|
|
58
|
+
|
|
59
|
+
- `$effect` and `onMount` do not run on the server. Keep GSAP out of module scope, or guard with `browser` from `$app/environment`. Importing GSAP on the server is harmless; running it is not.
|
|
60
|
+
- Register plugins once in a browser-guarded module that other modules import.
|
|
61
|
+
- Hydration paints server HTML first. The first-paint rule in [The swap gap and initial state](sveltekit-navigation.md#the-swap-gap-and-initial-state) is the only sanctioned way to hide before the first intro.
|
|
62
|
+
- `csr = false` on a page removes the client router; navigation hooks never fire there. `ssr = false` gives an empty shell until the client renders, so the first intro can wait for mount without a pre-paint rule.
|
|
63
|
+
- `afterNavigate` with `type: 'enter'` is the first-load intro. A prerendered page gets it on hydration like any other. A bfcache restore runs no hook at all.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# SvelteKit navigation
|
|
2
|
+
|
|
3
|
+
Read this when changing route-level motion or navigation.
|
|
4
|
+
|
|
5
|
+
## Router APIs
|
|
6
|
+
|
|
7
|
+
Check the installed SvelteKit types before using these. Everything below comes from `$app/navigation` unless noted. The hooks must be called during component initialization and stay active while that component is mounted.
|
|
8
|
+
|
|
9
|
+
- `beforeNavigate(cb)`: fires before every navigation the router sees: link clicks, `goto`, GET forms, back and forward, and leaving the document. Receives `type`, `from`, `to`, `willUnload`, `delta` (popstate only), `complete`, and `cancel()`. Not called for a redirect issued while a navigation is already in flight.
|
|
10
|
+
- `onNavigate(cb)`: fires immediately before the new page renders, only for client-side navigation. Return a promise and SvelteKit waits for it before updating the DOM. Return a function, or a promise resolving to one, and it runs once after the DOM has updated.
|
|
11
|
+
- `afterNavigate(cb)`: fires after every navigation while the calling component stays mounted, and once with `type: 'enter'` after hydration. That first call is dispatched from the router's initialization one microtask after the root mounts, so whether a page component has registered by then is a race; the intro path must also work when the page mounts after the `enter` call has passed. `to.scroll` is the position actually applied.
|
|
12
|
+
- `goto(url, { replaceState, noScroll, keepFocus, invalidateAll, invalidate, state })`: programmatic navigation. Resolves when the navigation completes and rejects when it is cancelled or aborted. Not for external URLs; assign `location` instead.
|
|
13
|
+
- `preloadData(href)`: imports the destination's code and runs its `load` now. If the next navigation goes there, the result is reused.
|
|
14
|
+
- `disableScrollHandling()`: skips the router's scroll for the navigation in progress. Legal only while the page is updating.
|
|
15
|
+
- `pushState` and `replaceState`: history entries without navigation, for shallow routing.
|
|
16
|
+
- `navigating` from `$app/state`: `from`, `to`, `type`, and `delta` while a navigation is in flight, `null` otherwise. `page` from `$app/state`: current `url`, `route`, `params`, and `state`. Both are reactive only in runes mode.
|
|
17
|
+
- Link attributes: `data-sveltekit-preload-data`, `data-sveltekit-preload-code`, `data-sveltekit-noscroll`, `data-sveltekit-replacestate`, `data-sveltekit-keepfocus`, `data-sveltekit-reload`. They apply to an `a` or any ancestor, and to GET forms.
|
|
18
|
+
|
|
19
|
+
`type` values: `link`, `goto` (also redirects), `form` (GET forms), `popstate` (back and forward), `enter` (hydration, `afterNavigate` only), `leave` (document unload, `beforeNavigate` only).
|
|
20
|
+
|
|
21
|
+
The navigation object carries an undocumented `event`. Do not build on it.
|
|
22
|
+
|
|
23
|
+
## Order of one navigation
|
|
24
|
+
|
|
25
|
+
Read from the client runtime. Confirm against the installed version when timing matters.
|
|
26
|
+
|
|
27
|
+
1. `beforeNavigate` callbacks. Any `cancel()` stops here. Cancelling a `popstate` also moves history back by `delta`.
|
|
28
|
+
2. `navigating` is set. `load` functions run, reusing a matching preload.
|
|
29
|
+
3. The outgoing page's snapshot is captured. History is pushed or replaced, so the URL bar already shows the destination.
|
|
30
|
+
4. `onNavigate` callbacks, awaited together. The old page is still mounted and live, and `page` still reports the old URL.
|
|
31
|
+
5. Focus is blurred, the component tree updates, and Svelte flushes. Reused components receive new props; new ones mount and run `onMount` and `$effect`.
|
|
32
|
+
6. Scroll: restored for `popstate`, kept for `noScroll`, moved to a hash target, otherwise top. Skipped after `disableScrollHandling()`.
|
|
33
|
+
7. Focus is reset to `body`, or an `autofocus` element, unless `keepFocus` was set or something already moved it.
|
|
34
|
+
8. `complete` resolves, `afterNavigate` callbacks and the functions returned from `onNavigate` run, the snapshot is restored for `popstate`, and `navigating` returns to `null`.
|
|
35
|
+
|
|
36
|
+
The router checks for a newer navigation after step 2 and after step 5 and abandons the older one there, rejecting its `complete`. It does not check between steps 4 and 5, so an older `onNavigate` that resolves late still updates the DOM once before it is abandoned. The lock below exists for this.
|
|
37
|
+
|
|
38
|
+
## Page lifecycle
|
|
39
|
+
|
|
40
|
+
**mount → initial state → intro → settled → outro → end state → unmount**
|
|
41
|
+
|
|
42
|
+
1. **Initial state.** The incoming page has mounted or updated in place, its final size is reserved, measurements are taken, and start values are set before anything is shown.
|
|
43
|
+
2. **Intro.** Reveal the route and play one timeline to the final layout.
|
|
44
|
+
3. **Settled.** Clear temporary styles. CSS owns the page. Everything is interactive.
|
|
45
|
+
4. **Outro.** The outgoing page stays mounted while the router waits. Stop competing component animations and play one outro timeline.
|
|
46
|
+
5. **End state.** Finalize outgoing targets and run completion once while still mounted. Resolve the router's wait. The outgoing tree goes away as the incoming one renders.
|
|
47
|
+
|
|
48
|
+
A controller may track internal states like `waiting` or `preparing`, but they serve these five phases.
|
|
49
|
+
|
|
50
|
+
Store the phase in `$state` owned by the layout controller and render it as a data attribute on the route container, so CSS and tests can read it. Svelte batches state, so two phase writes in one tick reach the DOM as one attribute change and an observer sees only the last; `await tick()` between them, or write the attribute on the container directly when consecutive phases must each be visible.
|
|
51
|
+
|
|
52
|
+
## Outro before navigation: two hooks
|
|
53
|
+
|
|
54
|
+
Both run on the old page. Pick one per project and use it everywhere. The choice turns on one fact: `history.pushState` runs before the router awaits `onNavigate`, so on that path the address bar already shows the destination while the old page animates. If the outro must play with the URL unchanged, which is what "outro before navigation" usually means, only `beforeNavigate` does it.
|
|
55
|
+
|
|
56
|
+
**`beforeNavigate`, the default.** Call `cancel()`, play the outro on the untouched page, then `goto(to.url)` from the end callback. The outro starts on click and the URL waits. The costs: the re-issued navigation re-enters `beforeNavigate`, so set a guard before `goto` and consume it inside the callback that sees the re-issued navigation, not on the `goto` promise, which resolves too late and leaves a window where the next real click passes unblocked; the re-issued navigation is `type: 'goto'` and drops the link's `replaceState`, `noScroll`, and `keepFocus` intent unless the controller reads those attributes from the link itself; a GET form cannot be re-issued cleanly; and `load` runs after the outro, so the end state sits on screen until the new page arrives and needs a cover or a presentable look. Call `preloadData(to.url.href)` when the outro starts so the fetch overlaps it. Never cancel `popstate`.
|
|
57
|
+
|
|
58
|
+
**`onNavigate`, the alternative.** Return the outro's promise; SvelteKit renders the new page when it resolves. Nothing is cancelled or re-issued, so `data-sveltekit-*` options, `goto` options, GET forms, and `type` survive, `afterNavigate` reports what really happened, and there is no swap gap: `load` has already finished, so the new page renders the moment the outro ends and no cover is needed. The costs: the URL changes before the outro, and the outro starts after `load`, not on click, so a slow route shows a still page first. Mitigate the second with `data-sveltekit-preload-data="hover"`, the template default, and a pending style from `navigating`. Return nothing for `popstate`. Use it when a URL that leads the animation is acceptable.
|
|
59
|
+
|
|
60
|
+
Neither hook delays a `willUnload` navigation. `type: 'leave'` cannot be delayed; `cancel()` there only raises the browser's unload dialog. An external link, where `to.route.id` is `null`, can be cancelled in `beforeNavigate`, outroed, and followed with `location.assign`, which is the `gsap-vanilla` path.
|
|
61
|
+
|
|
62
|
+
## One navigation at a time
|
|
63
|
+
|
|
64
|
+
The lock depends on the path.
|
|
65
|
+
|
|
66
|
+
- On the `beforeNavigate` path the first click cancelled its navigation, so the router is idle during the outro and `beforeNavigate` fires again for a second click. While the phase is `outro` or the incoming page is preparing, `cancel()` `link`, `goto`, and `form` navigations, or record the destination and `goto` it from the end callback if the design retargets.
|
|
67
|
+
- On the `onNavigate` path there is no lock to hold. The router runs `beforeNavigate` callbacks only while it is idle, and it is busy from the moment it accepted the first click until just before `afterNavigate`, so a second click never reaches them. It starts a newer navigation that supersedes the first; the router abandons the old one at its next check. Kill the outro so its promise settles and let the newer navigation own the page.
|
|
68
|
+
- Do not cancel `popstate`. Kill the running outro so its promise resolves at once and the pending navigation commits before the history navigation renders.
|
|
69
|
+
- Release the lock when the incoming intro starts, not when it ends: a click during the intro must kill the intro and start the outro from current values, and holding the lock through the intro leaves every link dead until it finishes.
|
|
70
|
+
|
|
71
|
+
A killed timeline never resolves its promise. Wrap `await` in a helper that also resolves on `onInterrupt` and returns whether the timeline completed, so an interrupted outro never leaves `onNavigate` pending.
|
|
72
|
+
|
|
73
|
+
GSAP's ticker stops in a hidden tab. Race the outro against a timeout so a click from a background tab still navigates.
|
|
74
|
+
|
|
75
|
+
## Two kinds of navigation
|
|
76
|
+
|
|
77
|
+
- **Requested** (`link`, `goto`, `form`): the full lifecycle. The outgoing page plays its outro on live DOM, the router waits, the incoming page prepares and plays its intro.
|
|
78
|
+
- **Unrequested** (`popstate`, redirects from `load`, `invalidateAll` re-renders, links marked `data-sveltekit-reload`): the tree changes without an outro, or the document reloads. Run initial state and intro only, without travel. Keep the shell stable. Optionally wrap the swap in `document.startViewTransition` from `onNavigate` so it is not a hard cut.
|
|
79
|
+
|
|
80
|
+
Do not keep a copy of the old page to fake an outro for unrequested navigation. Support fewer outro paths instead.
|
|
81
|
+
|
|
82
|
+
## Back and forward
|
|
83
|
+
|
|
84
|
+
`popstate` goes through `beforeNavigate`, `onNavigate`, and `afterNavigate` like any navigation, with `delta` and, before the DOM updates, `to.scroll` holding the position that will be restored.
|
|
85
|
+
|
|
86
|
+
- Never run an outro. Return nothing from `onNavigate`.
|
|
87
|
+
- The router restores scroll before `afterNavigate`. Start the intro from `afterNavigate`, then refresh ScrollTrigger. Reveal-on-scroll targets above the restored position must not stay hidden.
|
|
88
|
+
- Snapshots are restored after `afterNavigate`. Do not put the phase in a snapshot.
|
|
89
|
+
- A page reached by back that was reused rather than remounted still holds settled values. Write initial state explicitly.
|
|
90
|
+
- Leaving the site and coming back may restore the document from the bfcache. SvelteKit only clears `navigating` on `pageshow`; no hook runs. Leave the page readable whenever `willUnload` is true.
|
|
91
|
+
|
|
92
|
+
## Overlapping the old and new page
|
|
93
|
+
|
|
94
|
+
The router shows one page tree. An effect that needs both on screen at once has three honest options.
|
|
95
|
+
|
|
96
|
+
- **The browser.** `document.startViewTransition` in `onNavigate` snapshots both. A class on `html` gives the CSS the direction.
|
|
97
|
+
- **A Svelte `out:` directive** on the page root, or on a `{#key}` wrapper in the layout. Svelte inserts the new page at once and keeps the old one until its outro ends, both in normal flow, so stack them with a grid or position the outgoing one absolutely inside the route container, and keep GSAP off the node that carries the directive. See [Combining engines](page-lifetime.md#combining-engines).
|
|
98
|
+
- **A DOM snapshot.** After the outgoing page reaches end state and before resolving `onNavigate`, deep-clone the route container into a fixed layer: strip ids and every data attribute your lifecycle selects on, set `inert` and `aria-hidden`, position it at the container's document offset shifted by the scroll. The incoming intro reveals the new page over the clone and removes it at settle, on a ready timeout, on `popstate`, and at the start of any new navigation.
|
|
99
|
+
|
|
100
|
+
The clone is a static picture, not a component: nothing in it updates, and it is gone before the page is interactive.
|
|
101
|
+
|
|
102
|
+
## The swap gap and initial state
|
|
103
|
+
|
|
104
|
+
With `onNavigate` there is no gap: the new page renders as soon as the promise resolves. With `beforeNavigate` the old page sits at end state while `load` runs. Cover the route container during that gap, inside the element that wraps route content and never fixed to the viewport, or the header and footer flash on every click. Uncover only after every incoming target has its size and start styles.
|
|
105
|
+
|
|
106
|
+
The initial state must occupy the same layout as the settled state. Prefer `autoAlpha` and transforms. Size images, media, masks, and async regions before the intro. If the effect changes geometry, reserve the settled size with a wrapper or measure both states before writing either.
|
|
107
|
+
|
|
108
|
+
The route container owns geometry during the swap: hold a stable height while trees exchange, or animate it between measured sizes on purpose; if old and new are both mounted, overlap them so only one takes up space; reserve scrollbar space if route height changes would shift it.
|
|
109
|
+
|
|
110
|
+
Server-rendered HTML paints before hydration. Do not hide it unconditionally. If initial state must hide before first paint:
|
|
111
|
+
|
|
112
|
+
- Put an inline script first in `body` in `src/app.html` that marks `html` as JavaScript-active, and a CSS rule that hides intro targets only under that mark and only while the root is in its initial phase.
|
|
113
|
+
- Skip the mark under `prefers-reduced-motion` so the page paints settled.
|
|
114
|
+
- Keep the early failsafe active until preparation succeeds and the intro can run, not merely until a controller registers. Register rollback before setup, preserve the original deadline, and take the settled path after recovery. Follow [Initialization and recovery](initialization.md).
|
|
115
|
+
- Register recovery before setup. Advance the phase only after start values and completion handlers are ready, in the same turn that starts the intro.
|
|
116
|
+
- Keep content readable without JavaScript and keep the swap cover separate from the first-paint rule.
|
|
117
|
+
|
|
118
|
+
Do not rely only on inline styles: a context revert clears them during a swap. The cover must survive cleanup until the new tree is ready.
|
|
119
|
+
|
|
120
|
+
## Preloading and streaming
|
|
121
|
+
|
|
122
|
+
- Hover and tap preloading run `load` before the click. With `onNavigate` this is what lets the outro start promptly. With `beforeNavigate`, `preloadData` at outro start does the same.
|
|
123
|
+
- Preloaded data is dropped by invalidation or by a navigation elsewhere. Do not assume it survives a long outro.
|
|
124
|
+
- Promises streamed from `load` resolve after the page renders. Treat each streamed region as a component with its own controller: explicit initial state on arrival, a short intro, settled, cleanup. Reserve its block size so arrival moves nothing. Query outro targets when the outro is built, not at setup, so content that streamed in after setup leaves with the page.
|
|
125
|
+
|
|
126
|
+
## Settled state, focus, and scroll
|
|
127
|
+
|
|
128
|
+
On intro completion, mark settled once, clear temporary transforms, visibility, and `will-change`, and do not keep the page inside an active timeline to hold values.
|
|
129
|
+
|
|
130
|
+
- SvelteKit focuses `body`, or an `autofocus` element, before `afterNavigate`. Move focus to the main heading from `afterNavigate` only when the design needs it, with `tabindex="-1"` and a visible focus style. Do not steal focus from an active control.
|
|
131
|
+
- Keep the router's scroll behavior. Call `disableScrollHandling()` only while the page is updating, from the incoming page's `onMount` or an effect, then own the scroll yourself. In the current runtime `afterNavigate` runs after the scroll has been applied; check the installed version before calling it there.
|
|
132
|
+
- Refresh ScrollTrigger after scroll restoration, and after the intro if anything above a trigger changed height.
|
|
133
|
+
- SvelteKit's live region announces the new `title`. Give every page a title in `svelte:head` so an animated navigation is still announced.
|
|
134
|
+
|
|
135
|
+
## Combining with View Transitions
|
|
136
|
+
|
|
137
|
+
The documented recipe wraps the update: `onNavigate` returns a promise that `document.startViewTransition`'s callback resolves, and the callback then awaits `navigation.complete`, so the old snapshot is taken before the DOM updates and the new one after. GSAP runs before it, outro on live DOM awaited before the transition starts, and after it, intro on the new tree after `finished` for elements the transition touched. Keep their jobs separate:
|
|
138
|
+
|
|
139
|
+
- One engine per element per transition. A named morph and a GSAP tween on the same node fight, and a GSAP end state becomes the old snapshot.
|
|
140
|
+
- If the outro fades content the browser will morph, leave the shared element lit at end state or skip the view transition for that navigation.
|
|
141
|
+
- Name only elements that morph, per page, and clear names after each transition. Name chrome to hold it still.
|
|
142
|
+
- Set a direction class on `html` before starting the transition and remove it in `finished`. Read the same decision in the GSAP builders.
|
|
143
|
+
- Add `::view-transition { pointer-events: none }` so a running transition does not swallow clicks.
|
|
144
|
+
- Feature-detect `document.startViewTransition`. Every GSAP path must run when it is missing.
|
|
145
|
+
- Reduced motion covers both: zero view transition durations in CSS and take the GSAP reduced path.
|
|
146
|
+
|
|
147
|
+
## Cases to design for
|
|
148
|
+
|
|
149
|
+
- Navigation requested mid-intro.
|
|
150
|
+
- Two destinations clicked quickly.
|
|
151
|
+
- Back or forward with no outro, including mid-outro.
|
|
152
|
+
- A page reused with new params, and a search-param-only change.
|
|
153
|
+
- Programmatic `goto` and a GET form that bypass any link wrapper.
|
|
154
|
+
- A hash-only link, which the router leaves to the browser.
|
|
155
|
+
- A redirect from `load`, which skips `beforeNavigate`.
|
|
156
|
+
- An external link and a `data-sveltekit-reload` link, which unload the document.
|
|
157
|
+
- Split text or scroll plugins that changed the DOM before cleanup.
|
|
158
|
+
- Streamed data arriving after the intro.
|
|
159
|
+
|
|
160
|
+
Each case must end on one visible, interactive page with stable layout and no stale inline styles.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Verification
|
|
2
|
+
|
|
3
|
+
Check in proportion to what changed. Do not turn a focused animation task into a full audit.
|
|
4
|
+
|
|
5
|
+
## Always
|
|
6
|
+
|
|
7
|
+
- Run the repo's `svelte-check`, lint, format, and test commands where they exist.
|
|
8
|
+
- Confirm settled content is visible, interactive, and free of leftover GSAP inline styles.
|
|
9
|
+
- Confirm timelines, triggers, listeners, and plugin DOM changes are cleaned up on unmount and on a reused page's re-run.
|
|
10
|
+
- Confirm the page is readable with JavaScript disabled and with the pre-paint mark set but hydration blocked.
|
|
11
|
+
- Test reduced motion when the change has a reduced-motion branch, for GSAP and for any Svelte directive.
|
|
12
|
+
|
|
13
|
+
## Initially hidden content
|
|
14
|
+
|
|
15
|
+
Run the [failure verification matrix](initialization.md#failure-verification) when adding or changing hiding, preparation, or recovery. It covers disabled JavaScript, a blocked bundle after the marker, throws before/after styles and splits, stalled fonts/media, late initialization, no-flash success, reduced motion, and interruption/repeated setup. Assert text and native links, not opacity alone. Include shell/footer and intentionally hidden content.
|
|
16
|
+
|
|
17
|
+
Use this framework's [integration rules](motion-system.md#initialization-and-recovery) for rendering and navigation expectations. Measure document-load LCP separately from transitions when first-load behavior changes; report measured results and untested paths.
|
|
18
|
+
|
|
19
|
+
## Runtime changes
|
|
20
|
+
|
|
21
|
+
Check the changed lifecycle in a real browser when practical:
|
|
22
|
+
|
|
23
|
+
- Initial state is applied before reveal. Throttle the network and reload; no settled server HTML flashes before hydration.
|
|
24
|
+
- Intro ends in one settled state.
|
|
25
|
+
- Outro keeps the node mounted until completion runs, and only then does the held navigation re-issue or the `onNavigate` promise resolve. On the `beforeNavigate` path the URL is unchanged for the whole outro.
|
|
26
|
+
- Rapid or interrupted input ends in one coherent state.
|
|
27
|
+
- Layout boxes do not jump.
|
|
28
|
+
|
|
29
|
+
For route navigation, test the paths the change affects: an ordinary internal link, back and forward, a rapid double navigation, a same-route param change, a search-param-only change, a `goto`, and a reload. Confirm URL, visible page, focus, history, and scroll agree, and that `navigating` returns to `null`.
|
|
30
|
+
|
|
31
|
+
For a reused page, the returning lifecycle must run initial state and intro on its preserved DOM with no doubled tweens, and scroll triggers must measure correctly after new data renders.
|
|
32
|
+
|
|
33
|
+
When Svelte directives or View Transitions are involved, confirm no element is animated by two engines, outroing blocks are gone once their outro ends, and clicks land during a running transition.
|
|
34
|
+
|
|
35
|
+
For conditional components, test show, hide, and one interruption. Confirm removal happens after the outro.
|
|
36
|
+
|
|
37
|
+
## Builds and wider checks
|
|
38
|
+
|
|
39
|
+
Run a production build for changes to routes, `svelte.config.js`, page options, dependencies, `src/app.html`, or anything release-facing; the dev server hydrates differently from the built output. Serve the build the way the adapter does: under `adapter-node` that is `node build`, since `vite preview` serves no server-rendered routes there. Run wider browser, accessibility, responsive, streaming, and performance checks only when the change touches them or the user asks for a full audit.
|
|
40
|
+
|
|
41
|
+
Report which checks ran and which could not. Do not claim runtime behavior was verified when only static review was possible.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gsap-tanstack-router
|
|
3
|
+
description: "Build or review TanStack Router for React and TanStack Start animation: GSAP page transitions, component enter/exit, scroll effects, useBlocker, pending UI, route reuse, and cleanup. Use even when GSAP is unnamed, including choosing viewTransition. Also covers hidden-content recovery and first-load performance. Not for Solid, other routers, React without routing, or isolated GSAP API questions."
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
short-description: GSAP page and component lifecycles in TanStack Router
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# GSAP TanStack Router
|
|
10
|
+
|
|
11
|
+
**mount → initial state → intro → settled → outro → end state → unmount**
|
|
12
|
+
|
|
13
|
+
Mount and unmount belong to React; animation owns the five phases between them. TanStack Router preserves shared layouts and can reuse routes on parameter changes; pending UI and loaders also affect when the new page appears.
|
|
14
|
+
|
|
15
|
+
Keep the requested look and existing project conventions. Add GSAP/plugins only as needed; do not replace the chosen animation library unless asked.
|
|
16
|
+
|
|
17
|
+
## Start with the project
|
|
18
|
+
|
|
19
|
+
Read repository instructions, existing animation, layouts, navigation, CSS, accessibility conventions, and checks. Then:
|
|
20
|
+
|
|
21
|
+
1. Confirm `@tanstack/react-router`. Next.js belongs to `gsap-nextjs`, React Router to `gsap-react-router`, React without a router to `gsap-react`. Solid Router is out of scope.
|
|
22
|
+
2. Read the installed `@tanstack/react-router` version and, when present, `@tanstack/react-start`. Prefer their bundled types over memory: `node_modules/@tanstack/router-core/dist/esm/router.d.ts` for `RouterOptions`, `RouterState`, and `RouterEvents`, `node_modules/@tanstack/react-router/dist/esm/useBlocker.d.ts` for the blocker, `node_modules/@tanstack/history/dist/esm/index.d.ts` for history actions. The TanStack/router repository's `docs/router/` and `docs/start/` are the source of truth. The loading architecture changed during the 1.16x and 1.17x releases; `RouterState.isTransitioning` is gone from router-core 1.171.2x, and `useBlocker` is still marked experimental.
|
|
23
|
+
3. Tell file-based routes (`createFileRoute`, `routeTree.gen.ts`, `__root.tsx`) from code-based routes (`createRoute`, `createRootRoute`). The lifecycle is the same; only where route options live differs.
|
|
24
|
+
4. Tell TanStack Start (SSR, a root document shell with `HeadContent` and `Scripts`) from a client-only Vite app (`RouterProvider` rendered into a div). Client-only apps paint nothing before React, so they need no pre-paint rule. Check `ssr` per route, `defaultSsr`, `spa.enabled`, and prerendering.
|
|
25
|
+
5. Read the router options: `defaultPreload`, `defaultPendingComponent`, `defaultPendingMs`, `defaultPendingMinMs`, `defaultViewTransition`, `scrollRestoration`, `defaultStaleTime`, `defaultRemountDeps`. Each changes when pages mount and what the user sees while they load.
|
|
26
|
+
|
|
27
|
+
## Choose the engine
|
|
28
|
+
|
|
29
|
+
Use `defaultViewTransition` or Link/`navigate` `viewTransition` for snapshot morphs or page crossfades. Use GSAP for live-DOM outros that gate navigation, interruptible sequences, split text, or scroll-linked motion. One engine per element; see [combining engines](references/tanstack-navigation.md#combining-with-view-transitions).
|
|
30
|
+
|
|
31
|
+
## Read only what you need
|
|
32
|
+
|
|
33
|
+
- Invisible entrances, failed initialization, indexing, and first-load performance: [Initialization and recovery](references/initialization.md), plus the [framework integration](references/motion-system.md#initialization-and-recovery).
|
|
34
|
+
- Router APIs and the order of one navigation, outro before navigation with `useBlocker` or an intercepted Link, the lock, back and forward, pending UI, the swap gap, scroll, focus, View Transitions: [TanStack navigation](references/tanstack-navigation.md).
|
|
35
|
+
- Route reuse versus `remountDeps`, layouts and `Outlet`, the React lifecycle for GSAP, conditional content, TanStack Start SSR and hydration, deferred data: [Route lifetime](references/route-lifetime.md).
|
|
36
|
+
- The five phases, GSAP setup, show and hide, layout stability, scroll, text, plugins: [Lifecycle implementation](references/motion-system.md).
|
|
37
|
+
- Before calling work done: [Verification](references/verification.md).
|
|
38
|
+
|
|
39
|
+
Install the [official GSAP skills](https://github.com/greensock/gsap-skills) alongside this repository. Load `gsap-core` for API details and `gsap-react` for component setup only as needed.
|
|
40
|
+
|
|
41
|
+
## Rules
|
|
42
|
+
|
|
43
|
+
- Preserve invisible intros on successful setup; recover the current incoming owner on failure. Follow the initialization contract before adding hiding rules.
|
|
44
|
+
- GSAP runs only on the client. `useGSAP` never runs on the server; keep GSAP calls out of module scope in files Start renders on the server. Scope selectors. Clean up every tween, trigger, split, and listener.
|
|
45
|
+
- Reserve final geometry with normal CSS and a stable wrapper; overlap outgoing/incoming content without doubling layout space.
|
|
46
|
+
- Mount, then set initial values, then paint. Successful initialization never flashes settled content before the intro. Under Start, server HTML paints before hydration, so hide intro targets only under a root attribute set by a `ScriptOnce` inline script, only during the initial phase, with a no-JavaScript path.
|
|
47
|
+
- Animate to one settled state and clear temporary styles there.
|
|
48
|
+
- Keep outgoing pages mounted and visible through outro and end state. The router swaps only after every blocker allows the navigation and the loaders finish; resolve the blocker from the end callback.
|
|
49
|
+
- No router event fires before the URL changes. `onBeforeNavigate` runs after the history commit; only a blocker runs before it.
|
|
50
|
+
- A navigation to the same route with new params reuses the component. Run the lifecycle again against DOM that already holds settled values, keyed on the params, or set `remountDeps`.
|
|
51
|
+
- Back and forward arrive with `action` `BACK`, `FORWARD`, or `GO`. Never run an outro for them; the URL has already moved when the blocker runs. Give them an intro-only path after scroll restoration.
|
|
52
|
+
- `useLocation` moves to the destination when loading starts, before the new page mounts. Do not key route content on it; key on the presented matches or on `resolvedLocation`.
|
|
53
|
+
- Keep native link behavior, preloading, `activeProps`, focus, scroll, and no-JavaScript readability.
|
|
54
|
+
- Reduced motion reaches the same settled state and still fires every completion callback, including the one that lets the blocked navigation proceed.
|
|
55
|
+
- Define interruption and rapid-click behavior; completion must release navigation waits exactly once.
|
|
56
|
+
- Verify in a real browser when practical. Use a production build for route, config, dependency, or release changes.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "GSAP TanStack Router"
|
|
3
|
+
short_description: "GSAP page and component lifecycles in TanStack Router"
|
|
4
|
+
default_prompt: "Use $gsap-tanstack-router to add GSAP page transitions and component animation to this TanStack Router app."
|
|
5
|
+
|
|
6
|
+
policy:
|
|
7
|
+
allow_implicit_invocation: true
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<!-- Generated from shared/initialization.md; run scripts/sync_initialization.py. -->
|
|
2
|
+
|
|
3
|
+
# Invisible intros, recovery, and first load
|
|
4
|
+
|
|
5
|
+
Read this whenever an entrance hides meaningful content. The matching framework skill owns initialization, navigation, recovery, and interruption. Motion recipes own teardown and restoration of their changes. Styles select the look and pacing only.
|
|
6
|
+
|
|
7
|
+
## Keep the successful intro
|
|
8
|
+
|
|
9
|
+
Build readable, settled HTML and CSS first. Preserve invisible-to-visible entrances with a small early script and scoped pre-paint CSS:
|
|
10
|
+
|
|
11
|
+
```css
|
|
12
|
+
html[data-motion-boot="pending"] [data-motion-owner][data-phase="initial"][data-intro],
|
|
13
|
+
html[data-motion-boot="pending"] [data-motion-owner][data-phase="initial"] [data-intro] {
|
|
14
|
+
visibility: hidden;
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Names are examples. Use separate attributes for boot status, motion preference, and lifecycle phase. Rename a `data-motion="js"` boot example if the app already uses `data-motion="full|reduced"` for preference. Opt in only targets intended to enter visibly, including hidden ancestors, shell, cards, and footer. Give independent owners their own readiness records. One ready page must not cancel a footer's protection.
|
|
19
|
+
|
|
20
|
+
- Run the marker before content can paint, using the framework's document integration and CSP nonce/hash support. Arm its recovery timer before setting the marker. It must work without GSAP or the application bundle. If the marker is blocked, content stays readable.
|
|
21
|
+
- Never emit the active marker in server HTML. JavaScript disabled means no marker and readable HTML. A `noscript` override alone does not cover JavaScript enabled with a failed bundle.
|
|
22
|
+
- Skip hiding under reduced motion. Preserve completion, focus, navigation, and removal semantics through the instant path.
|
|
23
|
+
- Before releasing CSS hiding, prepare all required start values and attach the entrance's completion/interruption handlers. Start the timeline in the same turn. Do not flip the phase early to claim readiness: that can flash settled content.
|
|
24
|
+
- Do not hide server content through unconditional CSS, inline styles, client-only wrappers, or a hidden ancestor that the fallback cannot restore.
|
|
25
|
+
|
|
26
|
+
## Bound initialization, not choreography
|
|
27
|
+
|
|
28
|
+
Give each incoming owner an initialization deadline, measured from its first pre-paint hiding. Choose and document a short budget; roughly one second is a starting point, not a universal performance target.
|
|
29
|
+
|
|
30
|
+
The early timer covers bundle delivery and hydration. Register recovery before any setup work, including plugin registration, selectors, initial writes, and splits. Keep the deadline armed through required font/media preparation and timeline construction. Registration or a `live` flag is not readiness. Handing off timers must leave no unprotected interval and must not restart the budget.
|
|
31
|
+
|
|
32
|
+
A successful handoff occurs only when the prepared intro can run with its handlers attached. Cancel the initialization timer then. A deliberate hold or stagger inside that timeline belongs to animation duration, even if it exceeds the initialization budget. Handle runtime exceptions and interruptions separately; if a running timeline needs a watchdog, derive it from its planned duration, delay, repeats, and pause policy. Never cut a healthy intro short with the boot timer. Recheck deadlines on return from a suspended tab; timers cannot recover a blocked main thread.
|
|
33
|
+
|
|
34
|
+
Wait only for dependencies the effect needs. Bound font readiness, image load/decode, SplitText auto-split preparation, and frame waits. Prefer reserved image dimensions and a fallback font or unsplit heading over waiting for every font, image, or window `load`. A timed-out promise may still resolve: racing it does not cancel its continuation.
|
|
35
|
+
|
|
36
|
+
## Recover one owner
|
|
37
|
+
|
|
38
|
+
Track an owner, a visit/generation token, and a terminal recovery decision outside disposable effect setup. Use boot status such as `pending`, `running`, `recovered`, `disposed` separately from the framework's lifecycle phases. A recovery is permanent for that visit; a genuine later navigation may create a new visit. Repeated setup is not a new visit.
|
|
39
|
+
|
|
40
|
+
On timeout, rejection, setup exception, or failed entrance:
|
|
41
|
+
|
|
42
|
+
1. Verify the captured owner and generation are still current and intended to be visible. Invalidate the generation first. Mark it recovered so reentrant handlers cannot restart it.
|
|
43
|
+
2. Abort preparation where supported. Cancel queued frames, timers, event listeners, observers, and subscriptions that can recreate motion. Kill owned timelines, delayed calls, triggers, and ambient effects before restoring content. Do not kill unrelated GSAP work globally.
|
|
44
|
+
3. Run registered effect teardown in reverse order. Each builder must roll back partial changes if it throws before returning a handle. Continue other cleanup if one disposer throws; always reach the final readable fallback.
|
|
45
|
+
4. Revert split wrappers, masks, cloned accessibility text, and plugin DOM changes. Preserve framework-owned nodes and nested links/controls; never overwrite their subtree with a stale HTML snapshot. SplitText revert can reconstruct descendants: split a dedicated text leaf or visual copy when controls, state, or framework bindings must survive. Restore only owned inline properties to their original values, then apply the owner's readable settled state. A marker removal or `autoAlpha: 1` alone cannot undo clipping, transforms, child opacity, or a hidden parent. Avoid `clearProps: "all"` on application-owned styles.
|
|
46
|
+
5. Release only this owner's hiding, cover, busy/inert state, and navigation lock. Apply essential settled completion once, including appropriate focus and transition `done`. Do not replay decorative effects or call an outgoing navigation callback as entrance completion.
|
|
47
|
+
|
|
48
|
+
The bootstrap must retain a terminal recovery record even before the bundle arrives. With no application changes yet, it can release its CSS gate alone. Once setup starts, it must invoke the registered rollback as well. Releasing a shared document gate must not expose other still-preparing owners; use per-owner gates or transfer every owner's initial values before releasing it.
|
|
49
|
+
|
|
50
|
+
Every async continuation and controller entry point checks its captured token **before any DOM write or effect creation**, including `set`, `fromTo`, `onSplit`, resize/font callbacks, and `contextSafe` callbacks. Context ownership does not cancel promises. Catch failures inside those callbacks too. Late controller registration reads the terminal boot record and settles without hiding or splitting. Do not infer recovery only from an absent marker that navigation can later recreate.
|
|
51
|
+
|
|
52
|
+
On navigation, deactivate the outgoing owner's entrance recovery before the outro. Cancel stale work without revealing that owner. Recovery must exclude outgoing/end-state pages, cached hidden routes, closed dialogs, inactive tabs/panels, and decorative clones. Restore the outgoing page only if navigation itself is cancelled and that page becomes current again. Persistent shell elements keep separate visits. Dispose obsolete recovery timers on removal; never let them unlock or focus a newer route.
|
|
53
|
+
|
|
54
|
+
## Rendering and indexing
|
|
55
|
+
|
|
56
|
+
Keep primary text, headings, and meaningful links in server-rendered or prerendered HTML where supported. Preserve real `a[href]` links and independently accessible route URLs. Client-only rendering cannot reveal HTML that was never sent; provide a useful static shell/fallback and report that limit. Do not turn an entire page client-only to facilitate animation.
|
|
57
|
+
|
|
58
|
+
Google renders JavaScript and uses rendered HTML for indexing. An automatic intro does not inherently prevent indexing; that is an inference from Google's rendering model, not a guarantee for a particular page. Check rendered output when indexing is in question. Static hiding rules alone do not establish production indexing failures. See [JavaScript SEO basics](https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics).
|
|
59
|
+
|
|
60
|
+
Do not require a click, scroll, or hover to load primary indexable content. Keep primary hero media eagerly discoverable; reserve lazy loading for appropriate offscreen content. See [Google's lazy-loading guidance](https://developers.google.com/search/docs/crawling-indexing/javascript/lazy-loading).
|
|
61
|
+
|
|
62
|
+
## First-load performance
|
|
63
|
+
|
|
64
|
+
Initially hidden primary content can delay Largest Contentful Paint. LCP concerns eligible visible content painted in the viewport, not the end of a GSAP timeline. A heading or hero may become a candidate before the remaining stagger, footer, or ambient animation completes. Browser eligibility and candidate changes matter; do not calculate LCP from total timeline duration. See [Largest Contentful Paint](https://web.dev/articles/lcp).
|
|
65
|
+
|
|
66
|
+
Reveal primary headings and hero imagery without waiting for unrelated plugins, particle setup, below-fold media, or every font weight. Keep ambitious motion where requested; reduce unnecessary preparation and deliberate blank holds before weakening the effect. Never serve crawler-specific content or use near-zero opacity tricks to manipulate metrics.
|
|
67
|
+
|
|
68
|
+
Measure cold first loads separately from client-side transitions. Record the LCP element and timestamp, resource timing, layout shift, and a filmstrip under representative network/CPU conditions. Compare normal and reduced motion; use field data when available. Smooth route transitions do not prove fast document loads. Better performance does not promise ranking or indexing outcomes. See [Google's page-experience guidance](https://developers.google.com/search/docs/appearance/page-experience).
|
|
69
|
+
|
|
70
|
+
## Failure verification
|
|
71
|
+
|
|
72
|
+
Use the framework's production build and actual rendering mode. For every supported failure, assert meaningful text, usable links, restored owned styles/DOM, and absence of stale cover, lock, focus, or completion effects. Check page and shell owners separately.
|
|
73
|
+
|
|
74
|
+
| Case | Required observation |
|
|
75
|
+
|---|---|
|
|
76
|
+
| JavaScript disabled | Server/static content and native links work. Client-only routes get their documented static fallback, not invented SSR content. |
|
|
77
|
+
| Bundle blocked after marker | Prove the early marker executed; let its deadline expire. Content becomes readable without application cleanup. |
|
|
78
|
+
| Setup throws before initial writes | Readable settled state; no unresolved completion or navigation wait. |
|
|
79
|
+
| Setup throws after styles or split DOM | Timelines stop, original text/links return, temporary styles and masks disappear. |
|
|
80
|
+
| Fonts/media stall or reject | Bounded fallback. Resolve them afterward and confirm no new hiding or splitting. |
|
|
81
|
+
| Initialization arrives after recovery | Observe multiple frames after release and beyond the old timeline/deadline. No hidden frame or duplicate completion. |
|
|
82
|
+
| Successful delayed startup within budget | Hidden first frame, then full intended intro. No flash of settled content; intentional duration may exceed the boot budget. |
|
|
83
|
+
| Reduced motion | Readable first paint, functional links, normal completion semantics without travel. |
|
|
84
|
+
| Navigation during preparation or intro | One correct destination; stale recovery cannot reveal outgoing/hidden content or unlock/focus the new visit. |
|
|
85
|
+
| Repeated setup, history, and preserved nodes | No duplicate wrappers, listeners, callbacks, or replay after recovery within the same visit. |
|
|
86
|
+
|
|
87
|
+
Block only application resources in the bundle test, not the early script or stylesheet. Distinguish an intentionally delayed intro from stalled preparation. Record what ran, rendering limitations, and remaining browser/production gaps; these checks do not prove Google indexed the page or establish field LCP.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Lifecycle implementation
|
|
2
|
+
|
|
3
|
+
Read this to implement the five phases for pages and components without layout shift.
|
|
4
|
+
|
|
5
|
+
## The contract
|
|
6
|
+
|
|
7
|
+
**mount → initial state → intro → settled → outro → end state → unmount**
|
|
8
|
+
|
|
9
|
+
One controller owns a node from mount to unmount and exposes one current phase:
|
|
10
|
+
|
|
11
|
+
1. **Initial state.** Mounted, final size reserved, measured, start values applied, not yet shown.
|
|
12
|
+
2. **Intro.** One timeline from initial values to settled.
|
|
13
|
+
3. **Settled.** Visible, stable, interactive, and controlled by normal CSS.
|
|
14
|
+
4. **Outro.** Still mounted while one timeline moves it toward removal.
|
|
15
|
+
5. **End state.** Still mounted, final values applied, completion run once. Safe to unmount.
|
|
16
|
+
|
|
17
|
+
The user's request defines how each phase looks. If it only describes an intro or outro, implement the other phases as the minimum needed to enter and leave cleanly.
|
|
18
|
+
|
|
19
|
+
Store the current phase in state, a ref, or a data attribute. Do not infer it from opacity, DOM presence, or timeline progress.
|
|
20
|
+
|
|
21
|
+
## Setup and React lifecycle
|
|
22
|
+
|
|
23
|
+
Create one client-only module that imports GSAP, `useGSAP`, and only the plugins the project uses, and registers them once. Other modules import from it.
|
|
24
|
+
|
|
25
|
+
Use `useGSAP` in components:
|
|
26
|
+
|
|
27
|
+
- Pass a root ref as `scope`.
|
|
28
|
+
- Use refs for single targets and scoped selectors for repeated ones.
|
|
29
|
+
- Add dependencies only when the animation must rebuild. A reused route component needs its params, or its loader data, as dependencies with `revertOnUpdate` so a param change reruns the lifecycle.
|
|
30
|
+
- Wrap callbacks and event handlers that create GSAP work in `contextSafe`.
|
|
31
|
+
- Return a teardown for listeners and other non-GSAP resources.
|
|
32
|
+
|
|
33
|
+
Never run GSAP or plugin code during server rendering. Under TanStack Start every route file can render on the server; keep GSAP inside effects.
|
|
34
|
+
|
|
35
|
+
Do not call another component's `contextSafe` synchronously inside `useGSAP`: its context becomes a child and dies on the outer revert. Hand shared-controller work off through a microtask, effect, or event.
|
|
36
|
+
|
|
37
|
+
Write setup so it is correct when it runs more than once on the same node. React development checks do this, and a route component reused across a param change hands you a node that already holds settled values. Async work started by the first run can still be in flight when the second run starts, so anything a setup triggers outside its own context, such as a shared cover, must be safe to request twice. So: explicit initial writes (`set` or `fromTo`) rather than `from` tweens that trust a fresh node, and cleanup that leaves the node readable. Use a ref guard only for work that should happen once per visit rather than once per setup.
|
|
38
|
+
|
|
39
|
+
## Initial state
|
|
40
|
+
|
|
41
|
+
Build the final layout with normal CSS first. The initial state changes appearance, not layout. The element that owns geometry must exist before the animated node mounts.
|
|
42
|
+
|
|
43
|
+
- Mount content before measuring or animating it.
|
|
44
|
+
- Give images and media dimensions or an aspect ratio.
|
|
45
|
+
- Reserve async and streamed regions with a wrapper when their size is known.
|
|
46
|
+
- Prefer transforms, `autoAlpha`, masks, or clipping, which keep the layout box.
|
|
47
|
+
|
|
48
|
+
If the effect changes width, height, or position:
|
|
49
|
+
|
|
50
|
+
- Animate a transform on an inner element while an outer wrapper holds the settled size.
|
|
51
|
+
- For a real expand or collapse, measure start and end sizes first, animate the wrapper, and decide how surrounding content moves.
|
|
52
|
+
- For layout-to-layout changes, use Flip: capture the old state, apply the new layout, animate.
|
|
53
|
+
- When old and new content share one region, reserve the parent and overlap the children so only the parent affects layout.
|
|
54
|
+
|
|
55
|
+
Content must stay readable without JavaScript. The pre-paint rule in [SSR and hydration](route-lifetime.md#ssr-and-hydration-with-tanstack-start) is the only sanctioned way to hide server-rendered content before the intro; client-only apps need none.
|
|
56
|
+
|
|
57
|
+
## Initialization and recovery
|
|
58
|
+
|
|
59
|
+
Apply the [initialization contract](initialization.md) whenever content starts hidden. It includes recovery ordering, indexing/performance limits, and failure checks.
|
|
60
|
+
|
|
61
|
+
- With TanStack Start, use the installed `ScriptOnce` document integration described in [SSR and hydration](route-lifetime.md#ssr-and-hydration-with-tanstack-start). Include the independent deadline in that early script. Do not mutate split DOM before hydration.
|
|
62
|
+
- Router-only client rendering and Start routes using `ssr: false` or `ssr: 'data-only'` cannot expose missing route HTML without JavaScript. Verify their rendered shell/`pendingComponent`, preserve native links there, and start component recovery when real targets mount.
|
|
63
|
+
- Keep visit records in the persistent root controller. Register rollback before `useGSAP` initial writes; report ready only after required preparation and timeline handlers exist. Neither page registration nor `onRendered` alone proves readiness. Guard late loader, subscription, font, and media callbacks.
|
|
64
|
+
- Invalidate before the blocker runs an outro and before cleanup/remount. Reused matches, `remountDeps`, and React effect replay must respect the current visit's terminal recovery. Resolve only its blocker/cover wait; persisted layouts and shell have separate owners.
|
|
65
|
+
|
|
66
|
+
## Intro and settled
|
|
67
|
+
|
|
68
|
+
Write reusable intro and outro builders only when behavior repeats. Each returns a timeline so the controller can compose, kill, reverse, or await it.
|
|
69
|
+
|
|
70
|
+
- Make settled the source of truth. It must not depend on a paused timeline.
|
|
71
|
+
- Clear temporary transform, visibility, transition, and `will-change` styles once settled.
|
|
72
|
+
- Run intro completion and settled callbacks once, including under reduced motion.
|
|
73
|
+
- On rapid state changes, replace, kill, or reverse the active timeline. Do not stack conflicting tweens.
|
|
74
|
+
- Update assistive text and state immediately. Animate the visual, not the meaning.
|
|
75
|
+
|
|
76
|
+
## Outro and end state
|
|
77
|
+
|
|
78
|
+
Start the outro from current rendered values. Keep the node mounted, laid out, and owned until the timeline completes.
|
|
79
|
+
|
|
80
|
+
- Reject duplicate outro requests or define which wins.
|
|
81
|
+
- If an intro is running, reverse it only when the outro is its exact inverse. Otherwise kill it and build the outro from current values.
|
|
82
|
+
- Disable pointer events when the visual can no longer support them, without removing the layout box.
|
|
83
|
+
- Run end-state work once. Only then resolve the blocker, unmount, replace, hide, or hand off.
|
|
84
|
+
- Kill the active timeline on cleanup, but do not erase state the route cover still needs.
|
|
85
|
+
- No `display: none`, conditional removal, or DOM replacement before the outro completes.
|
|
86
|
+
|
|
87
|
+
## Conditional show and hide
|
|
88
|
+
|
|
89
|
+
React unmounts conditional content before an outro can play. Add a presence controller where that matters. It should:
|
|
90
|
+
|
|
91
|
+
- Mount into initial state before the intro.
|
|
92
|
+
- Stay mounted through settled and outro.
|
|
93
|
+
- Keep the active timeline.
|
|
94
|
+
- On re-show during an outro, reverse only if that gives the intended intro. Otherwise kill, set from current values, and build a fresh intro.
|
|
95
|
+
- Remove the node only after the end-state callback.
|
|
96
|
+
- Keep all five phases under reduced motion.
|
|
97
|
+
|
|
98
|
+
When content in a shared region changes size, decide who owns the region's geometry before mounting either child. Overlap old and new inside a reserved wrapper, or animate a measured wrapper between known sizes. Do not let unmount then mount push surrounding content twice.
|
|
99
|
+
|
|
100
|
+
Do not use presence for content that can simply appear, or for routes the root controller already manages.
|
|
101
|
+
|
|
102
|
+
- Focus a panel when its intro completes, not when it mounts. An element at `visibility: hidden` refuses focus silently, and `autoAlpha: 0` is exactly that. Reduced motion jumps to completion synchronously, so the focus still lands.
|
|
103
|
+
- When the outro ends and React is asked to unmount the children, clear only `will-change` from the wrapper. The unmount is queued, not immediate; clearing the collapsed height or visibility in the same tick flashes the content at full size for a frame.
|
|
104
|
+
|
|
105
|
+
A modal that is a child route is a presence controller whose unmount is a navigation. See [Conditional content](route-lifetime.md#conditional-content).
|
|
106
|
+
|
|
107
|
+
## Reduced and responsive motion
|
|
108
|
+
|
|
109
|
+
The OS preference is the default. Add an app override only if the product needs one.
|
|
110
|
+
|
|
111
|
+
Every effect needs initial, settled, and end states under reduced motion. Do not just shorten a disorienting effect. Skip travel, rotation, scale, parallax, and scrambling unless essential. A zero-duration timeline or an immediate `set` still fires completion for anything that depends on it, including the callback that lets a blocked navigation proceed.
|
|
112
|
+
|
|
113
|
+
Use `gsap.matchMedia()` for responsive and reduced-motion variants that must rebuild when conditions change. Revert it through the owning component. Do not nest a second GSAP context for the same setup.
|
|
114
|
+
|
|
115
|
+
An app-level override is not a media query, so `matchMedia` cannot see it. Read it in a shared `prefersReducedMotion()` helper that every timeline consults, mirror it as a root attribute so CSS can key on it, and for setups that live inside a `matchMedia` block either gate the block on the store through a hook dependency or accept that the block follows the OS alone and say so. Feed the router's `viewTransition` `types` function from the same decision.
|
|
116
|
+
|
|
117
|
+
## Scroll
|
|
118
|
+
|
|
119
|
+
Use `gsap-scrolltrigger` for the API; these rules cover route lifetime and measurement.
|
|
120
|
+
|
|
121
|
+
- Create triggers in document order. Refresh after fonts, images, streamed data, or dynamic content change layout.
|
|
122
|
+
- Create triggers inside the owning context. Do not kill all triggers globally when one page leaves. A layout route's triggers survive child navigations; a page's leave with it.
|
|
123
|
+
- A route reused with new params keeps its triggers against changed content. Refresh them after the new data renders.
|
|
124
|
+
- The router restores scroll in `onRendered`, after the page's layout effects. Triggers created in `useGSAP` measured before that; refresh from `onRendered`, and once more when the page settles if anything above a trigger changed height during the intro.
|
|
125
|
+
- A `useGSAP` context revert calls `revert()` on each trigger with no arguments, which ScrollTrigger treats as `kill(true)`: the pin spacer is removed and the pinned element's original inline styles are restored. Leaving a route mid-pin needs no extra cleanup. `gsap.matchMedia()` created inside the same setup registers with that context and is reverted with it; it is not a second context for the same setup.
|
|
126
|
+
- A `will-change` written from an `onToggle` callback is outside the context and survives its revert. Write it as a plain style and undo it in the matchMedia cleanup, or write it before the trigger is created.
|
|
127
|
+
|
|
128
|
+
Under reduced motion, go straight from initial to settled without unnecessary triggers. Keep outro and end callbacks that control navigation or unmount.
|
|
129
|
+
|
|
130
|
+
## Text
|
|
131
|
+
|
|
132
|
+
Use SplitText when the effect needs per-character, word, or line targets.
|
|
133
|
+
|
|
134
|
+
- For character splits, keep scoped `font-kerning: none; text-rendering: optimizeSpeed` before, during, and after revert, including reduced motion. Wrappers disrupt kerning and can cause horizontal snapping; use words/lines if natural kerning is essential. See [SplitText limitations](https://gsap.com/docs/v3/Plugins/SplitText/#tips--limitations).
|
|
135
|
+
- Apparent weight changes can be clipped ink: check computed fonts/readiness, then mask edges, punctuation, and descenders. For confirmed clipping, add scoped mask padding with compensating negative margins; verify spacing and both hidden endpoints before trying compositing workarounds.
|
|
136
|
+
- Keep reading accessible with the plugin's ARIA support. If text contains links or controls, keep an unsplit accessible version instead of hiding them.
|
|
137
|
+
- Use word-aware wrapping for character animation. Use auto re-split for line animation that must survive width or font changes.
|
|
138
|
+
- When line measurement needs fonts, bound the wait or auto-split preparation by the [initialization deadline](initialization.md#bound-initialization-not-choreography). Reserve settled height before splitting if wrappers could shift layout.
|
|
139
|
+
- Keep a handle to the split's animation so re-split and cleanup can dispose of it. With `autoSplit`, build the animation inside `onSplit` and return it: the plugin records its playhead before a re-split and restores it on the new lines, and `revert()` undoes the tween's values. With line splitting and `autoSplit`, the plugin waits for fonts itself; no separate font wait is needed.
|
|
140
|
+
- A split heading inside a page takes its timing from the page phase, not its own clock. Hold at initial while the page is initial, rise when the page enters, drop when it leaves. Give it its own pre-paint rule rather than marking it as a page target, or the page's stagger and the split's rise fight over one element.
|
|
141
|
+
- Loader data changing in a reused route re-renders the heading's text node in place, which breaks a split that replaced it with spans. Revert before the data-dependent render and re-split after it, or key the split on the data.
|
|
142
|
+
- Revert splits on interruption and unmount. Do not leave wrapper spans in stale content.
|
|
143
|
+
|
|
144
|
+
Revert when the owning phase no longer needs the split. Compare glyph appearance, character positions, wrapping, and height immediately before/after cleanup at desktop/mobile widths, with reduced motion and interruption. Stable boxes alone do not prove stable ink; distinguish subpixel rounding from visible movement.
|
|
145
|
+
|
|
146
|
+
## Interaction
|
|
147
|
+
|
|
148
|
+
Pointer motion needs keyboard parity. Pair hover with focus on interactive elements. Do not animate a non-interactive element like a control.
|
|
149
|
+
|
|
150
|
+
Keep gestures bounded, provide a non-gesture path, and dispose of interaction plugins with their owner. See `gsap-plugins` for Draggable, Observer, and Flip APIs.
|
|
151
|
+
|
|
152
|
+
## Layout stability and performance
|
|
153
|
+
|
|
154
|
+
- Prefer `x`, `y`, scale, rotation, and `autoAlpha` over layout properties.
|
|
155
|
+
- Use `clip-path`, filters, and variable-font axes deliberately; they can cost paint or shift layout.
|
|
156
|
+
- Batch reads before writes.
|
|
157
|
+
- The stable wrapper's box should not jump between mount, initial, settled, outro, end, and unmount. Intentional transforms move pixels; layout boxes do not.
|
|
158
|
+
- Set `will-change` just before animating and clear it after. Do not promote everything.
|
|
159
|
+
- Do not animate hundreds of nodes at once. Reduce targets, batch, or virtualize.
|
|
160
|
+
- Do not add a CSS transition on a property GSAP controls.
|