[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M7EM63MEBA9HSYF6SHT80PVR":3,"skill-same:01M7EM63MEBA9HSYF6SHT80PVR":45},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":18,"linkOnly":19,"markdownContent":20,"markdownBody":21,"frontMatter":22,"refName":23,"commitSha":24,"skillDirectory":25,"forksCount":26,"repositoryHtmlUrl":27,"repositoryHomepageUrl":6,"ownerHtmlUrl":28,"ownerBlogUrl":29,"ownerDescription":6,"updatedAt":30,"install":31,"resources":44},"01M7EM63MEBA9HSYF6SHT80PVR","ams-3d-web-experiences",null,"TanNhatCMS\u002Fjarvis","TanNhatCMS","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F113796420?v=4","01M753MV17KG5CD3152G3WQEQY","KietNT","01M7EKEDYVYQ6PWVJJMZ911VMX",0,"MIT","https:\u002F\u002Fgithub.com\u002FTanNhatCMS\u002Fjarvis\u002Fblob\u002Fmain\u002Fskills\u002Fams-3d-web-experiences\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: 3d-web-experiences\ndescription: Create 3D web experiences: scene setup, models, materials, lighting, animation, scroll-driven scenes, and performance budgets. Use when adding 3D to websites beyond basic demos.\ncategory: development\n---\n\n# 3D Web Experiences\n\nA practical guide to shipping 3D on the web — product viewers, hero scenes, scroll-driven storytelling, configurators — with an emphasis on the asset pipeline and performance budgets that separate smooth experiences from janky tech demos.\n\n## Overview\n\nWeb 3D = WebGL (or WebGPU) + a scene graph library (three.js dominates) + 3D assets + disciplined performance work. The hard parts are rarely the rendering code: they're **asset weight** (a 50MB model kills mobile), **draw calls** (hundreds of meshes = slow), and **frame budget** (16.6ms at 60fps, less on low-end devices).\n\nRule of thumb: design the experience for the weakest device you support, then enhance — not the reverse.\n\n## When to use\n\n- 3D product viewers and configurators (color\u002Fmaterial\u002Fparts switching).\n- Animated hero scenes and scroll-driven 3D storytelling.\n- Interactive data visualizations in 3D.\n- Choosing model formats and compression.\n- Diagnosing 3D performance problems.\n\n## Core concepts\n\n- **Scene graph.** Scene → meshes (geometry + material) → lights → camera. Everything is a positioned node; groups organize parts.\n- **Geometry.** BufferGeometry of triangles. Polygon count is a budget: hero models 50–200k tris desktop, far less for mobile; background props much less.\n- **Materials.** PBR (physically based rendering): `MeshStandardMaterial` with color\u002Froughness\u002Fmetalness maps. Fewer unique materials = fewer shader programs = faster.\n- **Lighting.** Key + fill + rim, or environment maps (IBL) for realistic reflections. Real-time shadows are expensive — one shadow-casting light max on mobile, or bake shadows into textures.\n- **glTF.** The standard interchange format. Prefer `.glb` (binary) with Draco mesh compression and KTX2\u002FBasis texture compression.\n- **Animation.** `requestAnimationFrame` loop with delta-time (never fixed steps); `THREE.AnimationMixer` for skeletal\u002FglTF animations; lerp for smooth interpolation.\n- **Scroll-driven scenes.** Map scroll progress → camera path \u002F object transforms. Use a smoothed (lerped) scroll value, never raw scroll events, to avoid judder.\n- **Draw calls.** Each mesh+material = at least one draw call. Merge static geometry, use instancing (`InstancedMesh`) for repeated objects (grass, bolts, stars).\n\n## Practical workflow\n\n**1. Prepare assets first.**\n```bash\n# Typical pipeline: Blender -> glTF -> compress\n# - Apply transforms, merge materials, bake AO\u002Fshadows where possible\n# - Export .glb, then compress:\ngltfpack -i model.glb -o model-packed.glb -cc   # meshopt compression\n```\nTarget: hero model under 3–5MB, textures ≤2048px (1024 for mobile), KTX2 compressed.\n\n**2. Scaffold the scene.**\n```js\nimport * as THREE from 'three';\nimport { GLTFLoader } from 'three\u002Faddons\u002Floaders\u002FGLTFLoader.js';\nimport { OrbitControls } from 'three\u002Faddons\u002Fcontrols\u002FOrbitControls.js';\n\nconst renderer = new THREE.WebGLRenderer({ antialias: true, powerPreference: 'high-performance' });\nrenderer.setPixelRatio(Math.min(devicePixelRatio, 2));\nconst scene = new THREE.Scene();\nscene.environment = await loadEnvironment(); \u002F\u002F RoomEnvironment or HDRI for PBR reflections\n```\n\n**3. Load with feedback.** Show a real loading UI with progress (`onProgress` bytes) — 3D assets are heavy; a blank canvas reads as broken.\n\n**4. Animate correctly.**\n```js\nconst clock = new THREE.Clock();\nfunction tick() {\n  const dt = Math.min(clock.getDelta(), 0.05); \u002F\u002F clamp tab-switch spikes\n  controls.update();\n  mixer?.update(dt);\n  renderer.render(scene, camera);\n  requestAnimationFrame(tick);\n}\n```\n\n**5. Budget and measure.** Use the browser's frame profiler + `renderer.info` (draw calls, triangles, geometries). Set budgets: e.g., \u003C150 draw calls, \u003C500k tris, \u003C10MB assets for a marketing hero.\n\n**6. Degrade gracefully.** `WebGL2` check → fallback to a static image or video. Respect `prefers-reduced-motion` (pause auto-rotation\u002Fcamera moves).\n\n## Common pitfalls\n\n- **Uncompressed assets.** Shipping raw 40MB FBX\u002FOBJ exports. glTF + meshopt\u002FDraco + KTX2 routinely cuts 80–95%.\n- **Draw call explosion.** A model with 300 separate meshes renders 300+ draw calls. Merge, instance, or atlas.\n- **Pixel ratio blindness.** `setPixelRatio(devicePixelRatio)` on a 3x phone = 9x pixels. Cap at 2 (or 1.5 for heavy scenes).\n- **Shadow abuse.** Multiple shadow-casting lights or huge shadow maps tank mobile GPUs. One directional light with tight shadow camera, or baked shadows.\n- **Memory leaks.** Geometries, materials, and textures not disposed on scene teardown (`geometry.dispose()`, `material.dispose()`, `texture.dispose()`). SPAs navigating between 3D views leak fast.\n- **Z-fighting.** Coplanar surfaces flicker — offset with polygonOffset or tiny positional gaps.\n- **Blocking the main thread.** Parsing a big glTF synchronously freezes the page. Load async, show progress, consider Web Workers for heavy prep.\n- **No loading state.** Users stare at black. Always: skeleton → progress → reveal.\n- **Ignoring color management.** Set `renderer.outputColorSpace = SRGBColorSpace` and use sRGB textures correctly, or colors look washed out\u002Fwrong.\n","# 3D Web Experiences\n\nA practical guide to shipping 3D on the web — product viewers, hero scenes, scroll-driven storytelling, configurators — with an emphasis on the asset pipeline and performance budgets that separate smooth experiences from janky tech demos.\n\n## Overview\n\nWeb 3D = WebGL (or WebGPU) + a scene graph library (three.js dominates) + 3D assets + disciplined performance work. The hard parts are rarely the rendering code: they're **asset weight** (a 50MB model kills mobile), **draw calls** (hundreds of meshes = slow), and **frame budget** (16.6ms at 60fps, less on low-end devices).\n\nRule of thumb: design the experience for the weakest device you support, then enhance — not the reverse.\n\n## When to use\n\n- 3D product viewers and configurators (color\u002Fmaterial\u002Fparts switching).\n- Animated hero scenes and scroll-driven 3D storytelling.\n- Interactive data visualizations in 3D.\n- Choosing model formats and compression.\n- Diagnosing 3D performance problems.\n\n## Core concepts\n\n- **Scene graph.** Scene → meshes (geometry + material) → lights → camera. Everything is a positioned node; groups organize parts.\n- **Geometry.** BufferGeometry of triangles. Polygon count is a budget: hero models 50–200k tris desktop, far less for mobile; background props much less.\n- **Materials.** PBR (physically based rendering): `MeshStandardMaterial` with color\u002Froughness\u002Fmetalness maps. Fewer unique materials = fewer shader programs = faster.\n- **Lighting.** Key + fill + rim, or environment maps (IBL) for realistic reflections. Real-time shadows are expensive — one shadow-casting light max on mobile, or bake shadows into textures.\n- **glTF.** The standard interchange format. Prefer `.glb` (binary) with Draco mesh compression and KTX2\u002FBasis texture compression.\n- **Animation.** `requestAnimationFrame` loop with delta-time (never fixed steps); `THREE.AnimationMixer` for skeletal\u002FglTF animations; lerp for smooth interpolation.\n- **Scroll-driven scenes.** Map scroll progress → camera path \u002F object transforms. Use a smoothed (lerped) scroll value, never raw scroll events, to avoid judder.\n- **Draw calls.** Each mesh+material = at least one draw call. Merge static geometry, use instancing (`InstancedMesh`) for repeated objects (grass, bolts, stars).\n\n## Practical workflow\n\n**1. Prepare assets first.**\n```bash\n# Typical pipeline: Blender -> glTF -> compress\n# - Apply transforms, merge materials, bake AO\u002Fshadows where possible\n# - Export .glb, then compress:\ngltfpack -i model.glb -o model-packed.glb -cc   # meshopt compression\n```\nTarget: hero model under 3–5MB, textures ≤2048px (1024 for mobile), KTX2 compressed.\n\n**2. Scaffold the scene.**\n```js\nimport * as THREE from 'three';\nimport { GLTFLoader } from 'three\u002Faddons\u002Floaders\u002FGLTFLoader.js';\nimport { OrbitControls } from 'three\u002Faddons\u002Fcontrols\u002FOrbitControls.js';\n\nconst renderer = new THREE.WebGLRenderer({ antialias: true, powerPreference: 'high-performance' });\nrenderer.setPixelRatio(Math.min(devicePixelRatio, 2));\nconst scene = new THREE.Scene();\nscene.environment = await loadEnvironment(); \u002F\u002F RoomEnvironment or HDRI for PBR reflections\n```\n\n**3. Load with feedback.** Show a real loading UI with progress (`onProgress` bytes) — 3D assets are heavy; a blank canvas reads as broken.\n\n**4. Animate correctly.**\n```js\nconst clock = new THREE.Clock();\nfunction tick() {\n  const dt = Math.min(clock.getDelta(), 0.05); \u002F\u002F clamp tab-switch spikes\n  controls.update();\n  mixer?.update(dt);\n  renderer.render(scene, camera);\n  requestAnimationFrame(tick);\n}\n```\n\n**5. Budget and measure.** Use the browser's frame profiler + `renderer.info` (draw calls, triangles, geometries). Set budgets: e.g., \u003C150 draw calls, \u003C500k tris, \u003C10MB assets for a marketing hero.\n\n**6. Degrade gracefully.** `WebGL2` check → fallback to a static image or video. Respect `prefers-reduced-motion` (pause auto-rotation\u002Fcamera moves).\n\n## Common pitfalls\n\n- **Uncompressed assets.** Shipping raw 40MB FBX\u002FOBJ exports. glTF + meshopt\u002FDraco + KTX2 routinely cuts 80–95%.\n- **Draw call explosion.** A model with 300 separate meshes renders 300+ draw calls. Merge, instance, or atlas.\n- **Pixel ratio blindness.** `setPixelRatio(devicePixelRatio)` on a 3x phone = 9x pixels. Cap at 2 (or 1.5 for heavy scenes).\n- **Shadow abuse.** Multiple shadow-casting lights or huge shadow maps tank mobile GPUs. One directional light with tight shadow camera, or baked shadows.\n- **Memory leaks.** Geometries, materials, and textures not disposed on scene teardown (`geometry.dispose()`, `material.dispose()`, `texture.dispose()`). SPAs navigating between 3D views leak fast.\n- **Z-fighting.** Coplanar surfaces flicker — offset with polygonOffset or tiny positional gaps.\n- **Blocking the main thread.** Parsing a big glTF synchronously freezes the page. Load async, show progress, consider Web Workers for heavy prep.\n- **No loading state.** Users stare at black. Always: skeleton → progress → reveal.\n- **Ignoring color management.** Set `renderer.outputColorSpace = SRGBColorSpace` and use sRGB textures correctly, or colors look washed out\u002Fwrong.\n",{},"main","af388a77c2fe5e0b4fd879cca4300a0ffa9a6579","skills\u002Fams-3d-web-experiences",1,"https:\u002F\u002Fgithub.com\u002FTanNhatCMS\u002Fjarvis","https:\u002F\u002Fgithub.com\u002FTanNhatCMS","https:\u002F\u002Fmrkiet.name.vn","2026-11-07 14:23:08",{"source":7,"skillName":5,"commands":32,"prompt":42,"zipAvailable":43},[33,36,39],{"tool":34,"command":35},"npx","npx skills add TanNhatCMS\u002Fjarvis --skill ams-3d-web-experiences",{"tool":37,"command":38},"bunx","bunx skills add TanNhatCMS\u002Fjarvis --skill ams-3d-web-experiences",{"tool":40,"command":41},"pnpm","pnpm dlx skills add TanNhatCMS\u002Fjarvis --skill ams-3d-web-experiences","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FTanNhatCMS\u002Fjarvis\u002Fblob\u002Fmain\u002Fskills\u002Fams-3d-web-experiences\u002FSKILL.md",true,[],[46,53,61,68,75,82],{"skillNo":47,"name":48,"nameZh":6,"description":49,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":50,"categories":51,"keywords":52,"publishedAt":18},"01M7EWYJR0J8DARY7E59Z6Y9MV","web-scrape","Turn web pages into LLM-ready markdown via the Firecrawl API (renders JS, anti-bot handling). Use when browser_open\u002Ffetch fails on JS-heavy pages, or when you need clean markdown\u002Fstructured extraction from a site. Requires FIRECRAWL_API_KEY.","https:\u002F\u002Fgithub.com\u002FTanNhatCMS\u002Fjarvis\u002Fblob\u002Fmain\u002Fskills\u002Fweb-scrape\u002FSKILL.md",[],[],{"skillNo":54,"name":55,"nameZh":6,"description":56,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":57,"sourceHtmlUrl":58,"categories":59,"keywords":60,"publishedAt":18},"01M7EWYBN5P6F2AJG3FR24T9BP","design-taste-frontend","tasteskill v2, the anti-slop frontend skill. Art direction for websites, distilled from a study of 247 curated gallery sites (One Page Love, Awwwards Sites of the Day). Deals researched directions (idea, composition, type, palette, photographs, section blueprints) from a library, enforces a strict no-slop house style with a real-browser inspector, and runs a look-and-fix loop on screenshots. Use this whenever you build, design, redesign, restyle, polish or review a landing page, marketing site, portfolio, product page, one-pager, hero or any public-facing web page, in any stack (HTML\u002FCSS, React, Next.js, Vue, Svelte, Astro, Tailwind) — also when the user says a page looks generic, templated, \"AI-made\", sloppy, or asks to make it look designed, premium, award-level or less like every other site. Not for dashboards or app screens.","https:\u002F\u002Fgithub.com\u002FTanNhatCMS\u002Fjarvis\u002Fblob\u002Fmain\u002Fskills\u002Ftaste-design\u002FLICENSE","https:\u002F\u002Fgithub.com\u002FTanNhatCMS\u002Fjarvis\u002Fblob\u002Fmain\u002Fskills\u002Ftaste-design\u002FSKILL.md",[],[],{"skillNo":62,"name":63,"nameZh":6,"description":64,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":65,"categories":66,"keywords":67,"publishedAt":18},"01M7EWY8FQFNQ2GB7NZZWGSSDX","test-driven-development","Use when implementing any feature or bugfix, before writing implementation code","https:\u002F\u002Fgithub.com\u002FTanNhatCMS\u002Fjarvis\u002Fblob\u002Fmain\u002Fskills\u002Fsuperpowers-tdd\u002FSKILL.md",[],[],{"skillNo":69,"name":70,"nameZh":6,"description":71,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":72,"categories":73,"keywords":74,"publishedAt":18},"01M7EWY5SHBFRH1HDHVWM9K7TV","systematic-debugging","Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes","https:\u002F\u002Fgithub.com\u002FTanNhatCMS\u002Fjarvis\u002Fblob\u002Fmain\u002Fskills\u002Fsuperpowers-debugging\u002FSKILL.md",[],[],{"skillNo":76,"name":77,"nameZh":6,"description":78,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":79,"categories":80,"keywords":81,"publishedAt":18},"01M7EWY3NM0Z0JAKS7HDZ24K66","requesting-code-review","Use when completing tasks, implementing major features, or before merging to verify work meets requirements","https:\u002F\u002Fgithub.com\u002FTanNhatCMS\u002Fjarvis\u002Fblob\u002Fmain\u002Fskills\u002Fsuperpowers-code-review\u002FSKILL.md",[],[],{"skillNo":83,"name":84,"nameZh":6,"description":85,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":18},"01M7EWY0WRMWX4M9ZFY0WKC593","brainstorming","You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).","https:\u002F\u002Fgithub.com\u002FTanNhatCMS\u002Fjarvis\u002Fblob\u002Fmain\u002Fskills\u002Fsuperpowers-brainstorming\u002FSKILL.md",[],[]]