⚠️ This project is in active development. Expect bugs, breaking changes, and incomplete features! Use at your own risk and report issues.
Decillion is a TypeScript-to-Luau compiler plugin and runtime that brings Million.js-inspired UI performance to Roblox. It statically analyzes TSX/JSX UI code, splits it into memoized blocks, and generates highly efficient Luau code that minimizes unnecessary Roblox UI tree mutations.
- TypeScript/JSX to Luau Transpilation: Write declarative UI in Roblox-TS, compile to optimized Luau.
- Block Memoization: UI is split into blocks/components that only re-render if their props/state change, inspired by Million.js.
- Static Extraction: 100% static UI subtrees are built once, skipping reconciliation.
- Efficient Patch System: Only updates Roblox Instances that actually need to change.
- Roact-like API: Familiar, ergonomic API for Roblox-TS developers.
- Compile-Time Optimizations: Most work is done at compile time, not runtime.
npm i @decillion/runtime rbxts-transformer-decillionAdd to typeRoots in tsconfig.json:
{
"compilerOptions": {
"typeRoots": ["node_modules/@decillion", "node_modules/@types"]
}
}Add to node_modules in default.project.json:
{
"node_modules": {
"$className": "Folder",
"@rbxts": {
"$path": "node_modules/@rbxts"
},
"@decillion": {
"$path": "node_modules/@decillion"
}
}
}Add to plugins in tsconfig.json:
{
"compilerOptions": {
"plugins": [
{
"transform": "rbxts-transformer-decillion",
}
]
}
}// Write UI in Roblox-TS JSX
return (
<frame>
<textlabel Text={props.name} />
<uigridlayout />
{props.items.map(item => <textbutton Text={item} />)}
</frame>
)Decillion compiles this to Luau code that only updates changed parts of the UI tree.
- Write UI in Roblox-TS JSX
- Compiler plugin transforms source:
- Detects block boundaries
- Generates block memoization wrappers
- Emits
shouldUpdatelogic per block
- Output Luau code:
- Each block is a function/class
- UI tree is built with block skips
- Patches only what’s needed when state/props change
transformer/— TypeScript transformer, codegen, and analysis logicruntime/— Luau runtime helperssrc/— Example stories and benchmarksMILLION_REFERENCE/— Reference implementation from Million.jsdemo/— Demo project for Roblox
- Install dependencies:
npm install
- Build sub-projects:
npm run build
- Run tests:
npm run test - Try the demo:
See
demo/for example usage and integration.
- Compile-time first: Prefer static analysis and codegen over runtime logic.
- Blockify everything: Memoize UI blocks for maximum performance.
- Minimal mutations: Only update Roblox UI when absolutely necessary.
- Developer ergonomics: Keep APIs clear and easy to use.
Contributions are welcome! Please open issues or pull requests for bugs, features, or questions.
MIT License. See LICENSE for details.