Home › Roblox (Luau) › Roblox Luau rules
Roblox Luau rules
Cursor rules for Roblox experiences in Luau: strict typing, client/server boundaries, remotes, and data saving.
CursorRoblox (Luau)
How to use
Save this as .cursor/rules/roblox.mdc in your repository root, commit it, and your agent will pick it up automatically. Edit the commands to match your project.
.cursor/rules/roblox.mdcDownload ---
description: Roblox Luau conventions
globs: ["src/**/*.{lua,luau}"]
alwaysApply: false
---
# Roblox (Luau)
- Start every script with `--!strict` and type function signatures and tables (`type PlayerData = { coins: number }`).
- Get services with `game:GetService("Players")`, never `game.Players`.
- Project layout via Rojo (`default.project.json`): `src/server` -> ServerScriptService, `src/client` -> StarterPlayerScripts, `src/shared` -> ReplicatedStorage. Shared logic in ModuleScripts.
- The server is authoritative. Clients only send intent through RemoteEvents/RemoteFunctions; the server validates every argument (type, range, cooldown, ownership) before acting.
- Never trust client values for currency, damage, or position. Don't use `RemoteFunction:InvokeClient`.
- Use `task.wait`, `task.spawn`, `task.delay`, never `wait()`/`spawn()`/`delay()`.
- Clean up connections: store them and `:Disconnect()` them, or use a Trove/Maid if the project has one.
- DataStores: wrap calls in `pcall`, use `UpdateAsync` for changes, save on `PlayerRemoving` and `game:BindToClose`, and respect request budgets. Use a session-locking library (ProfileStore) if present.
- Use `RunService.Heartbeat` for per-frame logic only when needed; avoid busy loops.
- Prefer `Instance.new` + setting `Parent` last.
## Done when
Selene (`selene src`) and StyLua (`stylua --check src`) pass and the change was tested in a Studio play session.