ccppccpp home

Profiles

Three.js r186

Three.js 0.186.x (r186) code, assets and tooling without pre-r186 APIs, with owned GPU resources, bounded per-frame work and package-manager-owned dependencies; any renderer, runtime or app shape. Rule IDs TJ-V/T/A/L/F/G/P/X/E/S/Q; NEED TO blocks.

Set this profile

ccpp cpo profile set threejs

Inside Claude Code, prefix the command with ! to run it in the session. Downloading a profile needs a Builder or Team plan; listing them does not.

Policies

93 policies, grouped by what they guard.

Error handling 1

Failures are propagated or handled, never swallowed or turned into fake success.

  • tj-l12-swallowed-failures

    TJ-L12/S08 · Three.js loading, initialization and compilation failures are not swallowed (empty catch, .catch(() => {}))

Performance & resource bounds 6

Timeouts, bounded retries and fan-out, reused clients, closed resources, no N+1 queries.

  • tj-f09-frame-allocations

    TJ-F09/F10/L13/P08/X11 · Per-frame callbacks do no unguarded allocation, GPU object construction or recompilation triggers

  • tj-f11-frame-calls

    TJ-F10/F11/G06/G16/P19/S05/X13 · Per-frame callbacks do no unguarded loading, compilation, PMREM generation, vertex baking, layout reads, logging, scene scans or sync readback

  • tj-l02-remove-without-dispose

    TJ-L02/L04 · Code that removes or clears scene objects it built releases their GPU resources (remove/clear/null do not dispose; material.dispose() keeps its textures)

  • tj-l06-recreated-gpu-objects

    TJ-L06/L13 · Resize and re-setup handlers resize or reuse renderers and render targets instead of constructing new ones without disposing the old

  • tj-l10-decoder-loaders

    TJ-L10/X07/X08 · KTX2/DRACO loaders are configured once (transcoder path, detectSupport), reused across assets and disposed when done

  • tj-l14-teardown

    TJ-L09/L14/S09 · A teardown that exists stops the render loop and releases the renderer, controls, timer and animation mixers the module created

Architecture & boundaries 4

Declared layers and dependency directions, no import cycles, small modules, explicit dependencies.

  • tj-a06-host-globals

    TJ-A06 · Reusable Three.js modules receive their canvas/container and size from the host (no document.body append or window sizing outside entry modules)

  • tj-s02-global-handles

    TJ-S02 · Renderer, scene, camera and loaders are not published as mutable globals (window.x / globalThis.x)

  • tj-s06-function-length

    TJ-S06 · With a selected budget (maxFunctionLines), functions in Three.js modules stay within it (warn; off by default)

  • tj-s07-renderer-internals

    TJ-A07/S07 · No patching of three internals (private renderer fields, ShaderChunk/ShaderLib overrides, prototype monkey patches, raw GL state)

Versions & deprecated APIs 26

