Lazy Media System
This page explains how lazy media works in 3AM as an implementation system, not just a component API.
Core files:
src/lib/lazyMedia.tssrc/lib/lazyMediaHydration.tssrc/components/lazyImage.tssrc/components/lazyPicture.tssrc/components/lazyVideo.ts
System model
The app creates one lazy-media controller during startup.
That controller scans for deferred media attributes and hydrates them when targets intersect viewport thresholds.
It scans once at startup and again after each route change.
Attributes the system hydrates
data-lazy-srcdata-lazy-srcsetdata-lazy-sizesdata-lazy-posterdata-lazy-bg-src
Pattern Comparison
Problematic Example (eager media)
<img src="/assets/dusk/dusk_transparent.webp" alt="Dusk" />Recommended Example (deferred media)
<img
src="/assets/shared/placeholder.png"
data-lazy-src="/assets/dusk/dusk_transparent.webp"
alt="Dusk"
/>Preferred usage
Use LazyImage, LazyPicture, and LazyVideo so attribute wiring is generated correctly.
Why this system exists
Better first paint behavior for heavy pages.
Lower chance of loading off-screen media too early.
Consistent hydration logic across images, picture sources, videos, and deferred backgrounds.
Common mistakes
Using plain heavy <img> where LazyImage should be used.
Using custom deferred attributes that the controller does not scan.
Forgetting route-change rescans when custom DOM insertion bypasses normal route flow.
Related docs: Performance, Ready Components, Building Components.
Keep one strategy
Do not mix multiple custom lazy-loading strategies in the same feature unless there is a strong reason. Prefer the project controller for consistency.