Three.js From Zero · Article s8-10

S8-10 Shipping Checklist

Season 8 · Article 10 · Finale

The Shipping Checklist

From 90% done to actually shipped. 8 categories, 40-ish items. The production punch list every 3D app should pass before hitting "Deploy."

🏁 Season 8 finale — Production Architecture concludes

Assets (S6)

  • All models passed gltf-transform validate
  • Geometries compressed (Draco or Meshopt)
  • Textures compressed (KTX2 with UASTC for normals, ETC1S for rest)
  • Textures no larger than needed (2K mobile max, 4K desktop max)
  • LOD levels authored for any mesh appearing at varying distances
  • Texture atlases built where ≥10 similar assets
  • Assets served with immutable, max-age=31536000 cache headers
  • CDN with Brotli compression on .json/.gltf

Rendering quality

  • Color management set: outputColorSpace = SRGBColorSpace, textures flagged correctly
  • Tone mapping picked (ACESFilmicToneMapping) and exposure tuned
  • PMREM environment set for PBR materials to have specular IBL
  • Shadow map size appropriate (1024 or 2048, not 4096 default)
  • Pixel ratio clamped: renderer.setPixelRatio(Math.min(devicePixelRatio, 2))
  • Post-processing gated by device tier (skip bloom/DOF/SSAO on low)

Performance

  • Named imports from 'three' — no * as THREE
  • GLTFLoader / DRACOLoader / KTX2Loader lazy-imported
  • Bundle analyzer run, nothing > 200KB surprise
  • Total JS bundle < 300KB (first paint)
  • FPS p10 ≥ 30 on low-tier device (tested)
  • Frustum culling enabled on Meshes (default, verify)
  • Instancing (InstancedMesh/BatchedMesh) for repeated geometry
  • Animation mixer paused when tab inactive

UI & UX (S7)

  • Loading state shown — never blank canvas on load
  • Error states messaged — never silent failure
  • Touch gestures work on mobile (touch-action: none)
  • Keyboard alternative for every gesture (arrow keys, Tab)
  • aria-label on canvas container
  • Screen reader announcements via aria-live
  • prefers-reduced-motion respected
  • Text uses MSDF or sharp HTML overlay (not blurry canvas)

Reliability

  • webglcontextlost handler with preventDefault()
  • webglcontextrestored handler that reinit's
  • GLTFLoader error callback handles failures with fallback
  • Network requests have timeouts (10s or less)
  • Capability tiers detected, rendering adjusted
  • No-WebGL fallback (static image + message)

Observability

  • web-vitals LCP/CLS/INP reporting
  • Custom "3D ready" metric
  • FPS p10/p50/p90 reporting (not just avg)
  • Long Task Observer hooked
  • Error tracking (window.error + unhandledrejection)
  • Device tier segmentation on all metrics
  • Alerting on p10 FPS regression

Security & privacy

  • CSP headers set (allow unpkg/CDN you actually use, nothing more)
  • Self-hosted Draco + Basis decoders (not gstatic in prod)
  • No PII in telemetry events
  • GDPR: telemetry requires consent (or anonymous)
  • User-generated 3D content validated (size, format, malicious glTF)

Launch day

  • Feature flag ready (Launch Darkly, GrowthBook, manual) to disable 3D if something breaks
  • Rollback plan: previous deploy tagged and ready
  • On-call engineer identified
  • Dashboards bookmarked and tested
  • 10% gradual rollout, not 100% big bang
  • Cross-device smoke test: Quest, iPhone, Chromebook, modern Mac
  • Lighthouse score >= 90

Season 8 recap

State → ECS → loops → authoring → debug → testing → errors → build → telemetry → checklist.

The engineering scaffolding that turns a demo into a product. Every item here either catches or prevents a production outage.

Season 9 next

Real-time Systems & Audio. WebRTC for voice/video streams. Web Audio API deep dive. Spatial audio. Convolution reverb. Audio-reactive visuals. Multiplayer sync. The sound half of "3D experience."