Code matches the installed version, without removed, renamed or deprecated APIs.

  • tj-v01-installed-version

    TJ-V01/V02/V04 · At session start, Claude learns the resolved three (and @types/three) version and whether this r186 profile applies

  • tj-v03-post-r186-apis

    TJ-V03 · No r187+ API in r186 code (Light.registerNode light registration)

  • tj-v05-commonjs-require

    TJ-V05 · New code imports three as an ES module (require('three') is deprecated in r186 and warns at run time)

  • tj-v05-core-exports

    TJ-V05/V08/V09/V10/V41 · Imports from three and three/webgpu name exports the resolved package has (no Geometry, *Encoding, *BufferGeometry, default import…)

  • tj-v05-module-paths

    TJ-V05/V06/V08/V11 · three subpath imports exist in the resolved package (no examples/js, three/nodes, removed addons, removed global builds)

  • tj-v05-tsl-exports

    TJ-V05/V42 · TSL imports from three/tsl name functions the resolved package exports (no tslFn, timerLocal, cond, uniforms, rangeFog, blend renames…)

  • tj-v06-html-modules

    TJ-V04/V06 · HTML pages load three as modules from one revision: no removed three(.min).js builds, an import map for bare imports, core and addons on the same version

  • tj-v07-addons-alias

    TJ-V07 · New addon imports use the public three/addons/ alias rather than three/examples/jsm/

  • tj-v09-removed-members

    TJ-V09/V10/V14/V34/V35/V37/V41 · No removed three members or options (outputEncoding, useLegacyLights, addAttribute, updateRange, waitForGPU, reverseDepthBuffer, TextGeometry height…)

  • tj-v11-deprecated-imports

    TJ-V11/V16/V17/V18/V31/V42/V45 · New code avoids three exports r186 deprecates (Clock, PostProcessing, PCFSoftShadowMap, Source, RGBELoader, PI2, cache, label…)

  • tj-v12-deprecated-members

    TJ-V12/V25/V27/V32/V33/V34 · New code avoids deprecated three members (renderAsync/clearAsync/…, setDecoderConfig, detectSupportAsync, createShapes, GTAO distance settings…)

  • tj-v12-lsp-deprecated

    TJ-V11/V12/V45 · No new call or member resolves to a declaration three marks @deprecated (language server: Matrix3 transforms, PassNode.setResolution, PMREM async…)

  • tj-v13-webgpu-init

    TJ-V13 · WebGPURenderer is initialized (await init() or setAnimationLoop) before hasFeature/compute/render/initTexture/detectSupport, and init failures are handled

  • tj-v15-webgpu-dispose

    TJ-V15 · WebGPURenderer.dispose() is awaited or returned when teardown completes asynchronously (WebGLRenderer disposal stays synchronous)

  • tj-v19-dispose-super

    TJ-V19 · A class extending a three Object3D type that overrides dispose() calls super.dispose() (r186 Object3D.dispose dispatches the dispose event)

  • tj-v21-triangles-in-place

    TJ-V21 · toTrianglesDrawMode() mutates its geometry in place since r186: a second name for the result is a shared, changed geometry

  • tj-v22-async-results

    TJ-V22/V33 · Promise-returning three APIs (SimplifyModifier.modify, EXR/KTX2 parse, parseAsync, loadAsync, fromCubeRenderTarget) are awaited or chained, not used as values

  • tj-v23-light-probe-grid

    TJ-V23 · WebGLRenderer code uses r186's LightProbeGridWebGL / LightProbeGridHelperWebGL (LightProbeGrid is now the WebGPU class)

  • tj-v24-sky-up-uniform

    TJ-V24 · Sky / SkyMesh code does not write the removed up uniform (+Y up is assumed since r186)

  • tj-v29-loader-return-value

    TJ-V29 · FileLoader.load() and ImageBitmapLoader.load() results come from onLoad or loadAsync (their return value is undefined since r184)

  • tj-v30-fbx-z-up

    TJ-V30 · No blanket Z-up correction on FBX imports (FBXLoader converts Z-up assets itself since r184)

  • tj-v36-copy-signatures

    TJ-V36 · copyTextureToTexture / copyFramebufferToTexture use the r186 argument order (textures first, positions after)

  • tj-v38-batched-instances

    TJ-V38 · BatchedMesh geometries become visible through addInstance(geometryId), not addGeometry alone

  • tj-v39-transform-controls-helper

    TJ-V39 · TransformControls is shown by adding controls.getHelper() to the scene (the controls are not an Object3D since r169)

  • tj-v40-controls-connect

    TJ-V40 · Controls.connect() receives the DOM element to listen to (no undefined fallback since r175)

  • tj-v44-position-local

    TJ-V44 · A positionNode built from positionLocal on skinned or morphed meshes is a deliberate choice (positionGeometry keeps skinning/morphing)

3D rendering 35

