Vela’s import surface is small. One package has a public entry point, that entry point exports three
values and four types, and a second subpath exports the transformer you wire into tsconfig.json.
pnpm add vela-rbxtsnpm install vela-rbxtsyarn add vela-rbxtsbun add vela-rbxtsFrom vela-rbxts
import { defaultConfig, defineConfig, definePreset, plugin, createTransformer, type TailwindConfig, type TailwindConfigInput, type VelaPreset, type ThemeScreens, type VariantDefinition, type ClassValue, type StylableProps,} from "vela-rbxts";The plugin and variant types are re-exports of @vela-rbxts/config, so nothing needs to be
installed to reach them.
defineConfig
function defineConfig(input?: TailwindConfigInput): TailwindConfig;Takes an input-shaped theme object and resolves it against the built-in defaults. The argument is
optional, and defineConfig() returns a fresh object deep-equal to defaultConfig. It is injected
into vela.config.ts’s scope automatically, which is why stripping the import still works.
defaultConfig
const defaultConfig: TailwindConfig;The resolved built-in theme: 28 colour families, ten named radius keys plus a DEFAULT, and a
single spacing key. This is what Vela uses when no vela.config.ts is found.
createTransformer
function createTransformer( options?: RbxtscTransformerBridgeOptions,): RbxtscTransformerBridge;
// the returned bridge:// { name, getFileEligibility, shouldTransformFile, transformSource, transformFile }The rbxtsc host bridge, returning an object whose name is "@vela-rbxts/rbxtsc-host" plus the
eligibility predicates and the transform entry point. transformSource and transformFile are the
same function under two names.
You do not need this to use Vela — it exists for tooling that drives the transform itself.
createTransformer imported from vela-rbxts is the rbxtsc host bridge described above.
createTransformer on vela-rbxts/transformer is the TypeScript program transformer factory.
It is a completely different function with a different signature and a different job.
The one that goes in tsconfig.json is vela-rbxts/transformer. Pass the root package’s createTransformer to roblox-ts and nothing is transformed, with no error explaining why.
Types
| Prop | Type | Description |
|---|---|---|
| TailwindConfig | { theme: { colors: ThemeColors; radius: ThemeScale; spacing: ThemeScale } } | A fully resolved config — every scale present. What defineConfig returns and what the compiler consumes. |
| TailwindConfigInput | { theme?: { colors?; radius?; spacing?; extend?: { colors?; radius?; spacing? } } } | The authoring shape — everything optional, with the extend branch. What you pass to defineConfig. |
| VelaPreset | TailwindConfigInput | A shareable slice of configuration. Same shape as what you pass to defineConfig; definePreset() types one without resolving it, so it still merges as an input rather than as a finished config. Added in 0.13.0. |
| ClassValue | string | number | boolean | null | undefined | Record<string, boolean | null | undefined> | ClassValue[] | The accepted type of the className prop. Covers conditional dictionary and nested array forms, not just strings. |
| StylableProps | StylableProps<P = unknown> | Intersects your own props P with { className?: ClassValue }. Use it when a component of yours should forward className. |
The global augmentation
Importing vela-rbxts has a side effect: it declares
declare global { namespace React { interface Attributes { className?: ClassValue; } }}That augmentation is what makes className type-check on the host elements. It applies only once
the module is imported somewhere your program includes, typically a one-line .d.ts:
import "vela-rbxts";Several helpers exist in @vela-rbxts/config but are not re-exported from the root. The
functions are SHADES, PALETTE_DEFAULT_KEY, resolveThemeColors, mergeColorRegistry,
normalizeColorRegistry and normalizeColorScale. The types are Shade, PaletteKey,
PaletteDefaultKey, ThemeScale, ColorPalette, ColorValue, ColorScaleInput, ThemeColors,
ColorInputMap, ThemeConfig and ThemeConfigInput. Reach into @vela-rbxts/config directly, and
expect them to be less stable.
From vela-rbxts/transformer
A CommonJS module whose export is a callable program-transformer factory. It also carries
.createTransformer, .createRbxtsTailwindProgramTransformer and .default, all pointing at
itself, so every resolution style lands on the same function.
This is the value that goes in tsconfig.json:
{ "compilerOptions": { "plugins": [{ "transform": "vela-rbxts/transformer" }] }}The factory throws if roblox-ts does not hand it a TypeScript instance. Plugin options are in Configuration.
Published packages
| Package | What it is | Install directly? |
|---|---|---|
vela-rbxts | The entry point: config helpers, types, the global augmentation, the transformer subpath, and — since 0.11.0 — the vela CLI | Yes — this is the only one an app installs |
@vela-rbxts/compiler | The Rust compiler behind an N-API binding: transform, completions, hover, diagnostics, document colors | No, pulled in transitively |
@vela-rbxts/compiler-wasm | The same compiler built to WebAssembly, for hosts that cannot load the native addon — a browser, most usefully | Only if you are lowering classes outside Node |
@vela-rbxts/config | The theme schema, defineConfig, defaultConfig, and the color merge helpers | Only to reach a helper the root package does not re-export |
@vela-rbxts/core | Shared constants, including the supported host element tags | No — and nothing depends on it, so it never arrives transitively either |
@vela-rbxts/ir | The intermediate style representation shared between the compiler and its consumers | No |
@vela-rbxts/types | Shared TypeScript types | No |
@vela-rbxts/rbxtsc-host | The roblox-ts adapter: file eligibility, config discovery, diagnostic mapping | No |
@rbxts/vela-runtime-core | The target-neutral half of the runtime: resolution engine, theme normalization, rem math, rich text, margin and divide computation | No, pulled in by whichever host you emit for |
@rbxts/vela-runtime | The React runtime host every transformed module imports, as one ModuleScript the place shares | No — it ships with vela-rbxts |
@rbxts/vela-runtime-vide | The same host for Vide, imported instead when the project sets framework: "vide" | No — it ships with vela-rbxts |
@vela-rbxts/lsp | The language server binary and its platform packages | Only if you wire up a non-VS Code editor yourself |
vela-rbxts-lsp | The VS Code extension, published as a VSIX rather than to npm | Install from the marketplace as astra-void.vela-rbxts-lsp |
For almost every project: install vela-rbxts, add the transformer to tsconfig.json, install the
VS Code extension. Everything else arrives as a dependency.
The three @rbxts/vela-runtime* packages are the exception to “nothing of Vela’s reaches your
place”. They sit under the @rbxts scope because roblox-ts only resolves a package whose scope
directory is one of the project’s typeRoots. That is the one every roblox-ts project lists and
every Rojo template maps. So they need no tsconfig or Rojo change. But pnpm needs
nodeLinker: hoisted for the directory to be real,
covered in installation.
Each host declares its own UI library as an optional peer, which keeps a Vide project from installing React. The host you do not emit for is inert.
The root package also declares two bin entries, vela and vela-rbxts, pointing at the same CLI.
It lowers a source tree ahead of rbxtsc for projects that cannot register the transformer — see
the CLI reference.
All packages are versioned in lockstep at 0.13.0, the VS Code extension included. Never mix
versions across the @vela-rbxts/* scope. What changed in each release is in the
release notes.
Three subpaths beyond the roots are public. @vela-rbxts/rbxtsc-host/project-config exposes config
discovery and loading, which the VS Code extension uses to evaluate the config files it watches.
@vela-rbxts/compiler/native exposes the raw N-API binding. Both roots also declare
"./package.json" in their exports maps. The root package ships a schema.json describing the
config input shape — point a vela.config.json’s $schema at it.
Version requirements
No package declares an engines field except the VS Code extension, which requires VS Code
^1.90.0. No package declares any peerDependencies either. roblox-ts, TypeScript and React
are ordinary dependencies throughout, so nothing is checked at install time. You find out from a
build failure, and in the TypeScript case below, from one that does not mention versions.
What the project is developed and tested against:
| Tool | Version |
|---|---|
| Node | 24 (what CI runs) |
| TypeScript | 5.9.3, pinned exactly — see below |
| roblox-ts | ^3.0.0 |
@rbxts/react | ^17.3.7-ts.1 |
@rbxts/services | ^1.6.0 |
@vela-rbxts/rbxtsc-host resolves typescript from your project and calls into its API directly. TypeScript 7 moved enough of that API to break the call. A project on the current TypeScript fails on its first file with compiler-invocation-failed: Cannot read properties of undefined (reading 'Latest').
5.9.3 is the tested pin and 6.x also builds. roblox-ts’s own typescript does not save you — it pins =5.5.3 for itself, while Vela reads the one in your project.
@rbxts/services is a genuine runtime dependency: the runtime helper imports UserInputService and
Workspace from it to evaluate variants.
Prebuilt compiler binaries
The compiler ships N-API binaries for these targets:
x86_64-unknown-linux-gnux86_64-unknown-linux-muslaarch64-unknown-linux-gnuaarch64-apple-darwinx86_64-apple-darwinx86_64-pc-windows-msvc
There is no aarch64-pc-windows-msvc build and no linux arm64 musl build, so those two targets
need the compiler crate built from source.
Two things look like escape hatches and are not. The napi-rs loader ends with a WASI fallback
reaching for @vela-rbxts/compiler-wasm32-wasi, which is not published. It always falls through to
Cannot find native binding., whose advice to reinstall without a lockfile is misleading on a
platform that has no binary. And @vela-rbxts/compiler-wasm is a separate package with its own API,
not a drop-in fallback.
See also
- Configuration for the schema
defineConfigaccepts. - Diagnostics for what the transformer reports.