Version 0.3.0 of Seam is here! Included in this update is:

  * Removal of `From` and `DeclareComponent`, revamp of components system
  * Removal of preset components
  * Addition of `GetValue`
  * Improvements to the backend
  * Fixes to race conditions
  * Fixes to crashes and infinite loops
  * And an insane number of other fixes

This version, to put it generously, is a huge step up for Seam. Many of these fixes and changes come from internal feedback sourcing from people that used it in production! I worked closely with these developers to get a dev branch stable and working that meets their needs -- and that dev branch is now the publicly released version v0.3.0.

## Revamped component system

The biggest change to Seam was the complete rethinking of the way components worked. Previously, there was a race condition to declare components, store them memory, and then use them with `From`. This approach was also super limited and unintuitive. Now, you create instances of components by passing the component module directly into `New`, giving you more control. As a bonus, these new components are object-oriented!

I got a ton of feedback regarding components from both @3_F7 and @HappySunChild, with the former developer testing my approach and approving it. You can take a look at how components work by reading the API for [**New**](https://seam.igottic.com/docs/API/declarations/New) and [**Component**](https://seam.igottic.com/docs/API/declarations/Component)!

In summary, components now work like this:

  * Create the component module, containing `Init` and `Construct` methods, as well as any others you optionally want
  * Return `Component(Module)`, instead of just `Module`
  * Pass in that module to the first parameter of `New`, and make the properties whatever you would like (they are custom, not directly applied)

I also removed preset components from Seam because, well, they feel like bloat. I would rather leave component creation to the developers and the community, who can do it much better than I can.

## Addition of GetValue

`GetValue` is an added declaration that allows you to read any value, including states.

In this example,

    local MyValue = Value(5)

    local X = GetValue(5)
    local Y = GetValue(MyValue)

X and Y are _both_ 5\. This is a great thing to try if your code may or may not have a state, but you need a value to work with.

## Fixed many, many bugs

I fixed a ton of bugs, and had a headache doing so (you can probably tell if you look at the commit messages, lol).

A summary of fixed bugs include:

  * Fixed a C-stack overflow caused by adverse state interactions
  * Critical fix for boolean value states
  * Typechecking fixes
  * Fixes to the way tables in values worked, including a fix to how they wouldn't update
  * Rendered is now properly declared as Rendered behind the scenes, not Computed
  * Addition of `Value.ValueRaw` for cases that need it (since `Value.Value` got tons of changes for tables)
  * Fixed signal triggers not triggering when using `table.insert` on value's value.
  * Fixed critical issues with animation states that could cause insane lag or bugs
  * Fixed an edge-case error that was caused by declaring children improperly
  * Updated the way compute states calculate values, preventing edge-case issues
  * And more small stuff!

## Seam's development philsophy remains unchanged

Seam is intended to be an improvement compared to existing UI frameworks, not a headache; this means community feedback will drive the direction of the library, and comes first for considerations on changes.

A large handful of developers were important to providing feedback to influence these changes, so my gratitude goes out to all of you!

That's all folks, enjoy a more stable and awesome Seam! :3


As a quick patch, version 0.3.1 has released! Here is what changed:

  * Added `SetValue`
  * Animation states (Spring and Tween) now calculate on pre-render (instead of render) to fix occasional bugs
  * Backend changes
  * Added `Tags`

Also, documentation for `GetValue` was finally added, even though it's been around since 0.2.2; this was a previous mistake, oops!

`SetValue` is a safe and alternative way to set state values. It really boils down to preference whether you use this, or `Value.Value`.

`Tags` is used to add `CollectionService` tags to an instance when creating or hydrating with `New`! See the documentation for more info.

Animation states were changed to `RunService.PreRender` instead of `RunService.RenderStepped` to prevent occasional issues. For example, you might've previously had weird bugs come from animation states being read every frame, but not updated properly. This should now be fixed!

There were also backend changes, but most notably, all of the codebase was changed from _lua_ to _luau_. I had previously used _lua_ out of habit, not because it's better.

That's it! Make sure to update Seam to get these newest features and fixes.


Seam is not the only UI framework on Roblox, with many other popular and great options (including React-lua, Fusion, Blend, and Vide) capturing a lot of adoption. So, when I present Seam to developers, I often get asked why Seam is better than the other options.

This blog post is going to be an overview of why I think Seam is worth trying, and what it's best for.

warning

Heads up! Seam is no longer just a UI library, so this blog post might be missing that context.

## Seam is built to be simpler and easier

Unlike most UI frameworks, there aren't redundant features that focus on specifics. Instead, features in Seam are built to be used across multiple contexts, increasing flexibility. For example, most frameworks reserve an equivalent to `Computed` for just a simple state reaction. If you wanted to create dynamic children, you'd have to use a different constructor, which creates more clutter and confusion. In Seam, you can do _both_ with `Computed`, since it acts how you would expect it to.

That's not the only reason Seam is simpler, though. More "complex" concepts, such as components or scopes, are not required to make UI with Seam. Often times, designers of UI frameworks get stuck in their own design philosphies, which may or may not be compatible with others. Seam is built to be simple in this way so that you can design UI how _you_ would like to.

**The cherry on top is that you don't have to programmatically make your UI. You can pre-design your UI in Studio's UI editor, and attach Seam functionality to it!** This means UI designers can focus on the designing, and the frontend programmers can focus on the programming. One frustrating thing I find with frameworks like React-lua is that I can't do this, and it wastes a lot of time and creates bottlenecks that don't need to be there.

## Seam is here for Roblox devs, not web devs

Fun fact: Roact (Roblox's equivalent to React) only exists because Roblox wanted to poach developers from other companies such as Meta, so they designed it to mimic their main web UI framework.

Seam isn't trying to reinvent the way UI frameworks work, and instead is taking the best parts of everything else to create something more usable. This means that beginners aren't going to have a hard time wrapping their head around how Seam works, but at the same time, Seam is just as easy and flexible for somebody who is experienced and looking to scale.

A big issue with open-source stuff in general is that people believe something new needs to completely reinvent what already exists to be meaningful. I disagree, since that isn't _always_ true -- sometimes just making things better through a collection of smaller decisions and changes is all that is needed to be a meaningful alternative. Reinventing things can often lead to over-engineering or otherwise weird solutions.

## Seam is made for games of all sizes

Your game doesn't have to be small, nor does have it have to be scaled up. Because there is so little boilerplate and setup to using Seam, while also being rich with functionality, you can use it in projects of any size. Want to just animate some stuff in your solo project? Go for it. Need a proper built-in component system to scale? Seam has your back. Are you somewhere in-between? That's also fine!

For example, React-lua is built well for large-scale projects, but doesn't make a lot of sense for smaller or solo projects, simply because of the amount of boilerplate there is to it.

Seam also performs well on the backend, being on-par with some other frameworks like Vide, or in extreme test cases, performing up to 5x-17x better (such as when compared to Fusion).

Lastly, Seam also does not have strict usage with syntax or juxtaposition, so you can arrange and type stuff in many different ways to match your coding conventions.

## So, what do ya say?

Most major UI frameworks serve a purpose for a specific set of developers, and I won't disrespect or invalidate them. But, with that being said, Seam also has a reason for existing, and might be worth checking out for UI/UX needs in your Roblox game.

I'm always open to feedback, though, and Seam is always changing for the better. If you have me added on Discord, reach out to me there! Otherwise, message me on Twitter or Roblox DevForum.

Thanks for the read, guys!


Seam is not the only UI framework on Roblox, with many other popular and great options (including React-lua, Fusion, Blend, and Vide) capturing a lot of adoption. So, when I present Seam to developers, I often get asked why Seam is better than the other options.

This blog post is going to be an overview of why I think Seam is worth trying, and what it's best for.


This feels strange to say considering I've never done this before, but yes, hi, this is my first blog post for Seam!

I want to catch you up on what has been happening with this framework lately, what my thinking is, etc.

First and foremost, you might notice the website looks completely different now. This is because I swapped the framework for documentation and more to Docusaurus. I didn't use this to begin with because I was lazy, to be honest. In fact, the first website was actually built with Carrd, believe it or not! Now, I hope (most) UX issues are fixed for ya. I'll improve this site over time, I just need to learn this framework some more (especially considering I am NOT a web developer, so I'm bad at this).

## Development Recap

Recently, Seam transitioned from the `0.0.3` alpha to `0.1.0` beta, which I would say declares it as more stable. Previously Seam was missing a ton of features and had some massive bugs, but that's all wrapped up now.

I don't want to call this production-ready yet, but that's mostly because I haven't used Seam in production for a large-scale project in a meaningful way. The best I got so far is usage in Slap Battles to support the crate system (specifically the opening animation), since Fusion caused a ton of lag (which Seam fixes).

## What's Next

I think Seam has a good number of features right now, and is very familiar to other frameworks, making it easy to learn. As such, I want to focus more on the documentation and stress-testing.

I have upcoming games releasing eventually, so, shoot, I might try Seam there.

## And uh, that's it...

Sorry I'm bad at this, plus my brain is pooped from working on these docs for a while now, so yeah. I'll make more posts later :3

Have a good day, fellas!


Version 0.3.2 has just released. Not much changed, but it might be worth updating if you have random problems!

In this version, the following changes were made:

  * Fixed shadowed variables in the code
  * Fixed typechecking issues
  * Fixed unused variables
  * Added selene.toml to source code
  * Fixed and optimized issues related to computed-based children
  * Fixed an issue with errors on the backend state manager
  * Adjusted typechecking for `New` in scope instance

That's it! Hope everybody had a happy holidays, and I wish you folks a great new year!


Two updates in two days? Wow, we're ending 2025 strong! Version 0.3.3 just dropped some utilities and more!

First and foremost, there are a lot of small little things you might like with this update. To begin, there is a new category in the API, called "Utilities". `GetValue` and `SetValue` are now both under this category.

The following changes have been made this update:

  * Re-organized all constructors into sub-folders on the backend
  * Components can now be edited as dictionaries by outside code
  * Components now have associated symbols on the backend
  * Added IsState (utility)
  * Added IsComponent (utility)
  * Added LockValue (utility)
  * Added MakeSymbol (utility)
  * Added MakeSignal (utility)
  * Added Inspect (utility)
  * Added OnAttached (connection)
  * Added Destroyed (declaration)

These all have various levels of "helpfulness", but regardless, they exist for when you need them! Take a look at the documentation to see more information about all of these.

Enjoy the new update, and again from the last update, have a happy new year!


Two updates in two days? Wow, we're ending 2025 strong! Version 0.3.3 just dropped some utilities and more!

Version 0.3.2 has just released. Not much changed, but it might be worth updating if you have random problems!

As a quick patch, version 0.3.1 has released! Here is what changed:

  * Added `SetValue`
  * Animation states (Spring and Tween) now calculate on pre-render (instead of render) to fix occasional bugs
  * Backend changes
  * Added `Tags`

Also, documentation for `GetValue` was finally added, even though it's been around since 0.2.2; this was a previous mistake, oops!

Version 0.3.0 of Seam is here! Included in this update is:

  * Removal of `From` and `DeclareComponent`, revamp of components system
  * Removal of preset components
  * Addition of `GetValue`
  * Improvements to the backend
  * Fixes to race conditions
  * Fixes to crashes and infinite loops
  * And an insane number of other fixes

Version 0.2.0 of Seam is here! Included in this update is:

  * Signifigantly improved typechecking
  * Added StageGui preset component
  * Removed ScaledUIStroke preset component
  * Bug fixes and more backend changes


# Tags

## C

  * [comparison1](https://seam.igottic.com/blog/tags/comparison)

## D

  * [discussion1](https://seam.igottic.com/blog/tags/discussion)

## S

  * [Seam17](https://seam.igottic.com/blog/tags/seam "Seam framework")

## U

  * [Update15](https://seam.igottic.com/blog/tags/update "Updates and news")


# Authors

  * [](https://seam.igottic.com/blog/authors/miagobble)

[## Mia Gobble](https://seam.igottic.com/blog/authors/miagobble)17

Seam Creator

[](https://x.com/iGottic_Real "X")[](https://www.linkedin.com/in/mia-gobble/ "LinkedIn")[](https://github.com/MiaGobble "GitHub")


# Rongo
A wrapper to connect MongoDB to your Roblox games.

Rongo is MongoDB Atlas Data API Wrapper for Roblox however also has support for self-hosted or non-Atlas MongoDB instances through use of a 1:1 REST API, relea

[**DevForum Post & Documentation**](https://devforum.roblox.com/t/rongo/1755615)


Infinite Shopping Mart

    The cool way to add plugins and themes to Infinite Yield!

(Beware of fake discords, the only official discord is on this README)

## Usage

The loader allows Infinite Store to always be kept up-to-date without re-downloading it every time you want to use it.

```lua
loadstring(game:HttpGet("https://raw.githubusercontent.com/Infinite-Store/Infinite-Store/main/main.lua"))()

## Contributions

Do you have your own plugin or want to update existing ones? You can do it by creating a fork and committing your files. Open a [pull request](https://github.com/Infinite-Store/Infinite-Store/compare) to get your changes accepted (compare across forks to select your fork).\
You may also open a pull request to add your plugin URLs from a source repository other than this one.

## License

Please read the [license](https://github.com/Infinite-Store/Infinite-Store/blob/main/LICENSE.md) before asking to use Infinite Store in your project.


# Welcome to modern-roblox-ts-template 👋

> A template repository for creating a Roblox game using roblox-ts and Flamework.

### 🏠 [Homepage](https://github.com/howmanysmall/modern-roblox-ts-template)

## Install

```sh
bun install

## Usage

```sh
bun run start

## Recommended Packages

⭐ means I use this package in my own projects.

# 🎞 Animation

- ⭐ [@rbxts/react-spring](https://www.npmjs.com/package/@rbxts/react-spring)
- [@rbxts/react-ripple](https://www.npmjs.com/package/@rbxts/react-ripple)
- [@rbxts/ripple](https://www.npmjs.com/package/@rbxts/ripple)

# 🏫 Classes

- ⭐ [@rbxts/rust-classes](https://www.npmjs.com/package/@rbxts/rust-classes)
- [@rbxts/rbx-date-time-utility](https://www.npmjs.com/package/@rbxts/rbx-date-time-utility)
- [@rbxts/rbx-format-number](https://www.npmjs.com/package/@rbxts/rbx-format-number)

# 📦 Data Storage

- ⭐ [@rbxts/rbx-profileservice-plus](https://www.npmjs.com/package/@rbxts/rbx-profileservice-plus)
- [@rbxts/lapis](https://www.npmjs.com/package/@rbxts/lapis)

# ⚛ React

- ⭐ [@rbxts/charm](https://www.npmjs.com/package/@rbxts/charm)
- ⭐ [@rbxts/context-stack](https://www.npmjs.com/package/@rbxts/context-stack)
- ⭐ [@rbxts/react-spring](https://www.npmjs.com/package/@rbxts/react-spring)
- [@rbxts/pretty-react-hooks](https://www.npmjs.com/package/@rbxts/pretty-react-hooks)
- [@rbxts/react-reflex](https://www.npmjs.com/package/@rbxts/react-reflex)
- [@rbxts/react-ripple](https://www.npmjs.com/package/@rbxts/react-ripple)
- [@rbxts/reflex](https://www.npmjs.com/package/@rbxts/reflex)
- [@rbxts/use-next-context](https://www.npmjs.com/package/@rbxts/use-next-context)
- [@rbxts/use-sync-external-store](https://www.npmjs.com/package/@rbxts/use-sync-external-store)
- [@rbxts/zustand](https://www.npmjs.com/package/@rbxts/zustand)

# 🗂 State Management

- ⭐ [@rbxts/charm](https://www.npmjs.com/package/@rbxts/charm)
- [@rbxts/reflex](https://www.npmjs.com/package/@rbxts/reflex)
- [@rbxts/use-sync-external-store](https://www.npmjs.com/package/@rbxts/use-sync-external-store)
- [@rbxts/zustand](https://www.npmjs.com/package/@rbxts/zustand)

# ⚙ Utilities

- ⭐ [@rbxts/iris](https://www.npmjs.com/package/@rbxts/iris)
- ⭐ [@rbxts/observers](https://www.npmjs.com/package/@rbxts/observers)
- ⭐ [@rbxts/rbx-draw](https://www.npmjs.com/package/@rbxts/rbx-draw)
- ⭐ [@rbxts/sift](https://www.npmjs.com/package/@rbxts/sift)
- ⭐ [@rbxts/streamable](https://www.npmjs.com/package/@rbxts/streamable)
- [@rbxts/immut](https://www.npmjs.com/package/@rbxts/immut)
- [@rbxts/remap](https://www.npmjs.com/package/@rbxts/remap)

## Author

👤 **HowManySmall**

* Github: [@HowManySmall](https://github.com/HowManySmall)

## Show your support

Give a ⭐ if this project helped you!

_This README was generated with ❤ by [readme-md-generator](https://github.com/kefranabg/readme-md-generator)_


# Aloha
 [](![]())

Aloha is a Discord API library written in Luau using [Lune](https://github.com/lune-org/lune). This is a successor to [Discordia](https://github.com/SinisterRectus/Discordia) for people who want to make Discord bots in Luau for easier Roblox integration.

## Current Features:
- Event connection system that allows you to listen in on Discord events with ease.
```lua
local Aloha = require("Aloha")
local Client = Aloha.Lib.Client

Client.On("MESSAGE_CREATE", function(message)
    print(message.content) -- Messages are automatically parsed into a Lua table, and abstracted to make accessing the channel, guild, etc, easier!

    message:Reply("Hello!")
end)
- A fully fledged type file for all of Discord's objects, so you don't have to check the docs!
- Enums for all those pesky numbers and constants from Discord.
- A secure and efficient WebSocket connection that automatically reconnects on failure.
- A built-in Luau evaluator for your convenience, sandboxed and safe for anyone to use!
- A janitor clone for cleaning up your connections.
- Built-in rate limiting.
- Shard management that scales with your bot.

## Getting started:
Running Aloha is incredibly simple. Simply call the `Run` function with your bot token and it will handle the rest.
```lua
local Aloha = require("Aloha")
local Enum = Aloha.Lib.Enum
-- DO NOT SHARE YOUR BOT TOKEN WITH ANYONE!
Aloha.Run("YOUR_BOT_TOKEN", Enum.INTENTS.DEFAULT) -- Run takes an optional second argument for intents.
Then run the file with `lune run <your_bot_file>.luau` and you're good to go!


# FastCast2

> Unofficial continuation of FastCast for Roblox

**An improved version of [FastCast](https://etithespir.it/FastCastAPIDocs/)** with **Parallel scripting**, **more extensions**, and **statically typed**.  **A powerful modern projectile** library

**FastCast2** It's a **Roblox projectile library** powered by [VMsDispatcher](https://github.com/weenachuangkud/VMsDispatcher) designed to simulate **thousands** of projectiles without relying on physics replication.

Because FastCast is no longer actively maintained by [EtiTheSpirit](https://github.com/EtiTheSpirit), this repository continues the project with updates and adaptations.

# Benefits of using FastCast2

- Highly customizable
- Versatile projectile library
- Parallel scripting support
- Easy to use and integrate
- Raycast and Blockcast, Spherecast support
- BulkMoveTo support
- Built-in ObjectCache
- Flexible and extensible design
- Improves development productivity
- High Performance
- Completely free

FastCast2 is an open-source project, and contributions from the community are welcome.
Read more on [FastCast2 devforum](https://devforum.roblox.com/t/fastcast2-an-improved-version-of-fastcast-with-parallel-scripting-more-extensions-and-statically-typed/4093890)

# Installation guide

1. Go to [Releases](https://github.com/weenachuangkud/FastCast2/releases) and install the `.rbxm` file from the latest release.
2. Open Roblox Studio and open any project.
3. Go to **File → Import Roblox Model** and import the `.rbxm` file.
4. After importing, **FastCast2** will appear in your Workspace.
5. Drag **FastCast2** into **ReplicatedStorage**.
6. Create a Part and set:
   - Size to `1, 1, 1`
   - `CanTouch` = false
   - `CanCollide` = false
   - `CanQuery` = false
7. Done — you’re ready to use FastCast2.

# Code example

Shooting projectiles from your head

```lua
-- Services
local Rep = game:GetService("ReplicatedStorage")
local RepFirst = game:GetService("ReplicatedFirst")
local Players = game:GetService("Players")
local UIS = game:GetService("UserInputService")

-- Modules
local FastCast2 = Rep:WaitForChild("FastCast2")

-- Requires
local FastCastTypes = require(FastCast2:WaitForChild("TypeDefinitions"))
local FastCastEnums = require(FastCast2:WaitForChild("FastCastEnums"))
local FastCastM = require(FastCast2)

-- CONSTANTS
local SPEED = 500

-- Variables
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local Head = character:WaitForChild("Head")

local Mouse = player:GetMouse()

local ProjectileContainer = workspace:WaitForChild("Projectiles")
local ProjectileTemplate = Rep:WaitForChild("Projectile")

local debounce = false
local debounce_time = 0.05

-- CastParams
local CastParams = RaycastParams.new()
CastParams.FilterDescendantsInstances = {character}
CastParams.FilterType = Enum.RaycastFilterType.Exclude
CastParams.IgnoreWater = true

-- Behavior
local castBehavior: FastCastTypes = FastCastM.newBehavior()
castBehavior.MaxDistance = 1000
castBehavior.RaycastParams = CastParams
castBehavior.HighFidelityBehavior = FastCastEnums.HighFidelityBehavior.Default
castBehavior.HighFidelitySegmentSize = 1
castBehavior.Acceleration = Vector3.new(0, -workspace.Gravity/2.3, 0)
castBehavior.AutoIgnoreContainer = true
castBehavior.CosmeticBulletContainer = ProjectileContainer
castBehavior.CosmeticBulletTemplate = ProjectileTemplate
castBehavior.UserData = {} -- Initial UserData when ActiveCast created
castBehavior.FastCastEventsConfig = {
    UseHit = true,
    UseLengthChanged = false, -- Warning: Setting this to true will make your FPS tank when there are 100-200+ projectiles
    UseCastTerminating = true,
    UseCastFire = true,
    UsePierced = false

-- Caster
local Caster = FastCastM.new()
Caster:Init(
    4, -- Roblox limits at 4 :(
    RepFirst,
    "CastVMs",
    RepFirst,
    "CastVMContainer",
    "CastVM",
    true
)

-- Functions

local function OnCastTerminating(cast: FastCastTypes.ActiveCastCompement)
    local obj = cast.RayInfo.CosmeticBulletObject
    if obj then
        obj:Destroy()
    end
end

local function OnHit()
    print("Hit!")
end

local function OnCastFire()
    print("CastFire!")
end

-- Connections

Caster.CastTerminating:Connect(OnCastTerminating)
Caster.Hit:Connect(OnHit)
Caster.CastFire:Connect(OnCastFire)

UIS.InputBegan:Connect(function(Input: InputObject, gp: boolean)
    if gp then return end
    if debounce then return end

    if Input.UserInputType == Enum.UserInputType.MouseButton1 then
        debounce = true

        local Origin = Head.Position
        local Direction = (Mouse.Hit.Position - Origin).Unit

        Caster:RaycastFire(Origin, Direction, SPEED, castBehavior)

        task.wait(debounce_time)
        debounce = false
    end
end)

How to set up [FastCastEventsModule](https://weenachuangkud.github.io/FastCast2/api/TypeDefinitions/#FastCastEventsModule)

```lua
-- Services
local Rep = game:GetService("ReplicatedStorage")

-- Modules

local FastCast2 = Rep:WaitForChild("FastCast2")

-- Requires
local TypeDef = require(FastCast2:WaitForChild("TypeDefinitions"))

-- Module

local module: TypeDef.FastCastEvents = {}

local debounce = false
local debounce_time = 0.2

module.LengthChanged = function(cast : TypeDef.ActiveCast)
    if not debounce then
        debounce = true
        print("OnLengthChanged Test")
        task.delay(debounce_time, function()
            debounce = false
        end)
    end
end

module.CastFire = function()
    print("CastFire!")
end

module.CastTerminating = function()
    print("CastTerminating!")
end

module.RayHit = function()
    print("Hit!")
end

module.CanPierce = function(cast, resultOfCast : RaycastResult, segmentVelocity, CosmeticBulletObject)
    local CanPierce = false
    if resultOfCast.Instance:GetAttribute("CanPierce") == true then
        CanPierce = true
    end
    print(CanPierce)
    return CanPierce
end

module.Pierced = function()
    print("Pierced!")
end

return module

After this, add this piece of code below the `FastCast:Init(...)`:

```lua
    Caster:SetFastCastEventsModule(pathTo.FastCastEventsModule)

(FastCastEventsModule can be used to optimize some FastCastEvents, like LengthChanged)

### -> Get started with the [FastCast2 documentation](https://weenachuangkud.github.io/FastCast2/)

# People behind FastCast2
- [Mawin CK](https://github.com/weenachuangkud): Main developer, Maintainer, Graphic designer
- [Naymmmm](https://github.com/Naymmmm): Help with proper docs, CI, Rojo supports, wally supports, Github pages(Moonwave)
- [EtiTheSpirit](https://github.com/EtiTheSpirit): Original developer

# Special Thanks

Thanks to the following people from the **Suphi Kaner Discord Server**:

- **@avibah** — For helping me create **VMDispatcher**
- **@ace9b472eeec4f53ba9e8d91bo87c636** — For advice and ideas
- **@23sinek345** — For code review and improvement suggestions


# BuiltInPlugins

Accurate decompilation of Roblox Studio's BuiltInPlugins

### Credits

* [TheGreatSageEqualToHeaven](https://github.com/TheGreatSageEqualToHeaven) - Outputting decompiled source code from bytecode output ([`src/PatchRoot/`](src/PatchRoot))
* Of course, the [Oracle](https://discord.gg/prHW9TA4QW) decompiler for decompilation of Luauc bytecode 🙂

## 🚫 Problems

* Some files may have had unhandled control flow and improperly decompiled, which would result in incorrect table and `goto` output

## 🏛 Licensing

Most of the BuiltinPlugins code is also proprietary and exclusively owned by Roblox Corporation ("Roblox"). Furthermore, any source code from this decompilation should be considered unlicensed code.

## Decompiler

These files were decompiled by the Oracle decompiler.

Discord Invite: https://discord.gg/prHW9TA4QW

[![Oracle Banner](extra/oracle-banner.png)](https://discord.gg/prHW9TA4QW)


![Html2Rbx-Thumb](https://github.com/user-attachments/assets/0d2376d2-79cc-4942-82fc-b13e50aefc1e)

> [!CAUTION]
> This is not at all ready for production use, but more for testing environments.
> I'm just trying to get this out there for bug testing, and for people to contribute and improve on.

## Where’s the Documentation?

Well, you’re in luck—it’s right over here on this website:
<https://systech-corp-1.gitbook.io/html-to-roblox/>

## What’s “HTML to Roblox”?

**HTML to Roblox** is an up‑and‑coming module that allows you to place HTML code into the module, and have it convert the contents of that HTML into a Roblox GUI.

## Why do I need this?

If you’re planning to recreate a website (I know a lot of games like [LegacyVerse](https://www.roblox.com/games/12147220287/LegacyVerse) do this), or maybe you just want something easy to set up and use, this might be useful. All you have to do is copy the website’s HTML code (with permission, of course), and the CSS if needed, and then you can see it on your GUI.

## What about the other solutions out there?

I’ve noticed this question in some older forum posts. I’ve seen “Roblox‑TS” mentioned quite a bit—it might be useful for some, but it appears to be harder to set up and less beginner‑friendly than this one aims to be. Plus, it uses TypeScript, which isn’t the easiest thing to learn right away. That’s why I made this module specifically for HTML—it’s the easiest for you.

## Does this include things like JavaScript support?

Absolutely. In fact, it also supports other features on HTML buttons like:
```html

  Press me

All this does is put the code into a JSTranspiler script within HtmlToRoblox's module and converts that same code into LuaU code supported by the Roblox engine. Depending on how much support compatibility we add, we might be able to put javascript html games in this thing.

# Want to Contribute?
Go ahead. The module’s source is in this repository for you to look over and help us improve for everyone using it. Thanks for making HTML to Roblox a better module for everyone.


To get HTML to Roblox up and going, you'll need to download the module from [here](https://github.com/Denied-ID/HTMLToRoblox/releases), and grab the latest release RBXM file. If you'd prefer to build it yourself, you can head over to this [Build from Source](https://systech-corp-1.gitbook.io/html-to-roblox/developers/build-from-source) guide. Then when you have that downloaded on your computer, place the file into studio from the Downloads folder (or wherever you save your files on your system) by dragging it in. Place it into ReplicatedStorage. It's where it can best be accessed from the client (the user playing the game).

[NextUsage Tutorial](https://systech-corp-1.gitbook.io/html-to-roblox/main/usage-tutorial)

Last updated 9 months ago


Module: HTMLToRoblox.HtmlParser

Functions

  * `**HtmlParser.parseAttributes**` `(attrString: string): table`

    * Converts an HTML attribute string into a table with key-value pairs.

  * `**HtmlParser.parse**` `(html: string): table`

    * Converts an HTML string into a node tree, represented as a table.

Module: HTMLToRoblox.CssParser

Functions

    * `**CssParser.parse**` `(cssText: string): table`

      * Converts a CSS string into a table mapping selectors to styles.

Module: HTMLToRoblox.GuiBuilder

Functions

      * `**GuiBuilder.reconstructHtml**` `(node: table): string`

        * Converts a node tree back into HTML.

      * `**GuiBuilder.build**` `(parent: Instance, node: table, cssTables: table)`

        * Creates Roblox GUI elements from a HTML/CSS parsed node tree.

      * `**GuiBuilder.buildChild**` `(parent: Instance, child: table|string, order: number, cssTables: table)`

        * Builds a child GUI element from a node or string.

Sub-module: HTMLToRoblox.GuiBuilder.ComponentRegistry

Functions

        * `**ComponentRegistry.parseColor**` `(colorString: string): Color3`

          * Converts a CSS color string to a Color3 object.

        * `**ComponentRegistry.parseSize**` `(sizeString: string): number?`

          * Converts a CSS size string to a number.

        * `**ComponentRegistry.create**` `(tag: string, props: table, baseCssStyles: table, hoverCssStyles: table, activeCssStyles: table): Instance?`

          * Creates a Roblox GUI component from HTML tag and style.

Table: `ComponentRegistry.registry`

          * Associates HTML tag names with GUI creation details, styles, and transitions.

Sub-module: HTMLToRoblox.GuiBuilder.JSEngine

Functions

          * `**JSEngine.register**` `(id: string, gui: Instance)`

            * Associates a GUI instance with an ID.

          * `**JSEngine.getGui**` `(id: string): Instance?`

            * Retrieves a GUI instance via ID.

          * `**JSEngine.execute**` `(jsCode: string)`

            * Runs JS-like code through the JSTranspiler.

          * `**JSEngine.evaluateExpression**` `(expr: string): any`

            * Evaluates a JS-like string or number expression.

          * `**JSEngine.setInnerText**` `(id: string, content: string)`

            * Updates text of a GUI element via ID.

          * `**JSEngine.setInnerHTML**` `(id: string, content: string)`

            * Updates the inner content of a GUI element by ID.

          * `**JSEngine.setValue**` `(id: string, content: string)`

            * Updates the value of a TextBox via ID.

          * `**JSEngine.navigateTo**` `(href: string)`

            * Simulates a URL navigation (displays a warning).

          * `**JSEngine.historyBack**`

            * Simulates a browser's back action (removes GUI).

Sub-module: HTMLToRoblox.GuiBuilder.JSEngine.JSTranspiler

Functions

            * `**JSTranspiler.transpile**` `(js: string): string`

              * Converts JS-like code to LuaU.

            * `**JSTranspiler.executeDirectly**` `(jsCode: string, JSEngine: table): any`

              * Directly runs transpiled JS, affecting the JSEngine's state.

[PreviousBuild from Source](https://systech-corp-1.gitbook.io/html-to-roblox/developers/build-from-source)

Last updated 9 months ago


When you have HTML to Roblox placed on your game, put it into a place where the client can access it such as ReplicatedStorage. For this tutorial, we'll be using ReplicatedStorage.

Next create a localscript inside of StarterGui. We'll name it **Builder **from now on.** **It will act as our Gui creator. Now how do we get the script going? Well all you have to do is find your HTML and place it somewhere with it enclosed as a string.

Html example (modulescript named Html inside of Builder):

Copy

    return {

Hello World!

This paragraph is red and bigger.

This paragraph uses default styles.

                <button onclick="console.log('Button clicked!')">Click me</button>

You have to keep your HTML starting with a body delimiter, or an html delimiter. Otherwise HTML to Roblox won't render it. This might change in the future.

Now lets go back to our Builder localscript. We need that Html module.

Copy

    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local Html = require(script:WaitForChild("Html"))

Now how can we get the Html rendered? Well first we need to require these modules. For CSS support (we'll get into that later), and Html handling/rendering.

Then we can get that html rendered. Parse the html, put it into a ScreenGui (or create one), then have GuiBuilder put the rendered html in that screengui.

Now you should see the html on your screen when you playtest the game. If you want to view the API Reference so you can learn more about this module, go ahead!

[PreviousInstallation](https://systech-corp-1.gitbook.io/html-to-roblox)[NextBuild from Source](https://systech-corp-1.gitbook.io/html-to-roblox/developers/build-from-source)

Last updated 9 months ago


First, you'll need to download the .zip source code. You can do that from [here](https://github.com/Denied-ID/HTMLToRoblox/archive/refs/heads/main.zip), or from the [GitHub repository](https://github.com/Denied-ID/HTMLToRoblox/tree/main) by clicking the green "Code" button, then "Download ZIP". Both should give you the same .zip source.

Next you have to extract the zip file. You can do this by double clicking the file from your file explorer if you're on a mac, or right click the file if you're on Windows from your file explorer and click "Extract All..." or use a file extractor such as 7zip.

Then navigate into that folder (there might be another folder named the exact same but that's normal), then find a folder called "source". Head into that folder. Next, double click build.bat if you're on Windows. It should then build the .rbxm file for you. The one that you saw in the releases tab earlier, but you made it instead. If you're not on Windows, open up that "source" folder in your terminal of choice. Then run:

Copy

    rojo build build.project.json -o HTMLToRoblox.rbxm

This command requires that you have "rojo" installed on your system, and in your system's path environment variables.

Congratulations! You should now have a .rbxm file that you can use inside of Roblox Studio. If you want to know how to properly get it installed and/or working, you can head over to the [Installation](https://systech-corp-1.gitbook.io/html-to-roblox) guide.

[PreviousUsage Tutorial](https://systech-corp-1.gitbook.io/html-to-roblox/main/usage-tutorial)[NextAPI Reference](https://systech-corp-1.gitbook.io/html-to-roblox/developers/api-reference)

Last updated 9 months ago


# CompKiller
CompKiller UI For Roblox (https://compkiller.net)

- Mobile Friendly
- Smooth
- Stable

![image](https://github.com/user-attachments/assets/b1c3a6d2-ef1f-42eb-91fe-cbdc2ce17721) ![image](https://github.com/user-attachments/assets/014e077b-0064-4d56-b0b0-d12e989e64f2)

# Usage ✨
- [**[Document 📝]**](https://cat-sus.gitbook.io/compkiller/documents/interface)
- [**[Example 🏫]**](https://github.com/4lpaca-pin/CompKiller/blob/main/examples/Full.luau)
- [**[Source Code 🔓]**](https://github.com/4lpaca-pin/CompKiller/blob/main/src/source.luau)

# Other Functions 🎖
### Icons
```lua
Compkiller:_GetIcon(<name : String>) -> Rbx AssetId : String
Icon from fontawesome
```lua
Compkiller:_GetIcon(<name : String> , true) -> Rbx AssetId : String

### Random String
```lua
Compkiller:_RandomString() -> CK=............. : String


# Inputter

**Inputter** is a fully-typed, cross-platform ROBLOX input manager for clean and efficient input handling across PC, mobile, and console devices.

## Features

- Cross-platform support (PC, Console, Mobile)
- Typed input configuration
- Easy integration with existing systems
- Supports multiple simultaneous inputs

## Installation

### Using Wally

Add the following line to your `wally.toml` dependencies:

```toml
Inputter = "adammillsy/inputter@0.1.1"

Then run:

```sh
wally install

### Manual Installation

Download a ZIP file of the module from the [GitHub repository](https://github.com/AdamMillsy/Inputter), and copy the code into your project.

## Getting Started

Require the module in your project:

```lua
local Inputter = require(Path.To.Inputter)

The following example creates a new inputter that responds to both mouse and gamepad input:

```lua
local exampleInput = Inputter.new("ExampleInput", {
    Inputter.Trigger.PRESS({
        Input = Enum.KeyCode.ButtonR2,
    }),
    Inputter.Trigger.MULTIPLE_PRESS({
        Input = Enum.UserInputType.MouseButton1,
    }, 2, 0.3),
})

exampleInput.OnActivated:Connect(function()
    print("Activated")
end)

exampleInput.OnDeactivated:Connect(function()
    print("Deactivated")
end)

Inputter automatically handles platform-specific input logic under the hood.

## Documentation

To view the documentation, please go to [this page](https://adammillsy.github.io/Inputter/).

## Why Inputter?

`UserInputService` is excellent, however most games focus on one platform before expanding to others. Inputter makes it easy to add and remove input methods, removing the complexity that the default methods provide.

## Contributing

Issues and PRs are welcome!

## TypeScript Port
A Roblox-TS port of Inputter is now available here: https://github.com/Its-a-bit-random/Inputter-TS

I am not a maintainer of this fork, but do endorse it.

## License

This project is licensed under the [MIT License](https://choosealicense.com/licenses/mit/) and maintained by **Adam Mills**.


# Leaderboard

    View docs

## Why you should use Leaderboard

Roblox developers often face challenges when implementing global leaderboards, particularly when dealing with various time periods. This library provides a streamlined solution, enabling you to create global leaderboards with just a few lines of code.

- **Time Period Support**: Leaderboard supports different time periods, including All-Time, Monthly, Weekly, and Daily leaderboards. Additionally, it provides flexibility with a custom rolling time, allowing you to choose how long the leaderboard should display.

- **Simplified Setup**: Streamline the creation of global leaderboards, eliminating the need for complex and time-consuming implementations. The library's design prioritizes ease of use and efficiency.

- **Efficient Memory Management**: Leaderboard leverages MemoryStore to surpass the limitations of OrderedDataStores. It features flexible rate limits and automatic data expiration, eliminating the need to create new stores for each time period.


### Simple

Leaderboard is so simple, you could have an Hourly, Daily, Weekly, Monthly and All Time leaderboard setup in 5 lines of code.

### Fast

Leaderboard is fast, it has been optimized to be as fast as it possibly can be without sacrificing features or functionality.

### Lightweight

Leaderboard is a lightweight performance friendly library that is designed to be as lightweight as possible.

# Leaderboard

[**View docs**](https://leaderboard.arxk.cloud/)

[](https://github.com/arxkdev/Leaderboard/actions/workflows/docs.yaml) [](https://github.com/arxkdev/Leaderboard/actions/workflows/pages/pages-build-deployment)

## Why you should use Leaderboard

Roblox developers often face challenges when implementing global leaderboards, particularly when dealing with various time periods. This library provides a streamlined solution, enabling you to create global leaderboards with just a few lines of code.

  * **Time Period Support**: Leaderboard supports different time periods, including All-Time, Monthly, Weekly, and Daily leaderboards. Additionally, it provides flexibility with a custom rolling time, allowing you to choose how long the leaderboard should display.

  * **Simplified Setup**: Streamline the creation of global leaderboards, eliminating the need for complex and time-consuming implementations. The library's design prioritizes ease of use and efficiency.

  * **Efficient Memory Management**: Leaderboard leverages MemoryStore to surpass the limitations of OrderedDataStores. It features flexible rate limits and automatic data expiration, eliminating the need to create new stores for each time period.


<source media="(prefers-color-scheme: dark)" srcset="/gh-assets/Logo.svg"></source>
      <source media="(prefers-color-scheme: light)" srcset="/gh-assets/Logo.svg"></source>

  All-in-one social framework.

## Social toolkit 🧰

With profiles, items, emotes and more, your world has everything it needs to engage players.

## Worlds network 🌐

An optional network interconnecting all worlds and allowing for more reach than possible alone.

## Happy players 🙌

A seamless social experience, hanging and roleplaying with friends and enjoying more time in-game.

## [Documentation 📄](https://rorooms.com/docs/)


# Social toolkit ð

With profiles, items, emotes and more, your world has everything it needs to engage players.


### Social toolkit 🧰

With profiles, items, emotes and more, your world has everything it needs to engage players.

### Worlds network 🌐

A universal network, interconnecting all worlds, and allowing for more reach than possible alone.

### Happy players 🙌

A seamless social experience, hopping between worlds with friends, and enjoying more time in-game.


<source media="(prefers-color-scheme: dark)" srcset="repo/shard-logo-dark.png">

Shards are a set of country groups that either roughly match up to where Roblox's server infrastructure is located or
help to group up countries that, whilst may connect to a certain server region, don't geographically exist there (for
instance, African countries tend to connect to Europe). This package helps faciliate the use of shards in games by
providing a thin API wrapper around the shard data and giving a mechanism to automatically fetch updated shard lists.

When you get a shard for a player, you can feed that into a matchmaking system to pair them up with players in the same
general region, meaning that players get better ping and experience. This is ideal for competitive or ping-dependent games,
but is also just good generally for a smoother experience for everyone. This also means that you will (in the best
conditions) create reserved servers in the best region for all of the players on a match.

In the spirit of eating our own dog food, this library is used in [Basketball: Zero](https://www.roblox.com/games/130739873848552/-)
for ranked matchmaking, and has been working extremely well, improving latency issues and matching people with others in
their own regions.

## Documentation

```lua
local Shards = require(...)

-- load the latest shard data from the default source, you should ideally do this once but
-- you can do it as many times as you like
-- NOTE: if this does fail, it will use the version of the data built in to your version of
-- the library instead
Shards.loadRemoteShardData()

-- if you want to load data from a custom source, you can do that too:
Shards.loadRemoteShardData("https://example.org/shards.json")

local shardId = Shards.getShardForPlayer(game.Players.lewisakura)
-- if you have a specific country code already (ex. trying to get the server's shard ID
-- instead), you can do that too:
Shards.getShardForCountry("US")

-- the shardId is a numerical ID representing the shard, so to get a display name, you can
-- use getShardName:
print(shardId) -- 1
print(Shards.getShardName(shardId)) -- North America

## Installation

### Wally Package

```toml
Shards = "playcurrent/shards@0.1.0"

### RBXM Module

Pop over to the [releases](https://github.com/playcurrent/shards/releases)!

## FAQ

### Why a package?

The biggest benefit is that the shard data can be updated remotely, so if an unexpected country code shows up or if
Roblox releases new server regions, we can quickly update games to start using the new entries without needing to release
a game update. Plus, it provides a small little API for people to use to make it easier.

### Why do shards have numerical IDs?

A lot of matchmaking systems actually have quite a hard time with strings. For instance, Amazon's GameLift FlexMatch
(funnily enough, what we use at BB:Z) really does not play nice with string equality in expansion rules, so a numerical
ID is provided as an alternative.

> Logo modified from Crystal Shard, under CC-BY-SA-4.0 by [Chanut is Industries](https://dribbble.com/Chanut-is-Industries)


# [shards](https://oss.playcurrent.com/shards/)

Shards are a set of country groups that either roughly match up to where Roblox’s server infrastructure is located or help to group up countries that, whilst may connect to a certain server region, don’t geographically exist there (for instance, African countries tend to connect to Europe). This package helps faciliate the use of shards in games by providing a thin API wrapper around the shard data and giving a mechanism to automatically fetch updated shard lists.

When you get a shard for a player, you can feed that into a matchmaking system to pair them up with players in the same general region, meaning that players get better ping and experience. This is ideal for competitive or ping-dependent games, but is also just good generally for a smoother experience for everyone. This also means that you will (in the best conditions) create reserved servers in the best region for all of the players on a match.

In the spirit of eating our own dog food, this library is used in [Basketball: Zero](https://www.roblox.com/games/130739873848552/-) for ranked matchmaking, and has been working extremely well, improving latency issues and matching people with others in their own regions.

## Documentation

    local Shards = require(...)

    -- load the latest shard data from the default source, you should ideally do this once but
    -- you can do it as many times as you like
    -- NOTE: if this does fail, it will use the version of the data built in to your version of
    -- the library instead
    Shards.loadRemoteShardData()

    -- if you want to load data from a custom source, you can do that too:
    Shards.loadRemoteShardData("https://example.org/shards.json")

    local shardId = Shards.getShardForPlayer(game.Players.lewisakura)
    -- if you have a specific country code already (ex. trying to get the server's shard ID
    -- instead), you can do that too:
    Shards.getShardForCountry("US")

    -- the shardId is a numerical ID representing the shard, so to get a display name, you can
    -- use getShardName:
    print(shardId) -- 1
    print(Shards.getShardName(shardId)) -- North America

## Installation

### Wally Package

    Shards = "playcurrent/shards@0.1.0"

### RBXM Module

Pop over to the [releases](https://github.com/playcurrent/shards/releases)!

## FAQ

### Why a package?

The biggest benefit is that the shard data can be updated remotely, so if an unexpected country code shows up or if Roblox releases new server regions, we can quickly update games to start using the new entries without needing to release a game update. Plus, it provides a small little API for people to use to make it easier.

### Why do shards have numerical IDs?

A lot of matchmaking systems actually have quite a hard time with strings. For instance, Amazon’s GameLift FlexMatch (funnily enough, what we use at BB:Z) really does not play nice with string equality in expansion rules, so a numerical ID is provided as an alternative.

> Logo modified from Crystal Shard, under CC-BY-SA-4.0 by [Chanut is Industries](https://dribbble.com/Chanut-is-Industries)

This site is open source. [Improve this page](https://github.com/playcurrent/shards/edit/main/README.md).


A streamlined Roblox animation utility that simplifies the use of springs,
tweens, and splines on object properties. See the API section for usage and
technical details.

## Tweens
Tweens support all properties that are supported by TweenService, as well as tweening Models by `CFrame` and tweening `NumberSequence`/`ColorSequence` values (given that the target sequence has the same number of keypoints).

```lua
.tween(object: Instance, tweenInfo: TweenInfo | {}, properties: {[string]: any}): AnimChain
.tweenFromAlpha(object: Instance, tweenInfo: TweenInfo | {}, properties: {[string]: any}, alpha: number): AnimChain
.getTweenFromInstance(object: Instance): Tween?

## Springs
Springs support the following types: `number`, `Vector2`, `Vector3`, `UDim`, `UDim2`, `CFrame`, and `Color3`. These are natively supported by the provided `Spring` class as well.

```lua
.impulse(object: Instance, springInfo: SpringInfo, properties: {[string]: any}): AnimChain
.target(object: Instance, springInfo: SpringInfo, properties: {[string]: any})
.bind(springs: {Spring}, label: string, callback: (positions: {Springable}, velocities: {Springable}) -> ())
.unbind(spring: Spring, label: string)
.createSpring(springInfo: SpringInfo, name: string?): Spring
.getSpring(name: string): Spring?

## Splines
Splines are used in animation for interpolating between a series of points in a smoothed curving fashion.

```lua
.getSpline(name: string): Spline?
.createSpline(controlPoints: {CFrame}, name: string?): Spline
.slerpTweenFromAlpha(object: Instance, tweenInfo: TweenInfo | {}, spline: Spline | {CFrame}, alignment: ("Track" | "Nodes")?, alpha: number?, waitToKill: boolean?): AnimChain


# LibreGrid

LibreGrid is an open-source grid placement solution for Roblox. It deals with all the math headaches for you and it is very intuitive and lightweight.

## Why LibreGrid?
I have been developing my world-building game [Wubby](https://www.roblox.com/games/12519560096/Wubby-TERRAIN-VR) for some time now, and the worst problem I stumbled upon was getting the proper grid calculations when the player had to place down blocks. With this open-source module, I want everyone to have a perfectly calculated, lightweight, and intuitive experience to prevent more people from descending into the rabbit hole I went through.

Every other grid module I found is either very limiting, too complex to use, or just not what I'm looking for. I would've loved it if a module like this had existed while I was first developing Wubby.

LibreGrid emulates surface-based placement (like the one that Roblox Studio offers), getting rid of all the math-related headaches that would take coding it yourself. Moreover, it allows for more customizations that developers can modify in real-time to their liking. This means that using LibreGrid, you can achieve a block-placing system (like Minecraft's), or a furniture placement system (2D placement), or a Roblox Studio-like experience.

This module results from months, if not years, of trial and error while developing Wubby.

## Features
- **Very lightweight:** 0 shapecasts, ~100 lines, everything thought with performance in mind.
- **Super intuitive:** Every function is well-documented, every type is specified, and the module only has three functions.
- **Customizable:** Allows for many grid-based systems to be created, ranging from 2D to 3D.

- **Automatically align blocks to tilted surfaces**
- **Allows custom rotations**
- **Allows *ANY* grid size, even those with decimals.**

- **100% open-source and free to use:** No attribution required but it'd be greatly appreciated! :3
- **Strictly typed** to avoid any type errors.

## Usage
Click [here](./usage.md) to check the documentation. You can also click [here](./uses.md) to check how to do different grid systems using this module.


An open-source tweening library for Roblox, featuring advanced
datatypes, customization, interpolation, and optimization.

[](https://create.roblox.com/store/asset/100081703118723)  [](https://devforum.roblox.com/t/3599638)  [](https://alexxander.gitbook.io/tweenplus)

# 🌟 More capabilities!
Experience animation in Roblox like never before.

With all the features of TweenService,
and many new and amazing features:
- Advanced networking for efficient global tweening.
- [Attributes](https://create.roblox.com/docs/scripting/attributes) support.
- Support for advanced data types:
  - Sequences.
  - Ranges.
  - Strings.
- Support for hidden properties:
  - Pivot.
  - Scale.
- Custom easing functions.
- Framerate limit control.
- Accurate color interpolation ([Oklab](https://observablehq.com/@aras-p/oklab-interpolation-test)).
- Beautiful, intuitive syntax.
- ***And much more!***

# ⚡ Fast, stable, intuitive.
- Blazingly fast, lag-free performance.
- Catches errors with clear feedback.
- Proper typing and documentation.

# Check out showcases and more information [here](https://devforum.roblox.com/t/3599638)!


1

Get the module

GitHub (recommended)

Creator Store

[See Latest Release](https://github.com/AlexanderLindholt/TweenPlus/releases/latest)

  * Download the `.rbxm` file.

  * Find the file in your file explorer.

  * Drag the file into Roblox Studio.

**Bonus:** The package will auto-update if you enable it in the `PackageLink` inside.

[Get Roblox Asset](https://create.roblox.com/store/asset/100081703118723)

  * Click `Get Model`.

  * Open the ToolBox in Roblox Studio.

  * Go to the `Inventory` tab.

  * Click on `Tween+` to insert.

2

Place it

Find a great place for the module, where other scripts can reference it.

[NextIntroduction](https://alexxander.gitbook.io/tweenplus/creation/introduction)

Last updated 3 months ago


When you require the module, it’ll return a function, which you can use to create tweens:

Copy

    local Tween = require(script.TweenPlus)

    local tween = Tween(
        workspace.Part, -- Instance to tween.
        {} -- Values to tween.
    )

You simply input all the values you would like to tween:

Copy

    local tween = Tween(
        workspace.Part,
            Position = Vector3.new(0, 10, 0),
            Color = Color3.fromRGB(255, 255, 0)
            -- And as many more as you’d like.
    )

[PreviousInstallation](https://alexxander.gitbook.io/tweenplus)[NextSupported datatypes](https://alexxander.gitbook.io/tweenplus/creation/introduction/supported-datatypes)

Last updated 3 months ago


After creating a new tween, you can use the following methods:

  * **Start**

  * **Stop**

  * **Reset**

  * **Destroy**

Example usage:

Copy

    local tween = Tween(workspace.Part, {Transparency = 1}, {Time = 2})
    tween:Start() -- Initial playback start.
    task.wait(1)
    tween:Stop() -- Stop after 1 second of playback.
    task.wait(1)
    tween:Start() -- Resume after a 1 second pause.

Copy

    local tween = Tween(workspace.Part, {Transparency = 1}, {Time = 2})
    tween:Start() -- Initial playback start.
    task.wait(1)
    tween:Reset() -- Reset after 1 second of playback.
    tween:Start() -- Start playback from the beginning again.
    task.wait(1)
    tween:Destroy() -- Throw the tween in the trash!

[PreviousPreallocations](https://alexxander.gitbook.io/tweenplus/creation/preallocations)[NextStates](https://alexxander.gitbook.io/tweenplus/tween-usage/states)

Last updated 3 months ago


Create a new ModuleScript and name it `Packets`. Make sure to [tag](https://create.roblox.com/docs/studio/properties#instance-tags) it `Packets` as well.

Then drag the `Packet` module (the networking library) inside of this new module.

The `Packets` module shall contain all of the packet definitions. It’s crucial that you include these exact packets in the module for Tween+ networking to function:

Copy

    local Packet = require(script.Packet)

    return {
        CreateTween = Packet(Packet.NumberU8, Packet.Instance, Packet.Any, Packet.Any),
        StartTween = Packet(Packet.NumberU8, Packet.Any, Packet.Any),
        StopTween = Packet(Packet.NumberU8),
        ResetTween = Packet(Packet.NumberU8),
        DestroyTween = Packet(Packet.NumberU8)

You can of course add any additional packets at any time for your own use in your game!

[PreviousNetworking library](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/network-library)[NextGlobal tweening](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/server-tweening)

Last updated 3 months ago


The options are provided in a table. You may provide any amount of options you like. Those not provided will fallback to their respective defaults.

Example:

Copy

    local tween = Tween(
        workspace.Part,
            Position = Vector3.new(0, 10, 0),
            Color = Color3.fromRGB(255, 255, 0)
        },
        { -- Options (optional).
            Time = 10,
            EasingStyle = "Sine",
            EasingDirection = "InOut"
    )

[PreviousHidden properties](https://alexxander.gitbook.io/tweenplus/creation/attributes-1)[NextOptions list](https://alexxander.gitbook.io/tweenplus/creation/customization/customization-options)

Last updated 3 months ago


Get [Packet+](https://github.com/AlexanderLindholt/PacketPlus) (my fork of Packet) from GitHub:

  * Download the latest `.rbxm` file.

  * Find the file in your file explorer.

  * Drag the file into Roblox Studio.

Check out the original Packet [DevForum](https://devforum.roblox.com/t/3573907) post to learn all about the library.

If you’re not sure why my version is better, check out why [here](https://github.com/AlexanderLindholt/PacketPlus?tab=readme-ov-file#-its-just-better).

[PreviousIntroduction](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/introduction)[NextPackets](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/packets)

Last updated 3 months ago


The server and client tween APIs basically identical, allowing you to reuse the same code on both ends. Only the `Replicated` option is server-only, obviously.

Any server tweens whose `Replicated` option has _not_ been set to `false`, will act as a global tween that replicates to all clients in the game server.

There’s a limit of 256 total global tweens at once due to optimizations.

It’s crucial that you initialize the Tween+ module on the clients by requiring it.

[PreviousPackets](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/packets)[NextHow it works](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/how-it-works)

Last updated 3 months ago


The `TweenPreallocations` attribute on the main module enables pre-sizing of the internal active tween table (default is `256`).

Only increase this if you’re starting hundreds of tweens at once and want a tiny performance boost.

[PreviousCustom easing functions](https://alexxander.gitbook.io/tweenplus/creation/custom-easing-functions)[NextPlayback and control](https://alexxander.gitbook.io/tweenplus/tween-usage/playback-and-control)

Last updated 22 days ago


_How does Tween+ consistently outperform TweenService and other libraries by such a significant margin?_

It isn't magic — it’s a huge shift in how the Client-Server bridge is handled. Instead of overwhelming the network with constant property updates, Tween+ utilizes packed data payloads and distributed interpolation.

In plain English: Instead of sending the object’s position 60 times every second, it sends one compact instruction once. The clients then do the hard work of calculating the movement locally in sync.

Additionally, there are a plethora of lower-level optimizations that take the performance even further!

Let’s break down the engineering that makes this possible!

[PreviousGlobal tweening](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/server-tweening)[NextLet the client do it](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/how-it-works/let-the-client-do-it)

Last updated 2 months ago


_If you aren’t already familiar with attributes, please check out the_ [_official explanation_](https://create.roblox.com/docs/scripting/attributes) _._

Starting a value name off with `@` will let Tween+ know that it’s an attribute. Other than that they work the same as usual properties.

Example usage of attributes:

Copy

    local tween = Tween(
        workspace.Part,
            Position = Vector3.new(0, 10, 0),
            Color = Color3.fromRGB(255, 255, 0),
            ["@Coolness"] = 10 -- Attribute named 'Coolness'.
    )

[PreviousSupported datatypes](https://alexxander.gitbook.io/tweenplus/creation/introduction/supported-datatypes)[NextHidden properties](https://alexxander.gitbook.io/tweenplus/creation/attributes-1)

Last updated 3 months ago


In Tween+, you can tween method-based properties just like normal properties.

Here’s an example:

Copy

    local tween = Tween(
        workspace.Model,
            Pivot = workspace.Model:GetPivot().CFrame -- The hidden 'Pivot' property. Read/write with `:GetPivot()` and `:PivotTo()`.
    )

Here are the supported method-based properties:

  * [Pivot](https://create.roblox.com/docs/reference/engine/classes/PVInstance#summary-methods)

  * [Scale](https://create.roblox.com/docs/reference/engine/classes/Model#Scale)

[PreviousAttributes](https://alexxander.gitbook.io/tweenplus/creation/attributes)[NextOptions](https://alexxander.gitbook.io/tweenplus/creation/customization)

Last updated 3 months ago


The following are properties representing the tween’s state:

  * **Playing**: boolean

  * **Repetitions**: number

  * **Reverse**: boolean

  * **Alpha**: number

Example:

Script1

Copy

    local tween = Tween(workspace.Part, {Transparency = 1}, {Time = 2, Repetitions = 5, Reverses = true})
    shared.MyTween = tween -- Share the tween with other scripts.
    tween:Start()

Script2

Copy

    task.wait(5)
    if shared.MyTween.Playing then
        print("Tween is still playing, wow!")
        -- Let’s print some information about the progress!
        print("Tween is going "..(if shared.MyTween.Reverses then " in reverse" else "forward").."!")
        print("Tween has done "..shared.MyTween.Repetitions.." repetitions!")
        print("Tween is exactly "..shared.MyTween.Alpha*100.."% done with the current repetition.") -- Alpha is in the range 0-1, so we multiply by 100 to get the percentage.
    else
        print("Tween is not playing anymore :(")
    end

Note that this is a rather useless example, simply to give an idea of what it does. There are actually good use cases for this of course!

[PreviousPlayback and control](https://alexxander.gitbook.io/tweenplus/tween-usage/playback-and-control)[NextSignals](https://alexxander.gitbook.io/tweenplus/tween-usage/signals)

Last updated 3 months ago


You can enable signals by installing a signal library.

[Signal+](https://devforum.roblox.com/t/3552231) is highly recommended because it’s the best.

Make sure to [tag](https://create.roblox.com/docs/studio/properties#instance-tags) the module `Signal`.

Each tween will have the following signals:

  * **Updated**

  * **Started**

  * **Stopped**

  * **Completed**

Example usage:

Copy

    local tween = Tween(workspace.Part, {Transparency = 1}, {Time = 2})
    tween.Updated:Connect(function()
        -- Alpha is in the range 0-1, so we multiply by 100 to get the percentage.
        print("Progress: "..tween.Alpha*100.."%") -- For example "Progress: 50%".
    end)
    tween:Start()

[PreviousStates](https://alexxander.gitbook.io/tweenplus/tween-usage/states)[NextIntroduction](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/introduction)

Last updated 3 months ago


Tween+ offers highly optimized networking for efficient global tweening in games.

See the main [DevForum](https://devforum.roblox.com/t/v2-tween-advanced-performant-tweening/3599638/163) post for a comparison to TweenService—the performance gap might surprise you.

[PreviousSignals](https://alexxander.gitbook.io/tweenplus/tween-usage/signals)[NextNetworking library](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/network-library)

Last updated 3 months ago


Instead of moving from `0` to `1` at a constant rate (linear), an easing function remaps time so motion isn’t constant but changing.

Usually, easing styles have 4 directions:

  * **In**: slow → fast

  * **Out**: fast → slow

  * **In-Out**: slow → fast → slow

  * **Out-In:** fast → slow → fast

Easing is crucial in animations to make them feel natural, rather than robotic, and can usually be visualized with graphs, showing the motion from A to B. Check out examples [here](https://easings.net/).

To add your own easing functions alongside the built-in ones, simply create a new module in your game, then [tag](https://create.roblox.com/docs/studio/properties#instance-tags) it `EasingFunctions`.

Here’s the required format:

Copy

    -- You can add any code here obviously :D

    return {
        -- You can either write a single direction style:
        CoolEasing = function(alpha)
            return alpha
        end,

        -- Or you can write an all directions style:
        SuperCoolEasing = {
            In = function(alpha)
                return alpha
            end,
            Out = function(alpha)
                return alpha
            end,
            InOut = function(alpha)
                return alpha
            end,
            OutIn = function(alpha)
                return alpha
            end

Tween+ will let you know if you do anything wrong!

You can always look in `Tween->Utilities->EasingFunctions` to see how the built-in ones are made. Just keep in mind they’re ultra-optimized.

[PreviousCustom defaults](https://alexxander.gitbook.io/tweenplus/creation/customization/custom-defaults)[NextPreallocations](https://alexxander.gitbook.io/tweenplus/creation/preallocations)

Last updated 2 months ago


**Property/attribute types:**

  * boolean

  * number

  * string

  * Vector2

  * Vector3

  * UDim

  * UDim2

  * Color3

  * CFrame

  * NumberRange

  * NumberSequence

  * ColorSequence

**Method-based properties:**

  * `Pivot`

  * `Scale`

[PreviousIntroduction](https://alexxander.gitbook.io/tweenplus/creation/introduction)[NextAttributes](https://alexxander.gitbook.io/tweenplus/creation/attributes)

Last updated 3 months ago


The following defaults can be overwritten by [custom defaults](https://alexxander.gitbook.io/tweenplus/creation/customization/custom-defaults).

  * **Time:** number _Default:_ `1`

  * **EasingStyle:** "Linear" | "Quad" | "Cubic" | "Quart" | "Quint" | "Sine" | "Exponential" | "Circular" | "Elastic" | "Back" | "Bounce" _Default:_ `Linear`

  * **EasingDirection:** "In" | "Out" | "InOut" | "OutIn" _Default:_ `In`

  * **RepeatCount:** number _Default:_ `0`

  * **Reverses:** boolean _Default:_ `false`

  * **DelayTime:** number _Default:_ `0`

  * **FPS:** number _Default:_ `nil`

  * **Replicate:** boolean _Default:_` false`

[PreviousOptions](https://alexxander.gitbook.io/tweenplus/creation/customization)[NextFPS](https://alexxander.gitbook.io/tweenplus/creation/customization/fps)

Last updated 3 months ago


`Replicate` is one of the many options.

The value controls whether or not the tween will be replicated to the clients (players). This option is server-only and requires specific networking [set up](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/introduction).

Useful for internal server tweens that have no reason to be attempted to be replicated.

Tween+ does not and is unable to disable Roblox’s replication. Therefore, on top of ensuring `Replicate` is set to `false`, ensure the instance doesn’t exist on any clients, otherwise Roblox will automatically replicate it every frame, leading to a lot of unnecessary network traffic.

[PreviousFPS](https://alexxander.gitbook.io/tweenplus/creation/customization/fps)[NextCustom defaults](https://alexxander.gitbook.io/tweenplus/creation/customization/custom-defaults)

Last updated 3 months ago


`FPS` is one of the many options.

It controls the playback target [FPS](https://en.wikipedia.org/wiki/Frame_rate). Defaults to infinite, meaning it will match the rest of the application.

It can be used to create a cool stop-motion effect or simply to optimize animations by lowering the framerate.

It does _not_ affect the actual target FPS of the application.

[PreviousOptions list](https://alexxander.gitbook.io/tweenplus/creation/customization/customization-options)[NextReplicate](https://alexxander.gitbook.io/tweenplus/creation/customization/replicate)

Last updated 3 months ago


You can actually replace the default defaults with your own defaults of choice.

Simply create a new module in your game, then [tag](https://create.roblox.com/docs/studio/properties#instance-tags) it `TweenDefaults`.

All you do is return a list of options whose defaults you want to modify. Here are the default defaults:

Copy

    return {
        Time = 1,

        EasingStyle = "Linear",
        EasingDirection = "In",

        DelayTime = 0,
        Reverses = false,
        RepeatCount = 0,

        FPS = nil,

        Replicate = false

You don’t need to list all options. Those not provided will stay at the default default.

Custom defaults are not verified. Therefore, be cautious of what you set them to, as they might cause errors if set incorrectly.

[PreviousReplicate](https://alexxander.gitbook.io/tweenplus/creation/customization/replicate)[NextCustom easing functions](https://alexxander.gitbook.io/tweenplus/creation/custom-easing-functions)

Last updated 3 months ago


The Roblox server is limited to 60 frames per second, and sending large amounts of data every frame is expensive, as not all clients have the bandwidth to handle it efficiently. To address this, we can transfer the hard work to the client.

But how do we ensure the client knows what to do? One solution is to synchronize tween data between the server and client. Instead of sending the tween’s output, the server only shares the internal tween parameters — such as those provided via an API like Tween+. Whenever the server creates, plays, resets, stops, or destroys a tween, it notifies the client with the necessary details.

Although there are a plethora of solutions, this one works well because it avoids sending the same data over and over again. And while this method increases the client’s workload, it also drastically reduces network traffic, and keeps tweens smooth for the players.

On Roblox unfortunately, due to the lack of ability to toggle the automatic replication, it’s unoptimal to tween like usual on the server. Here’s the workaround: we simply update the values only when a tween stops or reaches the start/finish. That way, the server stays in sync enough for most cases, while avoiding constant updates.

[PreviousHow it works](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/how-it-works)[NextRe-use data](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/how-it-works/re-use-data)

Last updated 2 months ago


To optimize further, we have to understand how data is represented in computers.

Bits are essentially switches, which live in our computers, and are used to represent all data. A boolean for example, can be stored with just a single bit. For more complex data, we have to use more bits, where each combination of the bits represent different data. It’s important to note that bits are stored in groups of 8, called bytes — for this reason, we can’t go below 8 bits per data element, and we are also forced to use increments of 8 — for example, a boolean, despite being just a single bit, will end up taking up 8 bits (1 full byte).

If we look closer at the bits, we often find unnecessary ones. For example, by default in Luau (Roblox’s programming language), numbers are usually stored as Float64s. `Float` meaning it can contain decimals, and `64` meaning it uses 64 bits to store the number. Since there’s no `U` in front, that means it’s signed, meaning it can store negative values too. The issue is that we don’t need negative values, decimals and 64 whole bits just to store the number `1`, for example.

A Float64 includes an insane range of numbers all the way down to `-1.7976931348623157 x 10^308` and all the way up to `1.7976931348623157 x 10^308`, with up to about 16 decimal digits. In many cases, that’s overkill. Therefore, we can lower the amount of bits used to represent the data.

One example of this optimization principle, is the Tween+ server tween identifiers, which are intentionally limited to the range 0-255, because that’s the range of a UInt8 (unsigned 8-bit integer). This means a maximum of 256 server tweens at once, but also means reduced network traffic.

Keep in mind that compression isn’t limited to numbers — it can be all sorts of data!

But there’s specific data that’s often overlooked.

For example, every time we send something over the network, we also send the identifier for the event, so the client knows which event we’re talking about — for example, we might have to inform the client that we’re firing the `StartTween` event — that’s what happens behind the scenes when you fire a RemoteEvent in Roblox. Therefore, it’s best to minimize the amount of event fires.

If we just send everything through the same event, we can just fire that one event no more than 1 time a frame by combining all of the data, allowing us to store the event identifiers how we want, which can result in slightly further reduced data if multiple events fire in the same frame.

There you go. Those were the main principles behind the networking library Packet (and its fork, Packet+), which Tween+ relies on for its global tweens feature – albeit it’s far more complex behind the scenes.

[PreviousRe-use data](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/how-it-works/re-use-data)[NextOutroduction](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/how-it-works/outroduction)

Last updated 2 months ago


Sometimes we can avoid sending certain data, as we may use other data to calculate it.

For example, when a player joins mid-tween, we want to inform them of how many repetitions we’ve done already. You might think we should also inform the client of whether or not we’re going in reverse at the moment. But we can actually utilize some simple math in this case:

Since we already have the repetition count, we can use that to calculate the direction we’re moving in. It’s merely a simple check to see if the repetition count is odd or even — if it’s odd, we’re going in reverse, otherwise we’re not.

This simple principle of re-using data can be applied in many other cases as well. Small optimizations like these add up, and can result in greatly reduced network traffic together.

[PreviousLet the client do it](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/how-it-works/let-the-client-do-it)[NextCompress the data](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/how-it-works/compress-the-data)

Last updated 3 months ago


If you’re interested in learning more, you can inspect the Tween+ source code on [GitHub](https://github.com/AlexanderLindholt/TweenPlus) at any time. That way you can see exactly how everything works in detail.

The network library’s source code can also be found at [its GitHub](https://github.com/AlexanderLindholt/PacketPlus).

Thanks for reading. If you have any questions, make sure to let me know — I’ll be happy to help.

[PreviousCompress the data](https://alexxander.gitbook.io/tweenplus/global-tweens-and-networking/how-it-works/compress-the-data)

Last updated 2 months ago


### Roblox - Supabase Client

        A comprehensive, type-safe Supabase client for Roblox Luau, providing full access to PostgREST API, Storage, and Edge Functions. Built specifically for Roblox's server-side environment with Rojo workflow compatibility.

        Read the docs

# Disclaimer

This project still has a lot of work to be done. Do not use it for production uses just yet.


# Roblox Supabase

A comprehensive, type-safe Supabase client for Roblox Luau, providing full access to PostgREST API, Storage, and Edge Functions. Built specifically for Roblox's server-side environment with Rojo workflow compatibility.

[See Docs](https://roblox-supabase.vercel.app/docs)


# Introduction

A comprehensive, type-safe Supabase client for Roblox Luau, providing full access to PostgREST API, Storage, and Edge Functions. Built specifically for Roblox's server-side environment with Rojo workflow compatibility.

This reference documentation covers every method and capability available in the Roblox Supabase Client, a Luau implementation of Supabase's JavaScript library specifically designed for Roblox Studio.

Feel free to support my work by following my [Roblox profile](https://www.roblox.com/users/925308243/profile).

This module is still under development!

There might be bugs or missing features for now.

If you wish to help me develop this, please see the [contributions docs](https://roblox-supabase.vercel.app/docs/contribute).

# Features

### PostgREST API Support

  * **Filter Operations**: Equality, inequality, comparison (gt, lt, gte, lte)
  * **Text Search**: `like()`, `ilike()`, full-text search with generated columns
  * **Array Operations**: `contains()`, `containedBy()`, `overlaps()`
  * **JSON Operations**: JSONB containment, partial matching
  * **Range Operations**: Date, integer, numeric, and timestamp range queries
  * **NULL Handling**: `is()`, `isNot()` for null/not-null checks
  * **IN Operations**: Multiple value matching with `in_()`

### Query Capabilities

  * **Complex Filtering**: Combine multiple conditions with AND/OR logic
  * **Modifiers**: Ordering, limiting, pagination (`range()`)
  * **Response Formats**: CSV, minimal returns, single/maybeSingle row retrieval
  * **Compound Queries**: Filter chains with proper precedence

### PostgreSQL RPC Support

  * **Function Calls**: Execute PostgreSQL functions with `rpc()`
  * **Parameter Support**: Pass parameters as JSON objects
  * **Method Flexibility**: Use POST (default) or GET for immutable functions
  * **Filter Chaining**: Apply filters to functions returning tables
  * **Full Modifier Support**: Ordering, limiting, single row retrieval on RPC results

### Data Mutations

  * **CRUD Operations**: `insert()`, `update()`, `upsert()`, `delete()`
  * **Batch Operations**: Multi-row inserts and updates
  * **Conditional Updates**: Update with WHERE clauses

### Edge Functions

  * **Function Invocation**: `invoke()` with payload support
  * **Error Handling**: Proper error responses for missing functions
  * **Type Safety**: Structured request/response handling

[InstallationInstall Roblox Supabase on your Roblox Studio project or using Rojo.](https://roblox-supabase.vercel.app/docs/installation)


# Filter Methods

Learn how to use filter methods to refine your queries in the Roblox Supabase client.

Filter methods must be used BEFORE Modifier methods.

Filter methods are available in the [`SelectFilterStage`](https://roblox-supabase.vercel.app/docs/types#selectfilterstage), [`UpdateFilterStage`](https://roblox-supabase.vercel.app/docs/types#updatefilterstage), [`DeleteFilterStage`](https://roblox-supabase.vercel.app/docs/types#deletefilterstage), and [`RPCFilterStage`](https://roblox-supabase.vercel.app/docs/types#rpcfilterstage). All filter methods are **chainable** within their respective filter stages and return the same stage type for unlimited method chaining.

## Filter Method Types

### `eq(column: string, value: any)`

Prop

Type

`eq?`function(column: string, value: any)

The `eq` method filters rows where the specified column's value is equal to the provided value.

    -- Get players with level 10
    local players, error = client
        :from("players")
        :select("*")
        :eq("level", 10)
        :execute()

### `neq(column: string, value: any)`

Prop

Type

`neq?`function(column: string, value: any)

The `neq` method filters rows where the specified column's value is NOT equal to the provided value.

    -- Get all players except those with level 1
    local players, error = client
        :from("players")
        :select("*")
        :neq("level", 1)
        :execute()

### `gt(column: string, value: any)`

Prop

Type

`gt?`function(column: string, value: any)

The `gt` method filters rows where the specified column's value is greater than the provided value.

    -- Get players with level greater than 50
    local highLevelPlayers, error = client
        :from("players")
        :select("*")
        :gt("level", 50)
        :execute()

### `gte(column: string, value: any)`

Prop

Type

`gte?`function(column: string, value: any)

The `gte` method filters rows where the specified column's value is greater than or equal to the provided value.

    -- Get players with level 50 or higher
    local highLevelPlayers, error = client
        :from("players")
        :select("*")
        :gte("level", 50)
        :execute()

### `lt(column: string, value: any)`

Prop

Type

`lt?`function(column: string, value: any)

The `lt` method filters rows where the specified column's value is less than the provided value.

    -- Get players with level less than 10
    local newPlayers, error = client
        :from("players")
        :select("*")
        :lt("level", 10)
        :execute()

### `lte(column: string, value: any)`

Prop

Type

`lte?`function(column: string, value: any)

The `lte` method filters rows where the specified column's value is less than or equal to the provided value.

    -- Get players with level 10 or lower
    local lowLevelPlayers, error = client
        :from("players")
        :select("*")
        :lte("level", 10)
        :execute()

### `like(column: string, pattern: string)`

Prop

Type

`like?`function(column: string, pattern: string)

The `like` method performs case-sensitive pattern matching using SQL's LIKE operator.

    -- Find usernames starting with 'john'
    local players, error = client
        :from("players")
        :select("username")
        :like("username", "john%")
        :execute()

### `ilike(column: string, pattern: string)`

Prop

Type

`ilike?`function(column: string, pattern: string)

The `ilike` method performs case-insensitive pattern matching using SQL's ILIKE operator.

    -- Find usernames containing 'admin' (case-insensitive)
    local admins, error = client
        :from("players")
        :select("username")
        :ilike("username", "%admin%")
        :execute()

### `is(column: string, value: boolean | "null")`

Prop

Type

`is?`function(column: string, value: boolean | "null")

The `is` method checks for NULL values or boolean equality.

    -- Find players without an email
    local noEmailPlayers, error = client
        :from("players")
        :select("*")
        :is("email", "null")
        :execute()

    -- Find active players (assuming 'active' column is boolean)
    local activePlayers, error = client
        :from("players")
        :select("*")
        :is("active", true)
        :execute()

### `in_(column: string, values: {any})`

Prop

Type

`in_?`function(column: string, values: {any})

The `in_` method checks if a column's value is in a specified list of values.

    -- Find players with specific IDs
    local specificPlayers, error = client
        :from("players")
        :select("*")
        :in_("id", {1, 2, 3, 5, 8})
        :execute()

    -- Find players in specific levels
    local levelPlayers, error = client
        :from("players")
        :select("*")
        :in_("level", {10, 20, 30, 40})
        :execute()

### `contains(column: string, value: any)`

Prop

Type

`contains?`function(column: string, value: any)

The `contains` method checks if an array or range column contains the specified value.

    -- Find players who have 'admin' in their roles array
    local admins, error = client
        :from("players")
        :select("*")
        :contains("roles", {"admin"})
        :execute()

    -- Find items in price range [10, 100]
    local midRangeItems, error = client
        :from("items")
        :select("*")
        :contains("price_range", "[10,100]")
        :execute()

### `containedBy(column: string, value: any)`

Prop

Type

`containedBy?`function(column: string, value: any)

The `containedBy` method checks if an array or range column is contained by the specified value.

    -- Find players whose roles are a subset of ['user', 'vip', 'admin']
    local subsetPlayers, error = client
        :from("players")
        :select("*")
        :containedBy("roles", {"user", "vip", "admin"})
        :execute()

### `rangeGt(column: string, range: string)`

Prop

Type

`rangeGt?`function(column: string, range: string)

The `rangeGt` method checks if a range column is strictly greater than the specified range.

    -- Find bookings that start after January 2024
    local futureBookings, error = client
        :from("bookings")
        :select("*")
        :rangeGt("booking_period", "[2024-01-01,2024-01-31]")
        :execute()

### `rangeGte(column: string, range: string)`

Prop

Type

`rangeGte?`function(column: string, range: string)

The `rangeGte` method checks if a range column is greater than or equal to the specified range.

    -- Find bookings from January 2024 or later
    local januaryPlusBookings, error = client
        :from("bookings")
        :select("*")
        :rangeGte("booking_period", "[2024-01-01,2024-01-31]")
        :execute()

### `rangeLt(column: string, range: string)`

Prop

Type

`rangeLt?`function(column: string, range: string)

The `rangeLt` method checks if a range column is strictly less than the specified range.

    -- Find bookings that end before January 2024
    local pastBookings, error = client
        :from("bookings")
        :select("*")
        :rangeLt("booking_period", "[2024-01-01,2024-01-31]")
        :execute()

### `rangeLte(column: string, range: string)`

Prop

Type

`rangeLte?`function(column: string, range: string)

The `rangeLte` method checks if a range column is less than or equal to the specified range.

    -- Find bookings up to January 2024
    local uptoJanuaryBookings, error = client
        :from("bookings")
        :select("*")
        :rangeLte("booking_period", "[2024-01-01,2024-01-31]")
        :execute()

### `rangeAdjacent(column: string, range: string)`

Prop

Type

`rangeAdjacent?`function(column: string, range: string)

The `rangeAdjacent` method checks if a range column is adjacent to (immediately before or after) the specified range.

    -- Find bookings adjacent to January 2024 (December 2023 or February 2024)
    local adjacentBookings, error = client
        :from("bookings")
        :select("*")
        :rangeAdjacent("booking_period", "[2024-01-01,2024-01-31]")
        :execute()

### `overlaps(column: string, value: any)`

Prop

Type

`overlaps?`function(column: string, value: any)

The `overlaps` method checks if a range or array column overlaps with the specified value.

    -- Find bookings that overlap with January 2024
    local overlappingBookings, error = client
        :from("bookings")
        :select("*")
        :overlaps("booking_period", "[2024-01-01,2024-01-31]")
        :execute()

    -- Find players with overlapping tag arrays
    local similarPlayers, error = client
        :from("players")
        :select("*")
        :overlaps("tags", {"rpg", "fantasy"})
        :execute()

### `match(query: {[string]: any})`

Prop

Type

`match?`function(query: {[string]: any})

The `match` method performs full-text search using PostgreSQL's full-text search capabilities.

    -- Search for players with specific attributes
    local matchedPlayers, error = client
        :from("players")
        :select("*")
        :match({
            username = "john",
            email = "@gmail.com"
        })
        :execute()

### `not_(column: string, operator: string, value: any)`

Prop

Type

`not_?`function(column: string, operator: string, value: any)

The `not_` method negates a filter condition using the specified operator.

    -- Find players NOT with level 10
    local notLevel10, error = client
        :from("players")
        :select("*")
        :not_("level", "eq", 10)
        :execute()

    -- Find players NOT in levels 1-10
    local notLowLevel, error = client
        :from("players")
        :select("*")
        :not_("level", "lte", 10)
        :execute()

### `filter(column: string, operator: string, value: any)`

Prop

Type

`filter?`function(column: string, operator: string, value: any)

The `filter` method provides a generic way to apply filters with custom operators.

    -- Equivalent to :eq("level", 10)
    local level10Players, error = client
        :from("players")
        :select("*")
        :filter("level", "eq", 10)
        :execute()

    -- Using a less common operator
    local specialFilter, error = client
        :from("items")
        :select("*")
        :filter("price", ">=", 100)
        :execute()

### `or_(filters: string, options: OrFilterOptions?)`

Prop

Type

`or_?`function(filters: string, options: OrFilterOptions?)

The `or_` method combines multiple filter conditions with OR logic.

    -- Find players who are either level 10 OR have VIP status
    local specialPlayers, error = client
        :from("players")
        :select("*")
        :or_("level.eq.10,status.eq.vip")
        :execute()

    -- Find items in specific categories OR above certain price
    local filteredItems, error = client
        :from("items")
        :select("*")
        :or_("category.in.(weapons,armor),price.gte.1000")
        :execute()

## Chaining Multiple Filters

All filter methods can be chained together, and they use AND logic by default:

    -- Find active players with level between 20 and 50 who joined recently
    local filteredPlayers, error = client
        :from("players")
        :select("*")
        :eq("status", "active")          -- status = 'active'
        :gte("level", 20)                -- AND level >= 20
        :lte("level", 50)                -- AND level <= 50
        :gte("created_at", "2024-01-01") -- AND created_at >= '2024-01-01'
        :order("level", { ascending = false })
        :limit(10)
        :execute()

## Combining AND and OR Logic

Use `or_()` within a chain to create OR conditions within an AND context:

    -- Find players who are:
    -- 1. Active AND (level 10 OR VIP status)
    -- 2. Created in 2024
    local complexQuery, error = client
        :from("players")
        :select("*")
        :eq("active", true)
        :or_("level.eq.10,status.eq.vip")
        :gte("created_at", "2024-01-01")
        :execute()

## Type Safety with Filter Methods

All filter methods maintain type safety through the [`FilterStage<Next>`](https://roblox-supabase.vercel.app/docs/FiltersAndModifiers/docs/types#filterstagenext) generic type. This ensures that:

  * Filter methods can only be called on appropriate stages
  * Method chaining preserves the correct return types
  * You get IntelliSense support in Roblox Studio

## Error Handling

Filter methods will return errors if:

  * The column doesn't exist
  * The value type doesn't match the column type
  * Invalid operator is used
  * Syntax errors in `or_()` filter strings

Always check the error return value:

    local result, err = client
        :from("players")
        :select("*")
        :eq("nonexistent_column", "value") -- This will error
        :execute()

    if err then
    warn("Filter error:", err)
    -- Handle error appropriately
    end

[Call a PostgreSQL FunctionInvoke PostgreSQL functions (stored procedures) using the Supabase client.](https://roblox-supabase.vercel.app/docs/Database/call-postgres-function)[Modifier MethodsLearn how to use modifier methods to refine and control query results in the Roblox Supabase client.](https://roblox-supabase.vercel.app/docs/FiltersAndModifiers/modifiers)