Materials, shaders, cameras, render loops and color spaces of real-time 3D scenes.

  • tj-a02-webgpu-glsl-materials

    TJ-A02/A03 · WebGPURenderer code customizes shading with node materials/TSL and post-processes with RenderPipeline (no ShaderMaterial, onBeforeCompile, EffectComposer)

  • tj-a04-node-materials-webgl

    TJ-A04 · Node materials rendered by WebGLRenderer go through the r186 WebGLNodesHandler (renderer.setNodesHandler)

  • tj-a08-stencil-buffer

    TJ-A08 · Stencil-based materials render with a stencil buffer enabled on the renderer created in the same module (off by default since r163)

  • tj-a09-tsl-js-operators

    TJ-A09 · TSL nodes are combined with node methods (add/mul/If/select), not JavaScript operators or if/ternaries that run once on the CPU

  • tj-a10-shader-uniforms

    TJ-A10 · ShaderMaterial uniforms are { value } objects, updated through uniform.value (no raw numbers/vectors, no replacing a uniform)

  • tj-a11-glsl-version

    TJ-A11 · Custom GLSL 3 shaders set glslVersion: GLSL3 and do not embed their own #version directive

  • tj-e03-render-target-restore

    TJ-E03 · Reusable passes (functions receiving the renderer) that switch the render target restores the previous one (getRenderTarget) instead of assuming it was null

  • tj-e05-pipeline-output-update

    TJ-E05 · Replacing RenderPipeline.outputNode after setup sets pipeline.needsUpdate = true

  • tj-f01-nested-frame-loops

    TJ-F01 · A callback given to setAnimationLoop does not also schedule itself with requestAnimationFrame (one scheduling owner per surface)

  • tj-f02-xr-animation-loop

    TJ-F02 · XR rendering is scheduled by renderer.setAnimationLoop (window requestAnimationFrame does not run inside an XR session)

  • tj-f05-time-units

    TJ-F05 · AnimationMixer.update and OrbitControls.update receive a delta in seconds, not a millisecond timestamp or an elapsed time

  • tj-f06-timer-update

    TJ-F06 · A Timer the module creates and reads is advanced with timer.update() (core Timer never advances on its own)

  • tj-f08-damping-update

    TJ-F08 · Controls with damping or auto-rotation enabled are updated every frame (controls.update) while those features run

  • tj-g03-attribute-uploads

    TJ-G03 · Buffer attributes written in per-frame callbacks are flagged for upload (attribute.needsUpdate = true)

  • tj-g05-instance-bounds

    TJ-G05 · Instances moved every frame keep valid bounds for culling and picking (computeBoundingSphere, or a justified frustumCulled = false)

  • tj-g07-attribute-item-size

    TJ-G07 · Literal vertex data matches its attribute itemSize (array length divisible by itemSize)

  • tj-g08-instance-uploads

    TJ-G08 · setMatrixAt / setColorAt / setMorphAt in frame callbacks and event handlers are followed by the matching needsUpdate flag

  • tj-g13-merge-null

    TJ-G13 · The result of mergeGeometries / mergeAttributes is checked for null before it replaces geometry

  • tj-g14-traverse-mutation

    TJ-G14 · traverse() callbacks do not add or remove scene objects while iterating (collect, then mutate)

  • tj-g15-manual-matrices

    TJ-G15 · Objects with matrixAutoUpdate = false recompute their local matrix after transform changes and flag matrixWorldNeedsUpdate after direct matrix edits

  • tj-p01-pixel-ratio

    TJ-P01 · The drawing buffer's pixel ratio is bounded (no raw devicePixelRatio: cost grows with its square)

  • tj-p02-projection-update

    TJ-P02 · Changing a camera's aspect, fov, near/far, zoom or frustum is followed by updateProjectionMatrix() in the same function

  • tj-p03-zero-size-aspect

    TJ-P03 · Aspect ratios computed from element sizes guard a zero height (hidden, collapsed or detached surfaces)

  • tj-p04-depth-range

    TJ-P04 · Literal perspective cameras use a valid depth range (0 < near < far) and, with a selected budget, a bounded far/near ratio

  • tj-p06-costly-renderer-flags

    TJ-P05/P06 · Costly renderer options (preserveDrawingBuffer, MSAA under post-processing, logarithmicDepthBuffer) come with a stated purpose

  • tj-p09-program-cache-key

    TJ-P09 · onBeforeCompile code that varies the shader with closure values declares customProgramCacheKey

  • tj-p13-premultiplied-blending

    TJ-P13 · Materials using MultiplyBlending or SubtractiveBlending set premultipliedAlpha: true (required since r178)

  • tj-p14-shadow-budget

    TJ-P14/P15 · Shadows are enabled per object, not for a whole traversal, and shadow maps stay within the project's selected budget

  • tj-p17-picking

    TJ-P17/P18 · Pointer picking computes coordinates from the canvas rectangle and does not raycast the whole scene recursively on every move

  • tj-x01-color-texture-space

    TJ-X01 · Color textures loaded with TextureLoader and used as map/emissiveMap get colorSpace = SRGBColorSpace (TextureLoader leaves NoColorSpace)

  • tj-x02-data-texture-srgb

    TJ-X02 · Data maps (normal, roughness, metalness, AO, displacement, bump, alpha…) are not tagged SRGBColorSpace

  • tj-x03-double-color-conversion

    TJ-X03 · Hex/CSS colors are not converted to linear a second time (ColorManagement already converts in setters)

  • tj-x04-output-conversion

    TJ-X04/X05 · Post-processing applies tone mapping and output color conversion exactly once (OutputPass for EffectComposer; outputColorTransform off when renderOutput is manual)

  • tj-x10-render-target-size

    TJ-X10 · Render targets are resized with setSize(), not by assigning width/height

  • tj-x12-texture-sampling

    TJ-X09/X12 · Textures assigned to glTF materials keep glTF orientation (flipY = false), and max anisotropy is not applied to every texture

