Project Overview
Rayfield is a modular TypeScript framework that demonstrates domain-driven backend architecture. It provides an opinionated structure for defining data models, encapsulating business logic, and exposing a GraphQL API.
Main Capabilities
- Auto-generate CRUD GraphQL schema from declarative data models
- Encapsulate use-case logic in isolated service classes
- Apply hooks and policies for validation, authorization, and side-effects
- Integrate common concerns (authentication, file storage, mailing) via plugins
- Offer a CLI for project scaffolding and code generation
Maintenance Status
Rayfield’s core is non-functional in its current state. The underlying data-model definitions have evolved, and the schema generation step fails until models are updated. No active releases address this incompatibility.
Why Study or Fork Rayfield
- Explore a clear separation between domain entities, use-cases, and API layer
- Reuse or modernize its plugin hooks for auth, files, and email workflows
- Adapt its CLI-driven code-generation approach for new projects
- Contribute a data-model migration to revive the framework
Getting Started
Clone the repository and inspect the architecture:
git clone https://github.com/AllahSolutions/rayfield.git
cd rayfield
npm install
Open
src/models/
and align definitions with current schema conventions.Run the code generator (once models update):
npm run generate npm run dev
Explore
src/use-cases/
,src/plugins/
, and the generatedsrc/graphql/
schema.Submit pull requests to update data models and restore functionality.
Getting Started
Follow these steps to import Rayfield into your Roblox game, create your first window, and add a simple button in under five minutes.
1. Install Rayfield
- Open Roblox Studio and your target place.
- In the Explorer, right-click ReplicatedStorage → Insert Object → ModuleScript.
- Rename the new ModuleScript to
Rayfield
. - Paste the contents of
main.lua
into ReplicatedStorage.Rayfield and save.
2. Initialize a Window
Create a LocalScript under StarterPlayerScripts (or StarterGui) and add:
-- StarterPlayerScripts/InitRayfield.lua
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Rayfield = require(ReplicatedStorage.Rayfield)
-- Create a basic window
local Window = Rayfield:CreateWindow({
Name = "Demo UI", -- Window title in top bar
LoadingTitle = "Welcome to Demo UI", -- Splash screen title
LoadingSubtitle = "Loading...", -- Splash screen subtitle
ConfigurationSaving = {
Enabled = true, -- Enable config file saving
FolderName = nil, -- Defaults to "RayfieldConfigs"
FileName = "UserSettings" -- Name of the config file
},
Discord = {
Enabled = false, -- Discord invite button
Invite = "" -- Your server invite code
},
KeySystem = false -- Disable built-in keybind check
})
Save and run the game; you should see a loading splash, then an empty window titled Demo UI.
3. Add a Button
Extend the same script to add an interactive button:
-- Add a button that notifies when clicked
Window:CreateButton({
Name = "Click Me", -- Button label
Callback = function()
Rayfield:Notify({ -- Built-in notification pop-up
Title = "Success",
Content = "You clicked the button!"
})
end
})
Full example:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Rayfield = require(ReplicatedStorage.Rayfield)
local Window = Rayfield:CreateWindow({
Name = "Demo UI",
LoadingTitle = "Welcome to Demo UI",
LoadingSubtitle = "Loading...",
ConfigurationSaving = { Enabled = true },
Discord = { Enabled = false },
KeySystem = false
})
Window:CreateButton({
Name = "Click Me",
Callback = function()
Rayfield:Notify({
Title = "Success",
Content = "You clicked the button!"
})
end
})
Run the game. You now have a functional Rayfield window with a working button—your first success!
API Reference
Rayfield exposes a single module RayfieldLibrary
that you require
to bootstrap your UI. Use its methods to create windows, tabs, and UI elements, and to trigger notifications or theme changes.
Library Bootstrap
require & CreateWindow
Signature
local RayfieldLibrary = require(path_to_main)
-- Create the main UI window
local Window = RayfieldLibrary:CreateWindow(settings: table): Window
Parameters (settings table)
• Name (string): window title shown in header.
• LoadingTitle (string, optional): text shown during UI load animation.
• ConfigurationSaving (table, optional): auto save/load settings
– Enabled (bool)
– FileName (string)
– FolderName (string)
Returns
• Window object
Example
local Rayfield = require(game.ReplicatedStorage.Rayfield)
local Window = Rayfield:CreateWindow({
Name = "My Admin Panel",
LoadingTitle = "Initializing…",
ConfigurationSaving = {
Enabled = true,
FileName = "AdminConfig",
FolderName = "AdminConfigs"
}
})
Window Object
Once created, a Window
lets you add tabs and control high-level features.
Methods
CreateTab
local Tab = Window:CreateTab(title: string): Tab
• title
: text label for the tab.
Returns a Tab
object.
SetTitle
Window:SetTitle(newTitle: string)
• Updates window header text.
(Global) ChangeTheme
RayfieldLibrary:ChangeTheme(theme: table)
• theme
: table of color overrides (see Themes in repository).
Tab Object
A Tab
groups related UI elements. All Create…
methods return the element descriptor for further control.
CreateButton
Tab:CreateButton(options: table): Button
Options
• Name (string): label text.
• Description (string, optional): tooltip or subtitle.
• Callback (function): invoked on click.
Example
Tab:CreateButton({
Name = "Teleport to Spawn",
Description = "Instantly move to spawn",
Callback = function()
game.Players.LocalPlayer.Character.HumanoidRootPart.CFrame =
workspace.SpawnLocation.CFrame
end
})
CreateToggle
Tab:CreateToggle(options: table): Toggle
Options
• Name (string)
• Flag (string, optional): for config persistence
• CurrentValue (bool)
• Callback (function(state: bool))
Example
Tab:CreateToggle({
Name = "Enable Godmode",
Flag = "godmode",
CurrentValue = false,
Callback = function(isOn)
_G.Godmode = isOn
end
})
CreateSlider
Tab:CreateSlider(options: table): Slider
Options
• Name (string)
• Range (table[number, number]) e.g. {0,100}
• Increment (number)
• Suffix (string, optional)
• CurrentValue (number)
• Flag (string, optional)
• Callback (function(value: number))
Example
Tab:CreateSlider({
Name = "Walkspeed",
Range = {16, 100},
Increment = 1,
Suffix = "studs/s",
CurrentValue = 16,
Flag = "walkspeed",
Callback = function(v)
game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = v
end
})
CreateDropdown
Tab:CreateDropdown(options: table): Dropdown
Options
• Name (string)
• Options (array[string])
• CurrentOption (string)
• MultiSelect (bool, optional)
• Flag (string, optional)
• Callback (function(selected: string or table))
Example
Tab:CreateDropdown({
Name = "Select Tool",
Options = {"Sword","Shield","Bow"},
CurrentOption = "Sword",
Flag = "fav_tool",
Callback = function(choice)
print("Equipped:", choice)
end
})
CreateColorpicker
Tab:CreateColorpicker(options: table): Colorpicker
Options
• Name (string)
• Flag (string, optional)
• CurrentColor (Color3)
• Callback (function(color: Color3))
Example
Tab:CreateColorpicker({
Name = "ESP Color",
Flag = "esp_color",
CurrentColor = Color3.fromRGB(255,0,0),
Callback = function(c)
ESP.HighlightColor = c
end
})
CreateKeybind
Tab:CreateKeybind(options: table): Keybind
Options
• Name (string)
• Flag (string, optional)
• Mode (string): "Toggle"
or "Hold"
• Default (Enum.KeyCode)
• Callback (function(key: Enum.KeyCode))
Example
Tab:CreateKeybind({
Name = "Toggle UI",
Flag = "toggle_ui",
Mode = "Toggle",
Default = Enum.KeyCode.F,
Callback = function(key)
Window:Toggle() -- show/hide window
end
})
Notifications
RayfieldLibrary:Notify
RayfieldLibrary:Notify(options: table)
Options
• Title (string)
• Content (string)
• Duration (number, optional, seconds)
Example
RayfieldLibrary:Notify({
Title = "Warning",
Content = "Low health detected",
Duration = 5
})
Configuration (Save/Load)
Refer to Configuration Saving and Loading for SaveConfiguration()
and LoadConfiguration()
details. After building all tabs and elements, call:
RayfieldLibrary:LoadConfiguration()
to restore persisted flags. Call RayfieldLibrary:SaveConfiguration()
to write manual updates.
Configuration & Themes
Rayfield centralizes theme management and configuration persistence. Use ConfigurationSaving
in CreateWindow
to enable save/load, and define or update themes via Theme
, UpdateTheme
, and SetTheme
.
1. Configuration Persistence
1.1 Enable Saving & Loading
Pass a ConfigurationSaving
table when creating your window:
local Rayfield = loadstring(game:HttpGet("https://raw.githubusercontent.com/AllahSolutions/rayfield/main/source.lua"))()
local Window = Rayfield:CreateWindow({
Name = "My Game UI",
LoadingTitle = "Initializing...",
ConfigurationSaving = {
Enabled = true, -- master switch
FolderName= "GameConfigs", -- subfolder in your executor’s workspace
FileName = "DefaultConfig",-- default config file
AutoSave = false, -- save on every change
AutoLoad = true -- load on window init
},
Theme = {
TextColor = Color3.fromRGB(255,255,255),
MainColor = Color3.fromRGB(30,30,30),
AccentColor = Color3.fromRGB(0,170,255),
BackgroundColor = Color3.fromRGB(20,20,20)
}
})
1.2 Runtime Save & Load
Use these methods to persist or restore UI element states:
-- Save current state as "Session1"
Window:SaveConfiguration("Session1")
-- Load values from "Session1"
Window:LoadConfiguration("Session1")
Combine with buttons or keybinds for manual control:
Window:CreateButton({
Name = "Save Config",
Callback = function() Window:SaveConfiguration("QuickSave") end
})
Window:CreateButton({
Name = "Load Config",
Callback = function() Window:LoadConfiguration("QuickSave") end
})
2. Theme Customization
2.1 Initial Theme Definition
Define your base look when calling CreateWindow
(see above). Fields:
TextColor
: default textMainColor
: panels, popupsAccentColor
: buttons, slidersBackgroundColor
: window backdrop
2.2 Update Theme at Runtime
Change part or all of the theme without rebuilding the UI:
-- Update only accent and background colors
Window:UpdateTheme({
AccentColor = Color3.fromRGB(255,100,100),
BackgroundColor = Color3.fromRGB(15,15,15)
})
This refreshes every element using those theme fields.
2.3 Replace Entire Theme
Apply a completely new theme object:
local DarkTheme = {
TextColor = Color3.fromRGB(200,200,200),
MainColor = Color3.fromRGB(40,40,40),
AccentColor = Color3.fromRGB(100,200,100),
BackgroundColor = Color3.fromRGB(10,10,10)
}
Window:SetTheme(DarkTheme)
2.4 Light/Dark Toggle Example
Combine toggle element with theme switching:
-- Define themes
local LightTheme = {
TextColor = Color3.new(0,0,0),
MainColor = Color3.fromRGB(230,230,230),
AccentColor = Color3.fromRGB(0,120,215),
BackgroundColor = Color3.fromRGB(245,245,245)
}
local DarkTheme = {
TextColor = Color3.fromRGB(255,255,255),
MainColor = Color3.fromRGB(30,30,30),
AccentColor = Color3.fromRGB(0,170,255),
BackgroundColor = Color3.fromRGB(20,20,20)
}
-- Add toggle to switch
Window:CreateToggle({
Name = "Dark Mode",
Current = true,
Callback = function(isDark)
if isDark then
Window:SetTheme(DarkTheme)
else
Window:SetTheme(LightTheme)
end
end
})
This instantly swaps colors across all UI elements.