roblox-ui — Claude Code skill: build Roblox interfaces
A skill for building Roblox interfaces: ScreenGui lifecycle, responsive UDim2 layouts, gamepad and touch input. Useful when UI clips or resets on respawn.
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill roblox-ui -a claude-codeWhat roblox-ui does
The skill walks the agent through a fixed order. First inspect existing ScreenGuis, fonts, colors and reusable components in Explorer, then decide ownership and lifecycle. StarterGui is the authored template and Roblox clones it into each player's PlayerGui, so ResetOnSpawn = false decides whether a screen survives respawn. Stale references to a destroyed clone are a bug.
Next comes a readable hierarchy of editable Instances and small behavior modules, plus responsive structure built from UDim2 scale, bounded offsets, UIPadding, UIGridLayout and AutomaticCanvasSize. Interactive elements stay inside CoreUISafeInsets so touch controls do not cover them. State renders from a small view state, buttons use Activated, and gamepad navigation gets an explicit entry point through GuiService.SelectedObject.
Verification runs in Device Simulator and Controller Emulator: desktop, narrow portrait, mobile landscape, tablet, console, then a respawn. The skill targets Roblox engine APIs and pairs with game-ui-ux for engine-neutral UX; action mapping belongs to input-systems and server trust to roblox-networking. Worth installing if your UI is one giant LocalScript that nobody wants to touch.
What it helps with
- build a HUD that holds up on a narrow phone screen
- fix UI that resets after respawn
- replace pixel layouts with responsive UDim2 structure
- add gamepad navigation with an explicit focus path
- split one giant LocalScript into components and modules
Example prompts for the agent
- Build an inventory ScreenGui with UIGridLayout and AutomaticCanvasSize that works in portrait and landscape
- Add gamepad navigation: focus the first button on open, clear SelectedObject on close
- Check this HUD in Device Simulator at narrow portrait and in Controller Emulator, note where text clips
How to install roblox-ui
1Skills CLI (Vercel)
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill roblox-ui -a claude-code2Manually: put the files in place
~/.claude/skills/roblox-ui/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/roblox-ui/
1Skills CLI (Vercel)
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill roblox-ui -a codex2Manually: put the files in place
.agents/skills/roblox-ui/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill roblox-ui -a cursor2Manually: put the files in place
.cursor/skills/roblox-ui/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install gamedev-skills/awesome-gamedev-agent-skills roblox-ui2Manually: put the files in place
.github/skills/roblox-ui/SKILL.md1Skills CLI (Vercel)
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill roblox-ui -a gemini-cli2Platform CLI
gemini skills install https://github.com/gamedev-skills/awesome-gamedev-agent-skills --path skills/other-engines/roblox-uiManually: put the files in place
.devin/skills/roblox-ui/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill roblox-ui -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about roblox-ui
How do I install roblox-ui in Claude?
Run npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill roblox-ui -a claude-code. The skill lands at ~/.claude/skills/roblox-ui/SKILL.md.
What does roblox-ui do?
It guides the agent through Roblox UI work: auditing existing ScreenGuis, PlayerGui lifecycle, responsive layouts, input and focus, restrained animation, and multi-viewport verification.
How is roblox-ui different from game-ui-ux?
roblox-ui owns Roblox Instances and APIs, while game-ui-ux covers engine-neutral information architecture and UX. They are meant to be used together.
Source text
SKILL.md · Apache-2.0
---
name: roblox-ui
description: >
Build production Roblox interfaces with ScreenGui/PlayerGui lifecycle, responsive UDim2
layouts, safe insets, reusable editable Instances, cross-device input and selection, restrained
motion, cleanup, and multi-viewport verification. Use for Roblox HUDs, inventories, shops,
settings, ability bars, ScrollingFrames, AutomaticSize, GuiService, gamepad focus, touch UI, or
UI that clips, resets on respawn, looks generic, or was generated as one giant LocalScript.
---
# Roblox UI
Implement deliberate, editable Roblox UI that preserves the experience's visual language and
works across supported devices. Targets Roblox's rolling platform APIs. Pair with `game-ui-ux`
for engine-neutral information architecture and UX; this skill owns Roblox Instances and APIs.
## When to use
- Use for authored `ScreenGui` interfaces, Roblox layout/constraint APIs, UI lifecycle, input,
focus, animation, performance, or responsive/device fixes.
- Use to replace brittle pixel layouts, runtime-created Instance tangles, mouse-only menus, or
generic generated styling with a maintainable hierarchy.
**When not to use:** general UX flow and accessibility principles belong to `game-ui-ux`; raw
gameplay action mapping belongs to `input-systems`; server trust belongs to `roblox-networking`.
## Workflow
1. **Inspect before designing.** In Explorer, inventory existing `ScreenGui`s, UI modules,
fonts, colors, icon family, spacing, corners, strokes, animation timing, naming, and reusable
components, including any `StyleSheet`/`StyleLink` styling, tokens and themes. Capture
representative screenshots at two viewports. Extend that language.
2. **Define ownership and lifecycle.** `StarterGui` is the authored template; Roblox clones it
into each player's `PlayerGui`. Decide whether each `ScreenGui` should persist across respawn
with `ResetOnSpawn = false`; never keep stale references to a destroyed clone.
3. **Author a readable hierarchy.** Prefer meaningful editable Instances and small behavior
modules. A normal screen should be understandable in Explorer; procedural generation is for
genuinely data-driven repetition, not the whole shell.
4. **Build responsive structure.** Combine `UDim2` scale for placement with bounded offsets,
correct `AnchorPoint`s, layouts, padding, content sizing, and constraints. Choose explicit
narrow/wide arrangements instead of shrinking a desktop panel until it technically fits.
5. **Handle platform obstructions.** Keep interactive UI in `CoreUISafeInsets` (the recommended
`ScreenGui.ScreenInsets` default), and account for touch controls and TV distance/overscan.
6. **Wire state and input.** Render from a small view state; update on events. Use `Activated` for
`GuiButton`s, explicit selected states, and reachable gamepad navigation. Bind non-widget
actions with `ContextActionService` only while the screen owns them.
7. **Polish with restraint.** Implement hover, pressed, selected, and disabled states. Animate
state changes, not decoration; honor `GuiService.ReducedMotionEnabled` and clean up tweens and
connections when the screen closes or is replaced.
8. **Verify the real interface.** Use Device Simulator and Controller Emulator. Test desktop,
narrow portrait, mobile landscape, tablet-like, and console/gamepad; then respawn. Record
clipping, overlap, text, scroll, safe-area, focus path, touch target, and lifecycle results.
## Production structure
```text
StarterGui
└── InventoryGui (ScreenGui; ResetOnSpawn = false)
├── Root (Frame)
│ ├── Header
│ ├── Content
│ │ ├── CategoryList
│ │ ├── ItemGrid (ScrollingFrame)
│ │ └── DetailsPanel
│ └── Footer
└── InventoryController (LocalScript)
ReplicatedStorage
└── UI
├── Components
└── Theme
```
Names describe roles, not colors or temporary positions. Keep repeated item cells as templates or
components, but keep the authored shell visible in Explorer.
## Patterns
### Layout that survives content and viewport changes
```lua
-- Authored properties on ItemGrid (ScrollingFrame):
-- AutomaticCanvasSize = Enum.AutomaticSize.Y
-- CanvasSize = UDim2.fromOffset(0, 0)
-- Children: UIPadding + UIGridLayout
local grid = itemGrid.UIGridLayout
local projectBreakpoint = 700 -- derive from where this composition stops being usable
local function applyComposition()
local narrow = root.AbsoluteSize.X < projectBreakpoint
categoryList.UIListLayout.FillDirection = if narrow
then Enum.FillDirection.Horizontal
else Enum.FillDirection.Vertical
categoryList.Size = if narrow
then UDim2.new(1, 0, 0, 40)
else UDim2.new(0, 148, 1, 0)
itemGrid.Position = if narrow then UDim2.fromOffset(0, 52) else UDim2.fromOffset(164, 0)
itemGrid.Size = if narrow
then UDim2.new(1, 0, 1, -52)
else UDim2.new(0.58, -164, 1, 0)
detailsPanel.Visible = not narrow -- open details as a separate narrow-screen state
local width = itemGrid.AbsoluteSize.X
local columns = if width < 520 then 2 elseif width < 820 then 3 else 4
local gap = 12
local usable = width - itemGrid.UIPadding.PaddingLeft.Offset
- itemGrid.UIPadding.PaddingRight.Offset - gap * (columns - 1)
grid.CellSize = UDim2.fromOffset(math.floor(usable / columns), 112)
grid.CellPadding = UDim2.fromOffset(gap, gap)
end
root:GetPropertyChangedSignal("AbsoluteSize"):Connect(applyComposition)
applyComposition()
```
Use `UIListLayout` for one-dimensional flow, `UIGridLayout` for uniform cells, and
`UITableLayout` only when row/column alignment is truly tabular. `AutomaticSize` fits content;
`AutomaticCanvasSize` fits scroll content. Bound extremes with `UISizeConstraint`,
`UIAspectRatioConstraint`, or `UITextSizeConstraint` rather than one global `UIScale` guess.
### One activation path and explicit gamepad entry
```lua
local GuiService = game:GetService("GuiService")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local function usesDirectionalFocus(): boolean
local preferred = UserInputService.PreferredInput
return preferred == Enum.PreferredInput.Gamepad
or preferred == Enum.PreferredInput.MicroGamepad
end
local function focusFirstItem()
task.spawn(function()
RunService.RenderStepped:Wait() -- selection must be rendered and selectable
if root.Visible and usesDirectionalFocus() then
GuiService.SelectedObject = firstItemButton
end
end)
end
local function openInventory()
root.Visible = true
focusFirstItem()
end
local function closeInventory()
GuiService.SelectedObject = nil
root.Visible = false
end
-- Owned by the screen lifecycle; disconnect on teardown.
local inputConnection = UserInputService:GetPropertyChangedSignal("PreferredInput"):Connect(function()
if root.Visible and GuiService.SelectedObject == nil then focusFirstItem() end
end)
firstItemButton.Activated:Connect(function()
selectItem(firstItemButton:GetAttribute("ItemId"))
end)
```
Decide input-dependent UI from `UserInputService.PreferredInput`, which follows the player's
primary device; `TouchEnabled`/`GamepadEnabled` are capabilities (a touch laptop reports touch)
and `GetLastInputType()` thrashes. Prefer `Activated` over separate mouse/touch handlers. Set `NextSelectionUp/Down/Left/Right`
when automatic navigation is ambiguous, especially around grids, sidebars, and modals. A modal
must trap focus inside itself and restore a sensible selection when it closes.
For cross-device action binding, the Input Action System (`InputContext`/`InputAction`/
`InputBinding`) is the modern edit-time layer; see `references/input-navigation.md`.
Inspect Roblox's default selection adornment in context. If it overwhelms the interface, assign a
project-owned `SelectionImageObject` or selected-state treatment; keep it visible, valid, and
restrained rather than disabling focus feedback.
### State transition without animation noise
```lua
local TweenService = game:GetService("TweenService")
local GuiService = game:GetService("GuiService")
local fade = TweenInfo.new(0.14, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local function setPanelVisible(visible: boolean)
panel.Visible = true -- panel is a CanvasGroup
if GuiService.ReducedMotionEnabled then
panel.GroupTransparency = if visible then 0 else 1
else
TweenService:Create(panel, fade, {
GroupTransparency = if visible then 0 else 1,
}):Play()
end
if not visible then
task.delay(fade.Time, function()
if panel.GroupTransparency == 1 then panel.Visible = false end
end)
end
end
```
Animate a panel or state boundary once. Do not independently bounce every descendant.
## Visual quality gates
- Establish hierarchy through size, weight, contrast, grouping, and whitespace before adding
decoration. Use a small spacing scale and align to it.
- Preserve the game's fonts, palette, icons, radii, and strokes. If the project uses UI styling,
change tokens and `StyleRule`s rather than per-instance properties; the Properties window
marks styled properties with ⚠ and names the style on hover. If nothing exists, define a compact token set (a token `StyleSheet` or module); do not improvise per
component.
- Use corners where the material/form calls for them, not on every nested `Frame`. Avoid nested
card-on-card shells, universal pills, arbitrary gradients/glows/shadows, neon outlines,
excessive transparency/blur, oversized headings, meaningless icons, and huge empty panels.
- Buttons with different importance should not look identical. Define primary, secondary,
quiet, destructive, selected, pressed, hover, and disabled treatment only as needed.
- Motion communicates open/close, focus, confirmation, or spatial relationship. Keep it short,
interruptible, and subtle; avoid perpetual motion and decorative tween chains.
- On touch devices, reserve the default movement/jump corners. Move or recompose bottom actions
that overlap them, and show only the hints for the current `PreferredInput`.
## Common failures
| Symptom | Likely cause | Remedy |
|---|---|---|
| UI disappears or duplicates after respawn | wrong `ResetOnSpawn` policy or stale clone | choose policy; reacquire from `PlayerGui`; clean old bindings |
| Phone layout clips | desktop offsets/global scale used as layout | add narrow composition, layouts, bounds, and Device Simulator checks |
| Content hidden under topbar/notch | insets ignored or `ScreenInsets = None` | use `CoreUISafeInsets` for interactive UI; inspect intentional bleed |
| Scroll ends early | fixed `CanvasSize` | use `AutomaticCanvasSize` or layout `AbsoluteContentSize` |
| Controller gets stuck | no entry selection or bad neighbor graph | set initial `SelectedObject`; define and test focus edges/modal trap |
| UI looks generated | decoration substituted for hierarchy | remove effects; align, reduce nesting, fix density and component roles |
| Explorer contains only one script | entire authored interface is procedural | author the shell as named Instances; generate repeated content only |
| Increasing connection/tween count | screen rebinds without cleanup | own connections per screen lifecycle; disconnect/cancel on teardown |
## Resources
- Read `references/responsive-layout.md` for layout decisions, inset policy, density, and the
required viewport matrix.
- Read `references/input-navigation.md` when implementing gamepad/touch focus, modal behavior,
action binding, or motion preferences.
- Build `assets/inventory-quality-test.project.json` with Rojo (it maps the adjacent JSON model)
for an editable Instance fixture used in visual/layout review; it is a test baseline, not a style
template for a shipping game.
## Related skills
- `game-ui-ux` — information hierarchy, screen flow, accessibility, and UX validation.
- `input-systems` — gameplay action mapping and device switching.
- `roblox-networking` — server-authoritative requests initiated by UI.
- `roblox-studio-workflow` — Explorer-first editing and Studio verification.
## Primary references
- Roblox Creator Hub: `https://create.roblox.com/docs/ui/on-screen-containers`
- Roblox Creator Hub: `https://create.roblox.com/docs/ui/position-and-size`
- Roblox Creator Hub: `https://create.roblox.com/docs/ui/size-modifiers`
- Roblox Creator Hub: `https://create.roblox.com/docs/studio/testing-modes`
© gamedev-skills · Apache-2.0 · gamedev-skills/awesome-gamedev-agent-skills