Skip to content

Overview ​

Flux is a reactive UI library for Luau. State updates batch once per frame, and only the Instance properties that actually change get touched.

luau
local count = Flux.signal(0)
local stats = Flux.store({ kills = 0, deaths = 0 })

local function CounterButton()
	return Flux.new "TextButton" {
		Size = UDim2.fromOffset(200, 50),
		BackgroundColor3 = Color3.fromRGB(0, 120, 255),
		Text = function()
			return `Clicks: {count()} | K/D: {stats.kills}/{stats.deaths}`
		end,
		Activated = function()
			count(count() + 1)
			stats.kills += 1
		end,
	}
end

Core Principles ​

1. Lazy & Frame-Batched ​

Dormant computations sleep with zero subscriptions until something observes them. When bound to the UI or an Effect, updates batch once per frame (RunService.PreRender on the client, Heartbeat on the server) and run in dependency order before effects fire. If a computed value produces the same result, downstream bindings don't wake up.

2. Direct Property Updates ​

Flux doesn't build or diff a virtual DOM tree. State changes flow straight to the property bindings that read them. When a player's health changes, only the health bar's Size updates.

3. Run-Once Components ​

Components in Flux are plain Luau functions that run once to create Instances and attach reactive bindings. After mounting, the component function never runs again. Only the individual property bindings re-run when their dependencies change.

4. Strictly Typed UI ​

Flux.new and Flux.edit build and wire up Roblox instances in one table with --!strict autocomplete for properties, events, and children. Reactive nodes also overload __call and standard operators (count + 1, `Clicks: {count}`), so expressions stay short.

Batteries Included ​

See Getting Started to install Flux and build your first component.