This plugin generates type-safe glTF file representations in TypeScript and optimizes the loading and bundling of models in web projects, while being bundler-agnostic (Vite, Rollup, Webpack, esbuild, Rspack, ...).
This plugin scans all model files in the project source, deconstructs the glTF JSON representation, and places generated type files next to them. It creates three.js types and uses it internally to parse the glTF files, including modifications like path resolutions etc.
With this plugin you get:
- ✅ Type safe glTF file representations with correct inner three.js types
like
Object3D
,Mesh
, etc..- ❗ Currently, we primarily support and generate the three.js types
Object3D
,Group
, andMesh
. Support for generating types for lights, cameras, materials, and other components is not yet implemented. See and subscribe to Issue #22 to stay updated on this development and be notified when these features are added.
- ❗ Currently, we primarily support and generate the three.js types
- ✅ Building will fail if a model is missing due to type-safe workflow.
- ✅ Only the used models are bundled in the final product, not all included in your dev project.
⚠️ Detects and handles Draco Compression during type generation automatically, see Draco Compression handling below for more information.- ✅ Works with glTF Seperate (
.gltf
+.bin
+ textures), glTF Embedded (only.gltf
) and glTF Binary (.glb
) files, see glTF Versions and Representations below for more information. - ✅ ESM ready.
⚠️ Build tool & bundler agnostic thanks to Unplugin, so use it with your favorite one, but see chapter Build Tool, Bundler and Framework Compatibility below for more details like compatibility or known problems:- ✅ Use it with your favorite framework built on top of the listed build tools above, such as:
If you like this plugin and want to support us, we would be very happy to see you as a sponsor on GitHub ❤️
You can find the Sponsor
button on the top right of the
GitHub project page.
Thanks a lot for the support <3
For development-related information, including setup instructions for contributors, please refer to the
Developer README README-dev.md
.
-
Install with your package manager (we use pnpm and recommend it):
# choose your package manager pnpm add -D @todde.tv/gltf-type-toolkit npm install --save-dev @todde.tv/gltf-type-toolkit yarn add --dev @todde.tv/gltf-type-toolkit bun add --dev @todde.tv/gltf-type-toolkit
-
Extend your
.gitignore
file to exclude generated files:# Generated glTF model files *.gltf.d.ts *.gltf.js
-
Add the plugin to your build tool, for example with Vite:
// vite.config.ts import gltf from '@todde.tv/gltf-type-toolkit/vite.js' export default defineConfig({ plugins: [ gltf({ // Plugin options are defined in: `@todde.tv/gltf-type-toolkit/src/entries/types.ts` /** * Module that provides an instance of a three.js GLTFLoader as the default export. */ // customGltfLoaderModule: '@/utils/customGltfLoader.ts', /** * Print extra information. */ // verbose: true, }), ], })
The plugin will run on:
- on dependency installation
- on dev server start
- on project build
Here's an example of how to use the plugin. You can customize this example to suit your needs, such as saving models to different folders, changing paths, or adjusting how the model is handled after import.
-
Install the plugin (See Installation above).
-
Add a model to your project, here in the project source under
@/assets/models
. We copy the following in it:MyModel.gltf
The glTF JSON representation that describes the model.MyModel.bin
The binary file of the model, compressed with the Draco Compression.MyModel-texture1.png
A texture that the model uses.MyModel-texture2.png
A second texture that the model uses.
-
Start your dev to generate all files. With our example model we get:
@/assets/models/MyModel.gltf @/assets/models/MyModel.bin @/assets/models/MyModel-texture1.png @/assets/models/MyModel-texture2.png +@/assets/models/MyModel.gltf.d.ts <- the typing +@/assets/models/MyModel.gltf.js <- actual code with node get helper function and model graph representation
Alternatively, you can run the script
gltf-codegen
supplied by the package to manually create those files. More details at Binary scripts. -
Import the type safe model in your code and use it, e.g.:
// yourCustomFile.ts import { getNode, MyModelScene } from '@/assets/models/MyModel.gltf.js' // load the main model, so to say the wrapper in the scene const model = await getNode(MyModelScene) // load a child const innerModel = await getNode(MyModelScene.someInnerModel) // work with a model innerModel.receiveShadow = true innerModel.castShadow = true
Thanks to Unplugin, we support a wide variety of build tools and bundlers, resulting in the following compatibility in our project:
(Legend: 🟢 Tested & Supported | 🟡 Not Yet Tested | 🔴 Not Supported)
Build Tool | Status | Note |
---|---|---|
esbuild | 🟢 | |
Nuxt3 | 🟢 | |
Rolldown | 🟢 | |
Rollup | 🟢 | |
Rspack | 🟢 | |
Vite | 🟢 | |
Astro | 🟡 | |
Farm | 🔴 | Tested & model files are not emitted (see Issue #27). Contributions welcome! ❤️ |
Webpack | 🔴 | Tested & model files are borked (see Issue #30). Contributions welcome! ❤️ |
(Legend: 🟢 Tested & Supported | 🟡 Partially Supported | 🔴 Not Supported)
glTF Version | File Representation | Status | Note |
---|---|---|---|
glTF 1.0 | Any | 🔴 | glTF 2.0 was introduced in 2017 with major improvements. Avoid using the outdated glTF 1.0 standard in your projects. |
glTF 2.0 | Separate (.gltf + .bin + textures) |
🟢 | Recommended! Offers better performance, version control, caching, transferability, and debugging. |
glTF 2.0 | Embedded (only .gltf ) |
🟢 | Assets are embedded directly into the .gltf file as base64 encoded data: sources within the uri fields, making single-file management simpler. |
glTF 2.0 | Binary (.glb ) |
🟡 | Currently, only works with models that contain all referenced files in the binary chunk without external file references. Contributions welcome! ❤️ |
This plugin can handle the Draco Compression during the type generation and handles your draco compressed models just fine.
On runtime though, you have to handle the draco compression yourself depending on your architecture and setup.
You can do this by creating a custom gltfLoader
and pass it in the customGltfLoaderModule
prop whn initializing
the plugin. In this loader, you can handle the draco loader.
For example with Vite:
// vite.config.ts
import gltf from '@todde.tv/gltf-type-toolkit/vite.js'
export default defineConfig({
plugins: [
gltf({
customGltfLoaderModule: '@/utils/gltfLoader.ts',
}),
],
})
// @/utils/gltfLoader.ts
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
const dracoLoader = undefined // use an existing draco loader or create a custom one by extending `DRACOLoader`
const gltfLoader = new GLTFLoader().setDRACOLoader(dracoLoader)
export default gltfLoader
In addition to the commands in the scripts
section of the package.json
, this plugin also provides binary scripts.
Run them by adding this plugin to your project, be sure to have the dependencies installed and then
add npx
or pnpx
before the commands.
This script generates types and runtime code for all models found in DIR
and sub-directories. DIR
defaults to
the current directory.
Run gltf-codegen --help
for more options and details.
On runtime it runs the default glTF loader mechanics of three.js under the hood. So, there is no extra layer of processing and therefore correct objects that three.js would give you when importing it yourself in your application.
To achieve this, we use patched versions of DRACOLoader
and GLTFLoader
to be able to run it in CLI because
originally you can only use them in a browser runtime.
So we do not parse the glTF JSON file ourself but work with the representation after the
three.js parsing. For code completion and for working with the
model graph, we store the paths in the graph by caching the child indices in the children
array from each
object. With this, we can O(1) look up what the user requests without the need of traversing - neither depth first
(default approach from three.js), nor breadth first.
One of the biggest challenges was making the plugin build tool agnostic bc not every build tool handles inner path references the same. Therefore, we have to reconstruct the buffers that link the glTF file with the binary and textures by text string & replace - kinda hacky, but reliable and the additional runtime is only performed in dev and build, not in the production runtime.
If you have problems, maybe one of the following will help:
- Delete your build output folder (maybe some old builds copied model files in there and our plugin is now scanning them).
- We currently do not provide a watcher. Restart your dev environment when changing model files.
Project founder & head of project:
Honorable mentions to people that helped this project:
- Andreas Fehn as contributor who helped incredible with the project. Thank you mate, you rock <3
Respectable mentions to projects that helped this project:
- zlig (zen-landscape-idle-game): A Japanese zen-inspired idle browser game that
showcases lightweight web technologies like
Vue
andThree.js
to create fully browser-based games. The idea and initial implementation of this plugin @todde.tv/gltf-type-toolkit originated during the development of zlig, where we required type-safe glTF representations to enable faster and more reliable development.
Used programs/ softwares, services and dependencies - besides the ones in ./package.json
:
- GitHub Copilot was used in private mode for programming questions.
Used assets/ materials including images and 3D models:
- [currently none]
Copyright (c) 2025-PRESENT Thorsten Seyschab
This project is licensed under the MIT License, see the LICENSE.md
file for more details.