Aura3D quick patterns for AI coding agents. Read this file first, then read `docs/agents/claims-and-boundaries.md` before making public examples, docs, route claims, template claims, or release claims. You are NOT writing three.js: - Do not `import * as THREE` or import from `three` / `three/examples/...`. Write `@aura3d/engine` public APIs. - Do not `new GLTFLoader()`, `new GLTFLoader().load(...)`, or hand-wire a renderer/scene/camera loop. `createAuraApp(...)` owns the runtime. - Do not invent asset paths or paste memorized/guessed GLB URLs (for example `raw.githubusercontent.com/.../KhronosGroup/glTF-Sample-Assets/.../DamagedHelmet.glb`). Those are hallucinated provenance. Resolve real objects from the asset catalog instead (see below). - three.js -> Aura3D mapping: | three.js | Aura3D | | --- | --- | | `new THREE.Mesh(...)` + `new GLTFLoader()` | `model(assets.x)` (typed asset) | | `new THREE.Scene()` | `scene()` | | `new THREE.PerspectiveCamera(...)` | `camera.perspective(...)` | | `new THREE.DirectionalLight(...)` / `AmbientLight` / `PointLight` | `lights.*` (for example `lights.studio()`) | | `new OrbitControls(camera, renderer.domElement)` | `interactions.orbit(...)` | | `THREE.MeshStandardMaterial` | `material.*` | | `new THREE.BoxGeometry(...)` (set-dressing only) | `primitives.*` | Resolve real objects from the asset catalog FIRST: - If a prompt names a real-world object (a helmet, a sneaker, a camera, a car), do not model it from primitives and do not invent a URL. Resolve it through the Aura3D asset catalog: `npx @aura3d/cli@latest assets search ""`. - The catalog is large (~850k license-verified GLB/glTF assets aggregated from Objaverse, Sketchfab, Poly Pizza, Poly Haven, OS3A, Khronos and CC0 packs). It is searched by **meaning + quality**, not just keywords, so use a natural descriptive phrase ("battle-worn knight helmet", "cozy wooden cabin") - the best-matching, highest-quality, license-clean candidates come back ranked. - Auto-pullable candidates (CC0 / CC-BY, verified, direct-download) are pulled to disk and typed for you; run `assets resolve "" --name ` to pull the top match and get a typed `assets.`. Then use it with `model(assets.)`. - For playable fighter/character prompts, add the game-asset profile: `npx @aura3d/cli@latest assets search "animated humanoid fighting character" --profile fighting-character --json`, then `npx @aura3d/cli@latest assets resolve "animated humanoid fighting character" --name fighter --profile fighting-character`. The profile filters toward animated redistributable GLB candidates and keeps catalog provenance in `aura.assets.json`. - Primitives are only for set-dressing around a resolved real asset, or in the rare case no clean catalog asset matches. They are never a substitute for a named real object - with ~850k assets, a real match almost always exists. - CSS, DOM, and canvas overlays are UI only. They must not stand in for Aura3D particles, 3D scene effects, labels attached to models, renderer output, or screenshot evidence. Claim boundary: - Public examples prove only what the root `createAuraApp` safe API actually renders through `@aura3d/engine`. - Do not claim production renderer behavior, high-end PBR parity, HDR/IBL, postprocess, WebGPU, skinned animation, morph targets, production game kits, or collision systems unless a browser test imports only `@aura3d/engine`, mounts the route, captures screenshots, and verifies pixels or runtime state for that exact claim. - Label every capability as one of: `createAuraApp` root safe API, `production-runtime`, `rendering` package internals, CLI asset pipeline, template-only scaffold, prototype, or roadmap. - Do not claim performance parity from the hand-authored feature inventory or a stale visual capture. Comparative performance claims require current like-for-like reports with no missing evidence inputs. - A compiling route is not proof. Evidence must include typed asset provenance, route-health or equivalent diagnostics, and screenshots where the primary subject is readable. Release integrity rules: - no raw string asset IDs, raw GLB/glTF URLs, `unsafeModelUrl(...)`, `three` imports, or `GLTFLoader` in public examples; - no primary character, vehicle, product, weapon, creature, world, or hero environment made only from primitives unless the route is explicitly abstract visualization; - no CSS/DOM particle implementation for examples claiming Aura3D particle rendering; - no WebGPU, PBR, postprocess, skinned animation, morph, or game-runtime claim without matching browser evidence; - no public showcase or README claim that exceeds detected capability, route-health evidence, or screenshots. Scaffold: ```bash npx create-aura3d@latest my-scene --template product-viewer npx create-aura3d@latest my-fighter --template fighting-game npx create-aura3d@latest my-studio --template animation-studio npx create-aura3d@latest my-animation --template animation-channel npx create-aura3d@latest my-episode --template prompt-animation-channel cd my-scene npx @aura3d/cli@latest assets add ./assets/robot.glb --name robot npm run dev ``` Hello world: ```ts import { createAuraApp, lights, model, scene } from "@aura3d/engine"; import { assets } from "./aura-assets"; createAuraApp("#app", { scene: scene().add(model(assets.robot)).add(lights.studio()) }); ``` Public imports for agent-authored apps come from `@aura3d/engine`: `createAuraApp`, `scene`, `model`, `camera`, `lights`, `material`, `effects`, `prefabs`, `sceneKits`, `primitives`, `group`, `timeline`, `interactions`, `physics`, `labels`, `environments`, `game`, `games`, `charts`, `character`, `city`, `product`, `solar`, `particles`, `ui`, evidence helpers, and prompt-animation helpers. Import only the names you use. Game runtime pattern: ```ts import { createAuraApp, game, lights, model, scene } from "@aura3d/engine"; import { assets } from "./aura-assets"; const app = createAuraApp("#app", { scene: scene() .add(model(assets.hero).runtime(game.runtimeNode("player", { tags: ["fighter"] }))) .add(lights.studio()) }); const player = app.nodes.require("player"); const input = game.input({ actions: { moveLeft: ["KeyA", "ArrowLeft"], moveRight: ["KeyD", "ArrowRight"], light: ["KeyJ"] }, axes: { moveX: { negative: "moveLeft", positive: "moveRight" } } }); app.onFrame(({ dt }) => { input.update(dt); player.translate(input.axis("moveX") * dt * 1.5, 0, 0); if (input.pressed("light")) player.play("light", { restart: true, speed: 1.2 }); }); ``` Game runtime rules: - Use `create-aura3d --template fighting-game` when the user asks for a playable browser fighting-game starter. - Create one Aura app per route; do not call `createAuraApp()` every frame. - Use `.runtime(game.runtimeNode("id"))` for nodes that gameplay code needs to mutate. - Use `app.onFrame(...)`, `app.offFrame(...)`, `app.pause()`, `app.resume()`, and `app.step(dt)` for runtime updates and deterministic tests. - Use `app.input(...)` when input should be disposed with the app; use `game.input(...)` for standalone tests and tools. - Call `input.update(dt)` once per frame before querying `pressed`, `held`, `released`, `buffered`, `input.combo(...)`, or `axis`. - Use `game.evidence(app)` to prove runtime nodes and frame-loop activity. - Keep typed assets from `./aura-assets`; do not use string ids, invented URLs, or direct loader code. Current Aura3D game runtime helpers include fighting presets, touch controls, jump assist, collision worlds, colliders, HUD bindings, accessibility state, input replay, event logs, platformer/racing/falling-block helpers, and debug overlays. Use them through `game`/`games` and prove each mechanic with browser input tests before making public game claims. Animation controller pattern: create an `AnimationController` from typed clip metadata, call `animation.update(dt)` in `app.onFrame(...)`, and crossfade named clips only when the names are present in asset metadata or inspection evidence. Current Aura3D animation/editor/visual scripting rules: - Read `docs/api/animation-runtime-events.md` before changing skeletal animation, animation events, or viseme/blendshape sync docs or examples. - Read `docs/api/editor-visual-scripting.md` before changing editor-runtime, timeline, project serialization, visual graph, or graph-to-runtime bridge docs or examples. - Use typed asset metadata for clip, skeleton, and morph target names. If the names are not in `src/aura-assets.ts`, `aura.assets.json`, an asset inspection report, or a source/license evidence file, inspect the asset first instead of guessing. - Use `AnimationController` / `createAnimationController(...)` for named clips, restart, crossfade, layers, events, diagnostics, and deterministic pose snapshots. - Use `animation.onEvent(...)` for clip-local gameplay events such as `hitbox.open`, `hitbox.close`, `sfx`, `vfx`, `camera.impulse`, `caption`, and `viseme`. - Use runtime node `setAnimationPose(...)`, `setMorphTarget(...)`, and `setMorphTargets(...)` for pose/morph state. Do not reach into renderer internals from app code. - For AuraVoice/animation sync, sample bridge or viseme timing and apply typed morph weights to the runtime node: ```text app.onFrame(({ time }) => { const sample = sampleAuraVoiceBridgeAtTime(bridgePackage, time, "host"); app.nodes.require("host").setMorphTargets(sample.viseme?.blendshapeWeights ?? {}); }); ``` - `@aura3d/editor-runtime` and `@aura3d/scripting` are public package surfaces for tools and tests. Live browser routes still mount through `@aura3d/engine`. - Visual graphs can validate and emit deterministic side effects. A graph is not proven to drive a browser scene until those side effects are applied to a mounted Aura app and captured in browser evidence. - Source metadata, deterministic snapshots, and nonblank screenshots are not enough for release claims. Animation/editor/visual scripting tasks need typed asset provenance, unit evidence, browser evidence, screenshots with hashes, package smoke reports, and explicit release reports under the relevant `tests/reports/*` directory. Aura3D Animation Studio rules (prompt → document → render pipeline): - Use `create-aura3d --template animation-studio` for the agent-driven episode workflow. YOU (the coding agent / harness) are the director — there is NO separate LLM and NO API key. You drive the validated Scene-Tool CLI (`animation-scene`, a.k.a. `aura3d animation scene`); each command edits one `EpisodeDocument` (`dist/scene/working.document.json`) and is rejected if it would break the scene. `animation-channel` and `prompt-animation-channel` remain source-level examples unless their render/package gates pass. - Generate a complete scene from a prompt: `animation-scene new --prompt "..." --full` (cast + dialogue + camera + per-beat actions). Omit `--full` for an empty-cast skeleton you populate. There is NO default scene — `animation-scene new` with no prompt is an error. - Cast: prompt nouns bind to the curated render-ready A-grade humanoid cast (neutral cast-a/cast-b — NEVER the moon-garden miko/luma). Override a slot with `animation-scene cast add --id --query "..."` (catalog) or `--file ` (local rig). - Set: `pickSetForPrompt` routes by keyword — garage/office/kitchen → distinct interiors, forest/meadow → meadow, space/station → space-station, moon/garden/night → moon-garden, everything else → a neutral studio. Moon Garden is NEVER the default. - Motion: a shared standard clip library (idle/talk/gesture/point/nod/walk/run/react) is retargeted per character. Extracted catalog mocap drives the UPPER body; legs stay procedural for stability; locomotion is velocity-gated (a walk/run cycle plays only while the character is actually translating). - Dialogue: write the timed track yourself with `animation-scene dialogue --line --speaker --text "..." --start ` (`--end` optional — computed from the line's speech duration). This single track IS the subtitles AND the AuraVoice lip-sync contract. - Render: `animation-scene render` (or `npm run episode:render-3d`) with `AURA_QUALITY=preview|final` and `AURA_RENDER_STYLE=toon|pbr`. The render is SILENT by design — Aura3D NEVER runs TTS; it emits the timed dialogue/caption/viseme track that AuraVoice consumes to generate the voice and mux audio afterward. - Resolve typed animation assets when pre-staging a manifest: `assets resolve ... --profile animation-character` for characters and `--profile animation-set` for sets when those profiles are available; otherwise add local licensed GLB/glTF assets with `assets add` and keep provenance in `aura.assets.json`. - A publish-ready animation episode needs real route playback, independently moving characters, visible mouth motion during dialogue, exported captions, render/package evidence, and review artifacts. - Do not claim a generated still image with CSS pan/zoom/shake/wobble, fake parallax, or subtitles is real Aura3D animation. Routes or reports marked `notTrue3D: true`, `sourceOnly: true`, or `image-puppet` are negative or experimental evidence only. - Do not claim Pixar quality, magic image-to-video, full animation-studio replacement, Unity/Unreal parity, or automated YouTube production unless the 1.1 PRD gates and human review evidence prove the narrower claim. - Use generated images as concept art, thumbnails, textures, background plates, or style references. The episode itself must be driven by typed assets, rigs or explicitly segmented puppet parts, timelines, visemes, captions, and render evidence. Benchmark priority: - Use `sceneKits.()` first for benchmark prompts. - Use `prefabs.*` only when the prompt needs lower-level composition. - Use primitives only for small prompt-specific additions, never as the main scene system. - A nonblank screenshot is not enough. The image must visibly match the prompt. - Read `docs/agents/benchmark-recipes.md` before writing benchmark code. - For benchmark runs, run finite commands such as `npm install` and `npm run build`, then stop. Do not run `npm run dev`, `npm run preview`, Playwright, browser screenshot capture, or manual visual verification inside the agent process. Root scene-kit examples: ```ts import { createAuraApp, sceneKits } from "@aura3d/engine"; import { assets } from "./aura-assets"; const dataset = [ [0.42, 0.68, 0.91], [0.55, 0.77, 0.83], [0.31, 0.59, 0.72] ] as const; createAuraApp("#app", sceneKits.physicsPlayground().toAppOptions()); createAuraApp("#app", sceneKits.particleFountain({ particleCount: 2400, emissionRate: 120 }).toAppOptions()); createAuraApp("#app", sceneKits.solarSystem().toAppOptions()); createAuraApp("#app", sceneKits.neonTunnel().toAppOptions()); createAuraApp("#app", sceneKits.dataViz({ dataset }).toAppOptions()); createAuraApp("#app", sceneKits.miniGolf().toAppOptions()); createAuraApp("#app", sceneKits.materialLab().toAppOptions()); createAuraApp("#app", sceneKits.cityBlock({ timeOfDay: "night" }).toAppOptions()); createAuraApp("#app", sceneKits.humanoidWalk({ animationState: "benchmark-pose" }).toAppOptions()); createAuraApp("#app", sceneKits.productViewer(assets.product).toAppOptions()); ``` Scene-kit selection table: | Prompt family | Start with | Expected screenshot contains | | --- | --- | --- | | Physics playground | `sceneKits.physicsPlayground()` | falling cubes, settled pile, ramp/catch geometry, contact patches, gravity cue, reset affordance | | Particle fountain | `sceneKits.particleFountain({ particleCount, emissionRate })` | dense upward flow, lifetime color variation, nozzle/emitter base, splash or collision context, emission-rate UI | | Solar system | `sceneKits.solarSystem()` | sun glow, six labeled planets, orbit paths, depth framing, stars/dust, readable scale cues | | Neon tunnel | `sceneKits.neonTunnel()` | inside-the-tube view, receding rings, rails, reflective floor/walls, fog depth, controlled bloom | | 3D data visualization | `sceneKits.dataViz({ dataset })` | bars, axes, numeric ticks, title, legend, selected value or hover readout, no orphan labels | | Mini golf | `sceneKits.miniGolf()` | ball, cup, aim/power state, score, obstacle, course boundaries, follow-camera target cue | | Material lab | `sceneKits.materialLab()` | root-proven base color, limited metallic/roughness contrast, matte/emissive material differences; partial texture/alpha/glass intent; unsupported clearcoat, normal-map, transmission, and contact-shadow claims unless separate root pixels prove them | | City block | `sceneKits.cityBlock({ timeOfDay })` | many buildings, window grids, streets, crosswalks, props, traffic/street lights, visible day/night state | | Humanoid walk | `sceneKits.humanoidWalk({ animationState: "benchmark-pose" })` | one connected humanoid, planted feet, shoulder/hip sockets, face cues, motion/path evidence | | Product viewer | `sceneKits.productViewer(assets.product)` | typed model centered, scaled, seated on plinth, contact shadow, softboxes, orbit/turntable cues | Do not submit examples: - Do not submit a primitive humanoid puppet made from disconnected boxes, spheres, or capsules. Use `sceneKits.humanoidWalk()` or `character.lowPolyHumanoid()` and run `character.visualQA(nodes)` when you customize. - Do not submit toy mini-golf with only a flat plane and a ball. Use `sceneKits.miniGolf()` or `games.createMiniGolfState()` so score, aim, obstacle, cup, boundaries, and physics evidence are visible. - Do not submit stray chart geometry, floating labels, detached ticks, or cobweb guide lines. Use `sceneKits.dataViz()` or `charts.visualQA(nodes)`. - Do not submit blown-out neon that becomes a white rectangle or flat portal. Use `sceneKits.neonTunnel()` and keep bloom/fog controlled. - Do not submit a washed material lab where root-proven metal/rubber/emissive differences look identical. Treat glass, clearcoat, transmission, normal maps, reflections, and contact shadows as partial or unsupported unless retained root pixels prove those exact features. Physics API boundary: - Prefer `sceneKits.physicsPlayground()`, `sceneKits.miniGolf()`, `prefabs.physicsPlayground(...)`, `prefabs.physicsRamp()`, and `prefabs.miniGolfHole()` for benchmark-visible physics evidence. - Use the safe root `physics` namespace from `@aura3d/engine` for simulation state: `physics.world(...)`, `physics.body(...)`, `physics.box(...)`, `physics.sphere(...)`, `physics.step(...)`, `physics.debug(...)`, and `physics.debugNodes(...)`. - Use `physics.worldFromScene(scene)` when you authored nodes with `.physics(...)` and want Aura3D to create bodies/colliders from the scene. - Do not import `PhysicsWorld`, `Shape`, or `PhysicsDebugAdapter` from `@aura3d/engine`. - Do not hand-roll mini-golf physics when `games.createMiniGolfState()` covers shots, score, collisions, cup trigger, reset, and follow-camera metrics. - Lower-level `@aura3d/physics` has opt-in adaptive CCD and accumulated Coulomb friction, but native oriented narrow-phase and angular contact remain incomplete. Name the backend and exact proof; do not generalize package or `cannon-es` evidence into a root collision claim. Typed asset rule: - Add assets with the CLI before writing model code: `npx @aura3d/cli@latest assets add ./assets/model.glb --name model`. - Read generated `src/aura-assets.ts` and import `assets` from `./aura-assets`. - Use `model(assets.model)` or `sceneKits.productViewer(assets.product)` with the exact generated key. - For normal public `model(assets.x)` scenes, use render-normalized placement helpers such as `groundedRenderedAssetPlacement(...)`, `normalizedRenderScaleForTargetHeight(...)`, and `normalizedRenderScaleForTargetMaxDimension(...)`. Do not use raw GLB `boundsMetadata` scale math directly in route code; the safe renderer already normalizes and grounds GLBs before user scale is applied. - Do not use `model("model")`, string asset ids, invented URLs, unrelated copied GLBs, or `unsafeModelUrl(...)` for benchmark product proof. - `unsafeModelUrl(...)` is only an explicit temporary escape hatch outside safe benchmark code. Game and animation asset readiness: - Before claiming a playable game route is asset-ready, run or document `npx @aura3d/cli@latest assets validate-game --profile fighting-character` for fighter-heavy routes. - Before claiming a prompt-to-animation or AuraVoice episode route is asset-ready, run or document `npx @aura3d/cli@latest assets validate-animation`. - Use `npx @aura3d/cli@latest assets assemble-character --name hero --body heroBody --part hair=heroHair` for repeatable character plans. Add every body, hair, prop, outfit, and stage part through `assets add` first. - A readiness report is not visual proof. Do not mark visual-quality, animation-quality, or launch-quality gates complete without screenshot/runtime evidence. - Use `create-aura3d --template prompt-animation-channel` for prompt-driven episode scaffolds that need AuraVoice manifests, shot timelines, dialogue beats, visemes, captions, and render plans. The shorter `animation-channel` template name remains supported. Aura3D 2.0 package/readiness declarations: ```bash npx create-aura3d@latest my-fighter --template fighting-game npx create-aura3d@latest my-episode --template prompt-animation-channel npx @aura3d/cli@latest assets validate-game --profile fighting-character npx @aura3d/cli@latest assets validate-animation npx @aura3d/cli@latest check-deploy --dist dist pnpm game-runtime:docs pnpm game-runtime:template pnpm game-runtime:package pnpm game-runtime:release pnpm prompt-animation:docs pnpm prompt-animation:template pnpm prompt-animation:package pnpm prompt-animation:release ``` Do not claim game, prompt-animation, AuraVoice, package, deployment, screenshot, visual-quality, or accessibility readiness from source declarations alone. The matching command outputs, route evidence, browser screenshots, deterministic hashes, and human/automated visual review must exist. Aura3D 2.0 game-engine/showcase claim rules: - Treat 2.0 as a major public-contract replatform whose package, docs, installed-route, performance, visual, and readiness claims remain separately evidence-gated. - Do not describe Aura3D as a mature commercial game engine, Unity replacement, Unreal competitor, or Babylon.js parity product. - Do not describe Aura Clash Arena as a flagship-quality game until gameplay, visual, asset, audio, performance, deployment, and docs-claim gates pass. - Aura Clash Arena may be described as a development showcase and runtime proof target when supported by current build, smoke, screenshot, and route evidence. - Use a static approved poster/link in marketing previews unless the live playable embed passes the same visual and gameplay gates as the route itself. Prompt-animation and AuraVoice pattern: - `compilePromptEpisodePlan(...)` owns the explicit episode JSON contract. - `createAuraVoiceBridgePackage(...)` carries dialogue/captions/visemes/audio stems. - `createShotPlaybackPlan(...)` plus `installShotPlayback(...)` drives a mounted Aura app. - `collectPromptAnimationEvidence(...)` and `evaluatePromptAnimationPublishReadiness(...)` are required before public claims. - Cast, locations, dialogue, screenshots, and audio paths are user/project data. There is no default cast or set. Prompt-plan pattern: ```ts const plan = definePromptPlan({ sceneType: "product-viewer", subject: { asset: assets.product }, camera: { preset: "product-orbit" }, lighting: { preset: "studio-softbox" }, effects: ["bloom"], interaction: "orbit", acceptanceCriteria: ["product centered", "studio lighting visible"] } as const); const compiled = compilePromptPlan(plan); createAuraApp("#app", { scene: promptPlanToScene(plan) }); console.log(compiled.report.visualSystems, compiled.report.repairHints); ``` Diagnostics and QA: - Use `collectAuraSceneEvidence(scene)` to report physics bodies/colliders, interaction modes, camera state, animation clips, typed asset provenance, and performance budgets. - Use `charts.visualQA(nodes)`, `character.visualQA(nodes)`, `city.visualQA(nodes)`, `product.visualQA(nodes)`, and `solar.visualQA(nodes)` before accepting customized prompt scenes. - If visual review fails, apply `compilePromptPlan(plan).report.repairHints` or switch back to the matching scene kit before changing labels or claims. Small UI rules: - Use `ui.html`, `ui.setText`, `ui.onClick`, `ui.range`, `ui.slider`, and `ui.onInput` for HUD text, counters, buttons, and sliders. - Do not use `HTMLStrongElement` or untyped `event.currentTarget` in benchmark TypeScript. - Create one Aura app per route. Do not call `dispose()` and `createAuraApp()` every animation frame. Use `.animate(...)`, `timeline.loop(...)`, or ordinary DOM overlay updates. Verification: ```bash npm run build npm run test npx @aura3d/cli@latest assets validate ```