Dependencies & toolchain 15

Packages change through the package manager, lockfiles stay consistent and the project's tools are used.

  • tj-t01-manual-dependency-edit

    TJ-T01 · Dependencies change through the package manager (add/remove/update), never by editing package.json by hand

  • tj-t01-new-manifest

    TJ-T01/T02 · A new package.json comes from the package-manager initializer (or a generator), and gets its dependencies from the package manager

  • tj-t01-package-manager-call

    Records the tool calls that run a package manager (they may rewrite package.json and lockfiles; TJ-T01/T08)

  • tj-t02-hand-written-manifest

    TJ-T02 · A new package.json without dependencies is initialized with the package manager

  • tj-t03-version-lookups

    TJ-T03 · Registry version lookups are not a step before installing

  • tj-t03-version-pins

    TJ-T03 · Packages are installed by name: no guessed exact version, no --save-exact without a reason

  • tj-t04-package-manager

    TJ-T04 · Dependencies are installed with the project's package manager (packageManager field, lockfile)

  • tj-t04-second-lockfile

    TJ-T04 · No second lockfile next to another package manager's lockfile

  • tj-t05-locked-installs

    TJ-T05 · CI and container builds restore dependencies from the lockfile (npm ci, --frozen-lockfile, --immutable)

  • tj-t06-vendored-copy

    TJ-T06/S07 · Project sources do not contain copied three builds or addon modules (license header of Three.js Authors)

  • tj-t06-vendored-download

    TJ-T06 · three builds and addons are not downloaded into the project by hand (curl/wget); the package manager or an import map provides them

  • tj-t08-hand-edited-lockfile

    TJ-T08 · Lockfiles are written by the package manager only (no hand edit, no script rewriting them)

  • tj-t08-stale-lockfile

    TJ-T08 · A turn that changes package.json dependencies also updates the lockfile next to it (once per stop)

  • tj-v01-install-specs

    TJ-V01/T03 · Installing three or @types/three at a version outside this profile's release line needs the user's confirmation

  • tj-v01-resolved-version

    TJ-V01 · After an install that named three, the resolved three is still on this profile's release line

Completion evidence 6

A turn ends with its checks run and passing; claims of success need proof after the last edit.

  • tj-q01-evidence-ledger

    Records, per session, Claude's edits (file tools and shell writes) and the typecheck, lint and test runs that succeeded after them (TJ-Q01)

  • tj-q01-new-type-errors

    TJ-Q01 · A turn adds no TypeScript errors to the changed files or their importers (language server, once per stop)

  • tj-q01-required-checks

    TJ-Q01 · A turn that changed Three.js code ends only after the configured checks (default: typecheck) succeeded on the final files (once per stop)

  • tj-q03-measurement-ledger

    Records that the turn ran a measurement (benchmark, profiler, performance trace) for TJ-Q03

  • tj-q03-performance-claims

    TJ-Q03 · A turn that changed Three.js code does not claim a measured performance gain without a measurement in the turn (once per stop)

  • tj-turn-baseline

    Records the work tree when a prompt starts: the baseline of the Three.js end-of-turn checks (TJ-T08, Q01)