Free low-poly models that behave like React components. R3F renders three.js from JSX, and its <primitive> escape hatch takes any Object3D, so these modules drop straight in: no GLTFLoader, no useGLTF, no Suspense boundary and no loading state. Each one returns a ready THREE.Group the moment you call it, and the parameters it was built with arrive as props. Real-world scale, origin on the ground, one material and one draw call each. No attribution, commercial use allowed.
Every free model is hotlinkable. This is the real snippet for Hanging Signboard:
// GLB: works in three.js, Unity, Godot, Blender
new GLTFLoader().load(
'https://polyfork.dev/cdn/hanging-signboard-c10e01.glb',
(gltf) => scene.add(gltf.scene)
);
// or the drop-in ES module (three.js, zero loaders):
import { createAsset } from 'https://polyfork.dev/cdn/hanging-signboard-c10e01.mjs';
scene.add(createAsset());
The starter opens a full React Three Fiber project in StackBlitz with one of these models already in it: a Canvas, the component, and a dropdown wired to one of the model's own knobs. Nothing to install and no account. The model ships inside the project as a local file, which is how you would really use it, so what you are looking at is the actual workflow rather than a demo that only works here.
A GLB is a file, so using one in R3F means useGLTF, a Suspense boundary and a loading state to design around, and what you get back is frozen geometry. These are ES modules: createAsset() returns a ready THREE.Group synchronously, and <primitive object={obj} /> accepts it as-is. There is nothing to await and nothing to suspend, so a model can render on the first frame alongside the rest of your tree.
A model here is a small program rather than a mesh, and its parameters are typed and published. In R3F that stops being a feature you read about and becomes the thing you already expect: wrap createAsset in useMemo keyed on props and <Tree season="autumn" height={4} /> rebuilds exactly like any other component. State, context, springs and leva controls drive it with no adapter, because it is just props going into a function.
gltfjsx exists because a GLB is static and React developers want components, so it converts geometry into JSX once, ahead of time. It is a good tool and worth using on your own models. What it cannot do is give a mesh parameters it never had: the JSX it writes describes one frozen shape. These models ship with their parameters intact, which is the difference between a component that renders a model and a component that generates one.
Some models animate themselves and expose userData.tick(seconds): live water, a steam plume, drifting bubbles. R3F already owns the frame loop, so drive it from useFrame with state.clock.elapsedTime and nothing else is needed. The model has no loop of its own to conflict with yours.
Every model is flat-shaded vertex colours on a single material, so a set of them merges into one draw call. Import mergeAssets from the CDN, merge the static ones, and hand the result to a single <primitive>. Anything rigged comes back separately so it stays animatable.
A Canvas cannot server-render, so the component holding it is a client component: add the use client directive, or import it with next/dynamic and ssr false. Import the .mjs as a local file in the project rather than from the CDN URL, because bundlers do not resolve remote imports. The plain three.js page covers the hotlinking route for pages without a bundler.
Every free model on this page, downloaded at once, is 10.1 MB. They are flat-shaded vertex colour on one material with no textures, which is where the size goes and why they draw in one call. Measured from the files being served right now, not rounded down for a landing page.
No. A model is a plain Object3D going through <primitive>, so fiber alone is enough. drei still helps with everything around it, and OrbitControls, Environment and Stage all work on these models normally.
In a plain page with an import map, yes. In a React project built with Vite or Next, no: bundlers do not resolve https:// imports. Download the .mjs from the model's page and import it as a local file.
Yes, with the usual R3F caveat that a Canvas cannot server-render. Put it in a client component, or load it with next/dynamic and ssr set to false. Nothing about these models makes that harder than any other R3F scene.
Every asset under 600 triangles is free forever, which is currently about half the catalogue. Free means the GLB and the ES module, no attribution, commercial use allowed. A free account downloads them; browsing and hotlinking need no account at all.
Not yet. The modules are plain JavaScript, and each one publishes its knob schema as JSON next to it, so the parameter names and ranges are machine-readable even though there is no .d.ts to import.
Yes, including the free ones and with no attribution. The one limit is that you may not resell the files as assets or use them to build a commercial 3D asset generator; the licence page has the exact terms.