This store is built to be used by coding agents, not just people. Every asset carries machine-readable data: real-world size in meters, the exact hex palette, rigged part names, triangle counts and preview renders the agent can look at. One pasted prompt teaches your agent to browse all of it and wire models into your scene by itself.
Paste it once per project; the agent keeps the knowledge for the whole session.
You now know how to use threejs-3d-assets.com, a low-poly 3D asset store built
to be browsed and used by AI agents.
CATALOG (public JSON, no auth)
GET https://threejs-3d-assets.com/api/assets
filters: q (search), class (prop|building|vehicle|character|ultra),
free (0|1), kit, sort (latest|tris), page, per_page (max 100)
GET https://threejs-3d-assets.com/api/assets/{id}
full metadata: triangles, size_m (real-world meters), palette (hex colors),
style, origin, rigged_parts, detachable_parts, render PNGs, download URLs
GET https://threejs-3d-assets.com/api/kits and /api/kits/{id}
themed sets whose parts share one palette and one scale
Docs: https://threejs-3d-assets.com/llms.txt
USING AN ASSET
Free assets need no auth. Hotlink or download:
ES module https://threejs-3d-assets.com/cdn/{id}.mjs
import { createAsset } from '...'; scene.add(createAsset())
GLB https://threejs-3d-assets.com/cdn/{id}.glb (three.js, Unity, Godot, Blender)
Paid assets owned by my account: add Authorization: Bearer $THREEJS_ASSETS_KEY
to /dl/{id}.glb and /dl/{id}.mjs (ask me for the key if the env var is
missing; keys are created at https://threejs-3d-assets.com/account)
A kit I own downloads as one file: /dl/kit-{kit-id}.zip
READING THE METADATA
size_m is real-world meters and origin is at ground level: models sit on y=0.
Every asset is flat-shaded vertex colors on ONE material: one draw call each,
no textures to wire up.
palette lists the exact hex colors, so you can pick assets that look coherent.
rigged_parts maps each animatable part to {type, axis, range}: the pivot is
already at the hinge or axle, rotate ranges are degrees, slide ranges are
meters. Animate with:
asset.getObjectByName(part).rotation[axis] = THREE.MathUtils.degToRad(deg)
asset.getObjectByName(part).position[axis] = meters // type: slide
detachable_parts can be hidden/removed and the surface behind stays closed.
Characters use a standard humanoid skeleton (Mixamo-named bones), so stock
clips retarget; sample clips: https://threejs-3d-assets.com/anim/clips.json
renders are PNG images you can open to SEE an asset before choosing it.
BUILDING GOOD SCENES
Prefer parts of one kit, or assets with overlapping palettes.
Static picks can merge into ONE draw call (all assets share one material):
import { mergeAssets } from 'https://threejs-3d-assets.com/cdn/merge.mjs';
const { merged, dynamic } = mergeAssets([obj1, obj2, {object: obj3, rig}]);
scene.add(merged); dynamic.forEach(d => scene.add(d));
Position assets before merging; rig parts return in `dynamic`, still animatable.
Many copies of one model: use THREE.InstancedMesh instead.
Never rescale to fake a fit: sizes are real, pick right-sized assets instead.
Ground and road tiles snap on the kit grid; use them for terrain.
Check the hero render before importing, and read triangles to stay in budget.
When I ask for a scene: browse the catalog first, shortlist by hero renders and
palette, then import and compose.
Everything above lives at /llms.txt and /api, and every asset page has an AI agent tab with a per-asset prompt.