Back to the catalog

CookiesLib

CookiesLib.lua · v3.5.0

The UI library Cookies Hub is built with. Draggable windows, tabs, 20 elements, 8 live themes, notifications, dialogs and configs, for PC and mobile.

On this page

Try it before you use it

Paste this line into your executor and a demo menu opens with every element wired to notifications. You don't have to write anything.

CookiesDemo.lua
loadstring(game:HttpGet("https://raw.githubusercontent.com/Lilwero20/CookiesLib/main/CookiesDemo.lua"))()
TabWhat you can try
Inicio (Home)Welcome notice, live stats (FPS, ping, players, time), paragraph, copy field and image.
Controles (Controls)Buttons (normal, primary, with confirmation, in columns, disabled), toggles with keys, sliders, text boxes, keybinds and dropdowns.
Avanzado (Advanced)Pill selector, range slider, number fields, progress bar, color picker, alerts and scrolling sections.
Avisos (Notices)The 4 notification types, one that updates itself, dialogs, watermark, keybind list and badges.
Personalizar (Customize)Theme, accent color, title, window size and the demo Key System.
Ajustes (Settings)The library's settings tab: theme, accent, scale, menu key, configs and auto-load.

The demo menu is in Spanish. The key for the demo Key System is COOKIES-DEMO. RightShift hides or shows the menu and Ctrl+F opens search.

Installation

CookiesLib loads from GitHub in one line. It works in any executor that has loadstring and game:HttpGet:

lua
local Library = loadstring(game:HttpGet("https://raw.githubusercontent.com/Lilwero20/CookiesLib/main/CookiesLib.lua"))()

Every other executor function is optional. If one is missing, the library adapts:

FunctionUsed forIf it's missing
gethuiPlacing the UI in a hidden containerUses PlayerGui
writefile, readfile, isfolder, makefolderConfigs, saved state and remembered keyDisabled
listfilesListing configsThe list is empty
delfileDeleting configs and the saved keyDeleting is disabled
setclipboardCopy fields and linksShows the text
requestOpening the Discord inviteOnly copies the link

Quick start

A window with one tab, one section and a toggle with a key. It's the starting point for any hub:

lua
local Library = loadstring(game:HttpGet("https://raw.githubusercontent.com/Lilwero20/CookiesLib/main/CookiesLib.lua"))()

local Window = Library:CreateWindow({
    Title = "Cookies Hub",
    ToggleKey = Enum.KeyCode.RightShift,
})

local Main = Window:CreateTab("Main", "H")
local Section = Main:CreateSection("Combat")

Section:AddToggle({
    Name = "Auto Farm",
    Flag = "AutoFarm",
    Default = false,
    Keybind = "F",
    Callback = function(value)
        print("Auto Farm:", value)
    end,
})

Window:CreateSettingsTab()

When you run it:

  1. 1The intro plays (logo and loading bar; one click skips it) and the window appears.
  2. 2The floating button with the logo appears. One click opens or closes the window, and it can be dragged.
  3. 3RightShift shows or hides the window and Ctrl+F opens search.
  4. 4Next time you run it, the window comes back with the same size, position, tab and theme.

Window

Library:CreateWindow creates the main window. Every option is optional:

lua
local Window = Library:CreateWindow({
    Title = "Cookies Hub",
    Subtitle = "v1.0",
    Logo = "rbxassetid://76143769732706",
    Width = 740, Height = 500,
    ToggleKey = Enum.KeyCode.RightShift,
    ConfigFolder = "CookiesHub",

    Intro  = { Enabled = true, Duration = 2 },
    Notify = { Duration = 4, Position = "TopRight" },
    Theme  = { Accent = Color3.fromRGB(245, 194, 12) },
})
OptionDefaultWhat it does
Title / Subtitle"Cookies Hub" / versionTop bar texts
LogoCookies logoTitle and floating button image. false removes it
Width, Height740, 500Initial size
ToggleKeyRightShiftKey to show or hide
FloatingButtontrueFloating button to open the window (important on mobile)
Resizable / DraggabletrueResize from the corner and drag from the top bar
SearchabletrueMagnifier button and global search
ShowProfiletrueCard with avatar and name in the sidebar
RememberLayouttrueRemembers size, position, tab and theme between runs
ConfigFolder"CookiesHub"Folder for configs and saved state
CompactBelow600Below this width the sidebar shows icons only

