Your first window

Build a real script UI from scratch — sections, controls, callbacks and reading values back.

The installation page got a window on screen. This page builds something you would actually ship, and explains each piece as it goes.

Create the window

Every script starts with one Ember.new call. Everything else hangs off the window it returns.

Luau
local Ember = loadstring(game:HttpGet('https://rbx.lol/ember.lua'))()
 
local win = Ember.new({
    Title = "Bloxburg Helper",
    Subtitle = "v2.1",
    Icon = "house",
    Size = Vector2.new(720, 470),
    Keybind = Enum.KeyCode.RightControl,
})

Title and Subtitle show in the top-left. Keybind is what hides and shows the window — it defaults to RightShift. Every option is listed under Ember.new.

Add sections

A section is a tab in the left rail. Give it a name and an icon name.

Luau
local main    = win:Section("Main", "house")
local farming = win:Section("Farming", "zap")
local visuals = win:Section("Visuals", "eye")
local config  = win:Section("Settings", "settings")

The first section you create is the one shown when the window opens.

Put controls on them

Controls are methods on the section. Each takes one table of options.

Luau
main:Title({ Text = "MOVEMENT", Icon = "compass" })
 
main:Toggle({
    Text = "Infinite jump",
    Description = "Jump again while already in the air.",
    Default = false,
    Callback = function(on)
        infiniteJump = on
    end,
})
 
main:Slider({
    Text = "Walk speed",
    Min = 16,
    Max = 250,
    Default = 16,
    Suffix = " studs/s",
    Callback = function(value)
        local char = game.Players.LocalPlayer.Character
        if char and char:FindFirstChild("Humanoid") then
            char.Humanoid.WalkSpeed = value
        end
    end,
})

Read values back

Every stateful control returns a handle. Keep it if you need to read or change the value later.

Luau
local speed = main:Slider({
    Text = "Walk speed", Min = 16, Max = 250, Default = 16,
})
 
print(speed:Get())   --> 16
speed:Set(120)       --> moves the knob and fires the callback

The shape of every control#

Once you have seen one control you have seen all of them. They all take a single table, and they all understand the same handful of options:

OptionTypeDefaultWhat it does
TextstringThe label on the left. Every control has one.
DescriptionstringA smaller second line under the label. Use it instead of a comment nobody reads.
IconstringAn icon name shown before the label.
IconColorColor3Overrides the icon's colour. Defaults to the theme's.
IconSizenumberIcon size in pixels.
LayoutOrdernumberForces a position on the page. Rarely needed — order of creation is the default.
CallbackfunctionCalled when the value changes. The argument is the new value.
Savestring | booleanPersists this control to disk under the given key. See Saving settings.
FlatbooleanfalseDrops the card surface. Set automatically inside a group.

Beyond those, each control has its own options — a slider has Min/Max, a dropdown has Options. They are all on the individual control pages.

A complete script#

Everything above, plus saving, put together:

Luau
local Ember = loadstring(game:HttpGet('https://rbx.lol/ember.lua'))()
 
local win = Ember.new({
    Title = "Bloxburg Helper",
    Subtitle = "v2.1",
    Icon = "house",
    SaveLayout = true,
})
 
local state = { fly = false, speed = 16 }
 
local main = win:Section("Main", "house")
 
main:Title({ Text = "MOVEMENT", Icon = "compass" })
 
main:Toggle({
    Text = "Fly",
    Description = "Hold space to rise, shift to drop.",
    Save = "fly",
    Callback = function(on)
        state.fly = on
    end,
})
 
main:Slider({
    Text = "Walk speed",
    Min = 16, Max = 250, Default = 16,
    Suffix = " studs/s",
    Save = "speed",
    Callback = function(value)
        state.speed = value
        local char = game.Players.LocalPlayer.Character
        local hum = char and char:FindFirstChild("Humanoid")
        if hum then hum.WalkSpeed = value end
    end,
})
 
main:Separator()
 
main:Button({
    Text = "Reset character",
    ButtonText = "Reset",
    ButtonIcon = "refresh-cw",
    Danger = true,
    Callback = function()
        game.Players.LocalPlayer.Character:BreakJoints()
        win:Notify({ Title = "Reset", Text = "Character reset.", Icon = "check" })
    end,
})
 
local settings = win:Section("Settings", "settings")
settings:Dropdown({
    Text = "Theme",
    Options = Ember.ThemeNames(),
    Default = "Dark",
    Save = "theme",
    Callback = function(name) Ember.SetTheme(name) end,
})

That script remembers itself

Because three controls have a Save key and the window has SaveLayout = true, closing and re-running restores the toggle, the slider, the theme, and where the window was on screen.

Cleaning up#

When your script is done, tear the window down. This disconnects every event, stops every animation and removes the GUI:

Luau
win:Destroy()

If you need to run your own cleanup at the same time, register it:

Luau
win:OnDestroy(function()
    myConnection:Disconnect()
end)

See Lifecycle and cleanup for the full picture.