Intro

The window stays hidden while the intro plays. Configure it with Intro = { ... }: Enabled, Duration (seconds), Skippable, OncePerSession (doesn't repeat when re-running in the same game), Logo and ShowBar.

Methods

lua
Window:Toggle()   Window:Show()   Window:Hide()
Window:Minimize()
Window:Resize(800, 520)
Window:SetUIScale(1.2)
Window:ResetPosition()
Window:ResetLayout()

Window:SetTitle("New title")
Window:SetSubtitle("Text")
Window:SetToggleKey(Enum.KeyCode.K)
Window:SetFloatingButton(false)

Window:AddTabCategory("Combat")
Window:GetTab("Main")
Window:SelectTab("Main")

Window:Destroy()

Stop your loops on unload

When the player presses Unload UI in Settings, OnUnload tells you so you can stop your loops:

lua
local running = true
Window:OnUnload(function() running = false end)

task.spawn(function()
    while running do
        task.wait(0.1)
    end
end)

Tabs

Create them with a name and an icon, or with a table of options. The first tab you create opens automatically.

lua
local Main = Window:CreateTab("Main", "H")

local Combat = Window:CreateTab({
    Name = "Combat",
    Icon = icon("swords"),
    IconColor = Color3.fromRGB(245, 194, 12),
    Columns = 2,
    Badge = "NEW",
})
OptionDefaultWhat it does
Iconfirst letterLucide icon, asset id or a letter (see Icons)
IconColoraccentIcon color while the tab is active
Columns2Section columns (1 on narrow screens)
BadgenilLabel next to the name, like "NEW" or a number

Use Window:AddTabCategory("Name") to add a text separator to the sidebar, like General or Automation.

lua
Combat:Select()
Combat:SetName("Fight")
Combat:SetIcon(icon("flame"))
Combat:SetBadge(3)
Combat:SetBadge(nil)
Combat:SetVisible(false)
Combat:ScrollToTop()
Combat:Destroy()

Icons

Tabs and sections accept Lucide icons through lucide-roblox. Use size 48; the helper with pcall avoids errors when a name doesn't exist:

lua
local Lucide = loadstring(game:HttpGet(
    "https://github.com/latte-soft/lucide-roblox/releases/latest/download/lucide-roblox.luau"
))()

local function icon(name)
    local ok, asset = pcall(Lucide.GetAsset, name, 48)
    return ok and asset or nil
end

local Home   = Window:CreateTab("Home", icon("home"))
local Combat = Window:CreateTab("Combat", icon("swords"))

local Aimbot = Combat:CreateSection({
    Name = "Aimbot",
    Icon = icon("crosshair"),
})
`Icon` valueResult
icon("home")Lucide icon (recommended)
123456789Asset id → rbxassetid://123456789
"rbxassetid://123"Asset id as text
"H"Letter inside a box (max. 2 characters)
nilTabs: first letter of the name. Sections: colored dot

lucide-roblox uses old Lucide names: "home" instead of "house", "line-chart" instead of "chart-line".

Sections

Sections group elements inside a tab. They spread across the columns on their own, or you can choose where each one goes:

lua
Tab:CreateSection({ Name = "Left", Column = "Left" })
Tab:CreateSection({ Name = "Right", Column = "Right" })
Tab:CreateSection({ Name = "Wide", Full = true })
Tab:CreateSection("Name only")

They collapse when you click their header. Options and methods:

lua
local Section = Tab:CreateSection({
    Name = "Aimbot",
    Icon = icon("crosshair"),
    Color = Color3.fromRGB(245, 194, 12),
    Minimized = true,
    Collapsible = true,
    MaxHeight = 220,
})

Section:Minimize()   Section:Expand()   Section:Toggle()
Section:SetTitle("Another name")
Section:OnToggle(function(open) print(open) end)

MaxHeight makes the content scroll past that height, and Minimized = true makes it start collapsed.

Several columns inside a section

lua
local Grid = Tab:CreateSection({ Name = "Grid", Columns = 2 })
Grid:AddButton({ Name = "A" })
Grid:AddButton({ Name = "B", Column = 2 })

local left, right = Grid:AddColumns(2)
left:AddButton({ Name = "Left" })
right:AddButton({ Name = "Right" })

Elements

Every element is created from a section with Section:AddXxx({ ... }). Elements with a Flag are saved in configs.

ElementUsed forSaved
AddButtonRunning an action—
AddToggleOn / off, with an optional keyYes
AddSliderPicking a number by draggingYes
AddRangeSliderPicking a min – max rangeYes
AddNumberNumber with − / + buttonsYes
AddDropdownPicking one or more optionsYes
AddPlayerDropdownPicking players in the serverOptional
AddSegmentedPicking between 2–5 options with pillsYes
AddKeybindAssigning a keyYes
AddTextBoxTyping text or numbersYes
AddColorPickerPicking a colorYes
AddProgress, AddStatShowing progress or a value—
AddAlert, AddCopyField, AddImageNotices, copyable text and images—
AddLabel, AddParagraph, AddDivider, AddSpacerText and layout—

Common options and methods

Almost all of them accept Name, Flag, Callback, Description (text under the name and tooltip), Tooltip, Visible and Enabled. They share these methods:

lua
element:Set(value, silent)
element:Get()
element:SetText("New name")
element:SetVisible(true)
element:SetEnabled(false)
element:SetCallback(function(value) end)
element:OnChanged(function(value) end)
element:Destroy()

Every Callback runs with task.spawn: an error in your function won't break the UI. :Set(value, true) changes the value without running the callback.

Button

Style can be Default, Primary or Danger. With Confirm = true the first click asks for a second click within 2.5 seconds; great for dangerous actions.

lua
local btn = Section:AddButton({
    Name = "Run",
    Description = "Optional text",
    Style = "Primary",
    Confirm = true,
    Callback = function()
        print("clicked")
    end,
})

btn:Click()

Toggle

iOS-style switch or checkbox (Style = "Checkbox"). With Keybind, a chip with the key shows up in the same row:

lua
local esp = Section:AddToggle({
    Name = "ESP",
    Description = "Shows players",
    Default = false,
    Style = "Switch",
    Keybind = { Default = "F", Mode = "Toggle", Flag = "ESPKey" },
    Flag = "ESP",
    Callback = function(on)
        print("ESP:", on)
    end,
})

esp:Set(true)   esp:Toggle()   esp:Get()
Key `Mode`What it does
Toggle (default)Each press turns it on or off
HoldOn only while the key is held

To change the key, the player clicks the chip and presses another one. Esc cancels and Backspace removes it.

Slider

The number box on the right can be typed into too. Decimals come from Increment (0.25 → 2 decimals). The callback runs while dragging.

lua
local speed = Section:AddSlider({
    Name = "Speed",
    Min = 16, Max = 100, Increment = 1, Default = 16,
    Suffix = " ws",
    Flag = "Speed",
    Callback = function(v)
        local h = game.Players.LocalPlayer.Character:FindFirstChildOfClass("Humanoid")
        if h then h.WalkSpeed = v end
    end,
})

speed:Set(50)   speed:SetRange(0, 200)

RangeSlider

Two handles to pick a range. The value is a { min, max } table; if you pass the values backwards they get sorted.

lua
local levels = Section:AddRangeSlider({
    Name = "Enemy level",
    Min = 1, Max = 100,
    Default = { 10, 60 },
    Flag = "LevelRange",
    Callback = function(v)
        print(v[1], v[2])
    end,
})

levels:Set({ 20, 80 })

Number

Number field with − and +. Holding a button repeats the change. Min and Max are optional.

lua
local amount = Section:AddNumber({
    Name = "Amount",
    Min = 0, Max = 99, Increment = 1, Default = 5,
    Suffix = "x",
    Flag = "Amount",
    Callback = function(v) end,
})

amount:Set(10)

PlayerDropdown

A dropdown with the server's players that updates itself when someone joins or leaves. The value is the name; GetPlayer() returns the Player object. It isn't saved in configs unless you set Savable = true.

lua
local victim = Section:AddPlayerDropdown({
    Name = "Player",
    IncludeSelf = false,
    Callback = function(name)
        print("Picked:", name)
    end,
})

local player = victim:GetPlayer()

Segmented

Pills with a sliding indicator. Better than a dropdown when there are 2 to 5 options.

lua
local mode = Section:AddSegmented({
    Name = "Mode",
    Options = { "Safe", "Normal", "Fast" },
    Default = "Normal",
    Flag = "Mode",
    Callback = function(v) end,
})

mode:Set("Fast")

Keybind

lua
local aim = Section:AddKeybind({
    Name = "Aim key",
    Default = Enum.KeyCode.E,
    Mode = "Hold",
    Flag = "AimKey",
    Callback = function(holding) end,
    Changed = function(key) end,
})

aim:Set(Enum.KeyCode.Q)   aim:SetMode("Toggle")
`Mode``Callback` receives
PressNothing; it runs once per press
Toggletrue / false, alternating on each press
Holdtrue on press and false on release

Changed runs when the player rebinds the key. Keys don't fire while the player is typing in a text box.

TextBox

With Numeric = true the value is a number. By default the callback runs on Enter or when the box loses focus (CallbackOnBlur).

lua
local msg = Section:AddTextBox({
    Name = "Message",
    Placeholder = "Type here...",
    Default = "",
    Numeric = false,
    Flag = "Msg",
    Callback = function(text) end,
})

ColorPicker

Saturation and brightness picker, hue bar, hex box and optional preset colors.

lua
local tint = Section:AddColorPicker({
    Name = "ESP color",
    Default = Color3.fromRGB(245, 194, 12),
    Presets = { Color3.fromRGB(255, 80, 80), Color3.fromRGB(80, 200, 120) },
    Flag = "ESPColor",
    Callback = function(c) end,
})

tint:SetHex("#FF0000")   tint:GetHex()

Elements for showing information

Progress

Read-only progress bar. With ShowPercent = false it shows the raw value.

lua
local bar = Section:AddProgress({ Name = "Loading", Min = 0, Max = 100, Default = 40 })
bar:Set(75)

Stat

A row with the name on the left and the value on the right: money, level, farm status…

lua
local money = Section:AddStat({ Name = "Money", Value = "$0", Color = Color3.fromRGB(96, 196, 124) })

money:Set("$1500")
money:SetColor(Color3.fromRGB(224, 92, 92))

Alert

A highlighted notice. Type can be Info, Success, Warning or Error, and the content accepts RichText.

lua
local warning = Section:AddAlert({
    Type = "Warning",
    Title = "Careful",
    Content = "This option can get you <b>kicked</b>.",
})

warning:Set("New title", "New content")
warning:SetType("Success")

CopyField

Text (a link, a code) with a Copy button that puts it on the clipboard.

lua
Section:AddCopyField({
    Name = "Discord",
    Text = "discord.gg/cookieshub",
    Callback = function(text) end,
})

Image

lua
Section:AddImage({
    Image = 76143769732706,
    Height = 120,
    ScaleType = Enum.ScaleType.Fit,
    Caption = "Text below",
})

Label, Paragraph, Divider and Spacer

lua
local info = Section:AddLabel("Info text")
Section:AddLabel({ Text = "Notice with <b>bold</b>", RichText = true, Color = Color3.fromRGB(232, 148, 58) })

local about = Section:AddParagraph({ Title = "Title", Content = "Longer description" })
about:Set("New title", "New content")

Section:AddDivider()
Section:AddDivider("Options")
Section:AddSpacer(8)

Flags and configs

An element with a Flag is registered in Library.Flags and goes into configs. You can read or change it from anywhere in your script:

lua
Library:GetFlag("ESP")
Library:SetFlag("ESP", true)
Library:GetObject("ESP")

Window:SaveConfig("my-config")
Window:LoadConfig("my-config")
Window:DeleteConfig("my-config")
Window:GetConfigs()

Auto-load

A config marked as auto-load is applied by itself every time the player runs the script:

lua
Window:SetAutoload("my-config")
Window:GetAutoload()
Window:LoadAutoloadConfig()
  • Configs are JSON files inside ConfigFolder.
  • LoadConfig runs each element's callback, as if the player had changed it.
  • Progress, Stat, CopyField and PlayerDropdown aren't saved.
  • Library.Flags is global: use unique Flag names if you have several windows.

Create the settings tab at the end of your script so auto-load finds all your flags. If you don't use it, call Window:LoadAutoloadConfig() once the menu is built.

Notifications

Type can be Info, Success, Warning or Error, each with its own icon. Duration = 0 keeps it open. The returned notification can be updated:

lua
Window:Notify({
    Title = "Cookies Hub",
    Content = "Config <b>loaded</b>",
    Type = "Success",
    Duration = 4,
})

local download = Window:Notify({ Title = "Downloading...", Content = "0%", Duration = 0 })
for i = 1, 10 do
    task.wait(0.3)
    download:SetContent(i * 10 .. "%")
end
download:SetTitle("Done")
  • One click closes it (and runs its Callback, if it has one).
  • Hovering pauses the timer.
  • Position and limit: Notify = { Position = "TopRight", Max = 5 } when creating the window.

Dialogs

A modal window to confirm actions. Without Buttons it shows Cancel and Confirm; with Buttons you can add any you like, each with its own Style.

lua
Window:Dialog({
    Title = "Teleport?",
    Content = "You will go to the final boss.",
    Callback = function()
        print("confirmed")
    end,
})

Window:Dialog({
    Title = "Save changes",
    Content = "You have unsaved changes.",
    Buttons = {
        { Name = "Cancel" },
        { Name = "Discard", Style = "Danger", Callback = function() end },
        { Name = "Save", Style = "Primary", Callback = function() end },
    },
})

Dismissible = false stops it from closing when clicking outside.

Watermark and keybind list

Floating panels that can be dragged and remember their position. The list shows the toggles' keys and lights up while they're active.

lua
local wm = Window:CreateWatermark({ Text = "Cookies Hub", ShowFPS = true, ShowPing = true, ShowTime = true })
wm:SetText("My Hub")   wm:SetVisible(false)

local binds = Window:CreateKeybindList({ Title = "Keybinds", ShowAll = false })
binds:Destroy()

Themes and colors

Themes apply live: the whole interface repaints without being rebuilt. There are 8 built in: Cookies, Mocha, Midnight, Ocean, Matcha, Strawberry, Grape and Graphite.

lua
Library:SetTheme("Midnight")
Library:SetAccent(Color3.fromRGB(170, 120, 255))
Library:SetTheme({ Accent = Color3.fromRGB(255, 80, 80) })

local themes = Library:GetThemes()
local current = Library.CurrentTheme

You can also pick it when creating the window: Library:CreateWindow({ Theme = "Ocean" }).

If the player picks a theme or accent in Settings, their choice is saved and takes priority over the script's theme.

Create your own theme

lua
Library:AddTheme("Lava", {
    Background = Color3.fromRGB(20, 10, 8),  Panel = Color3.fromRGB(30, 14, 10),
    Element = Color3.fromRGB(38, 18, 12),    Row = Color3.fromRGB(48, 22, 14),
    RowHover = Color3.fromRGB(60, 28, 18),   Input = Color3.fromRGB(16, 8, 6),
    Stroke = Color3.fromRGB(90, 40, 24),     Outline = Color3.fromRGB(10, 5, 4),
    Accent = Color3.fromRGB(255, 110, 40),
    Text = Color3.fromRGB(250, 236, 228),    Muted = Color3.fromRGB(190, 150, 130),
    Dim = Color3.fromRGB(130, 100, 86),
    Success = Color3.fromRGB(96, 196, 124),  Warning = Color3.fromRGB(232, 148, 58),
    Error = Color3.fromRGB(224, 92, 92),
})

Library:SetTheme("Lava")

The new theme also appears in the Settings picker. Use a different color for each key: if two keys share the same color, the library can't tell which one to repaint when the theme changes.

Global settings

Library:Configure changes the defaults for every window you create afterwards: animations, sizes, notifications, tooltips, intro…

lua
Library:Configure({
    Animations = true,
    AnimationSpeed = 1,

    Window   = { Width = 740, Height = 500, Shadow = true, RememberLayout = true, UIScale = 1 },
    Tab      = { Columns = 2, Padding = 12, Gap = 10, IconSize = 20 },
    Section  = { Collapsible = true, Minimized = false },
    Element  = { Height = 32, Corner = 7 },
    Notify   = { Duration = 4, Position = "BottomRight", Max = 5 },
    Tooltip  = { Enabled = true, Delay = 0.55 },
    Dropdown = { SearchThreshold = 7, MaxVisible = 5 },
    Intro    = { Enabled = true, Duration = 2, OncePerSession = true },
})

Settings tab

Window:CreateSettingsTab() creates a ready-to-use tab:

  • Appearance: theme, accent color and UI scale.
  • Interface: menu key, floating button, animations, tooltips, watermark, keybind list, Reset Layout and Unload UI.
  • Configs: save, load, delete and mark a config as auto-load.
lua
Window:CreateSettingsTab("Settings", icon("settings"))

With RememberLayout = true the library saves the size, position, open tab, theme and menu key to ConfigFolder/_ui_state.txt. Window:ResetLayout() deletes it.

Full example

An example hub with icons, live stats, sliders, toggles with keys, dialogs, a sample ESP tab and the settings tab. Copy it and run it as is:

MyHub.lua
local Library = loadstring(game:HttpGet("https://raw.githubusercontent.com/Lilwero20/CookiesLib/main/CookiesLib.lua"))()
local Lucide = loadstring(game:HttpGet(
    "https://github.com/latte-soft/lucide-roblox/releases/latest/download/lucide-roblox.luau"
))()

local Players = game:GetService("Players")
local LocalPlayer = Players.LocalPlayer

local function icon(name)
    local ok, asset = pcall(Lucide.GetAsset, name, 48)
    return ok and asset or nil
end

local Window = Library:CreateWindow({
    Title = "My Hub",
    Subtitle = "Demo",
    ToggleKey = Enum.KeyCode.RightShift,
    Theme = "Cookies",
    Notify = { Position = "TopRight" },
})

local running = true
Window:OnUnload(function() running = false end)

Window:AddTabCategory("General")
local Home = Window:CreateTab("Home", icon("home"))

local Info = Home:CreateSection({ Name = "Welcome", Full = true })
Info:AddAlert({ Type = "Info", Title = "My Hub", Content = "Press <b>RightShift</b> to hide the menu." })

local Stats = Home:CreateSection({ Name = "Live", Icon = icon("line-chart"), Column = "Left" })
local sPlayers = Stats:AddStat({ Name = "Players", Value = #Players:GetPlayers() })
local sTime = Stats:AddStat({ Name = "Time", Value = os.date("%H:%M:%S") })

local Links = Home:CreateSection({ Name = "Community", Icon = icon("users"), Column = "Right" })
Links:AddCopyField({ Name = "Discord", Text = "discord.gg/xxxxxx" })

task.spawn(function()
    while running do
        sPlayers:Set(#Players:GetPlayers())
        sTime:Set(os.date("%H:%M:%S"))
        task.wait(1)
    end
end)

Window:AddTabCategory("Game")
local Player = Window:CreateTab({ Name = "Player", Icon = icon("user"), Badge = "NEW" })

local Move = Player:CreateSection({ Name = "Movement", Icon = icon("footprints"), Column = "Left" })
Move:AddSlider({
    Name = "Walk speed", Min = 16, Max = 200, Default = 16, Suffix = " ws", Flag = "WalkSpeed",
    Callback = function(v)
        local h = LocalPlayer.Character and LocalPlayer.Character:FindFirstChildOfClass("Humanoid")
        if h then h.WalkSpeed = v end
    end,
})
Move:AddSegmented({ Name = "Mode", Options = { "Safe", "Normal", "Fast" }, Default = "Normal", Flag = "Mode" })
Move:AddToggle({
    Name = "Infinite jump", Flag = "InfJump",
    Keybind = { Default = "J", Flag = "InfJumpKey" },
    Callback = function(on)
        Window:Notify({ Title = "Infinite jump", Content = on and "On" or "Off", Type = on and "Success" or "Info" })
    end,
})

local Tp = Player:CreateSection({ Name = "Teleport", Icon = icon("map-pin"), Column = "Right" })
local target = Tp:AddPlayerDropdown({ Name = "Target" })
Tp:AddButton({ Name = "Go to target", Primary = true, Callback = function()
    local p = target:GetPlayer()
    if not p then
        return Window:Notify({ Title = "Teleport", Content = "Pick a player first", Type = "Warning" })
    end
    Window:Dialog({
        Title = "Teleport?",
        Content = "You will go next to <b>" .. p.DisplayName .. "</b>.",
        Callback = function()
            local mine = LocalPlayer.Character and LocalPlayer.Character:FindFirstChild("HumanoidRootPart")
            local theirs = p.Character and p.Character:FindFirstChild("HumanoidRootPart")
            if mine and theirs then mine.CFrame = theirs.CFrame * CFrame.new(0, 0, 3) end
        end,
    })
end })
Tp:AddButton({ Name = "Reset character", Style = "Danger", Confirm = true, Callback = function()
    local h = LocalPlayer.Character and LocalPlayer.Character:FindFirstChildOfClass("Humanoid")
    if h then h.Health = 0 end
end })

local Visuals = Window:CreateTab("Visuals", icon("eye"))
local Esp = Visuals:CreateSection({ Name = "ESP", Icon = icon("scan-eye") })
local c1, c2 = Esp:AddColumns(2)
c1:AddToggle({ Name = "Boxes", Style = "Checkbox", Flag = "EspBoxes" })
c2:AddToggle({ Name = "Names", Style = "Checkbox", Flag = "EspNames" })
Esp:AddColorPicker({ Name = "Color", Default = Color3.fromRGB(245, 194, 12), Flag = "EspColor" })
Esp:AddRangeSlider({ Name = "Distance", Min = 0, Max = 5000, Default = { 0, 1000 }, Flag = "EspRange" })

Window:CreateSettingsTab("Settings", icon("settings"))
Window:Notify({ Title = "My Hub", Content = "Loaded", Type = "Success" })

Common problems

  • I don't see the window when I run it: the intro keeps it hidden for about 2 seconds (one click skips it). With Intro = { Enabled = false } it appears right away.
  • The intro doesn't play when I re-run: that's on purpose (OncePerSession). Set Intro = { OncePerSession = false } to always see it.
  • I closed the window and can't open it: use the ToggleKey or the floating button. On mobile, don't disable FloatingButton.
  • The window opens somewhere else or with another theme: the library remembers what the player left. Use Reset Layout, Window:ResetLayout() or RememberLayout = false.
  • My callback runs when a config loads: that's normal for LoadConfig. Use :Set(value, true) for silent changes.
  • My loops keep going after Unload UI: stop them with Window:OnUnload.
  • `Lucide.GetAsset` fails: the icon doesn't exist; use the helper with pcall.