The next evolution of interface programming on Roblox

Mess-Free Backend

No more dependency messes, difficult readability, or strict formatting. Don't get pulled back by individual design philosophies you are forced to agree with, and enter a world where YOUR code comes first.

Easy To Learn

Seam is built for beginners, inspired by the Fusion syntax, and powered by simplicity. Quickly learn Seam, and integrate it into to your projects without friction. It's stress-free onboarding and easy to use across a team of any size.

Animate Fluidly

Animate using tweens, springs, or computes to create bounce, squash, swing, or whatever you want, to your heart's content. Never be limited by vanilla interface animation again.

Light As Feathers

Your project deserves an interface framework that doesn't strain the rest of your code. Free up some space for what really matters in your codebase.

It's time to make UI better

It's open-source and free, so give it a spin and see what you think.

Getting Started

Jump straight into Studio and import the module from the release page on GitHub, or alternatively, copy over the source code yourself. Roblox toolbox model coming soon!

Then, learn how to use it! If you're new, take a look at the intro tutorial, or if you're more technical and ready, take a look at the Seam documentation.

Seam is an unfinished product and does not yet have a tutorial. For now, read the documentation!

Before You Begin

Make sure you take a look at the tutorial to see how you set up your project and use everything!

Navigate

States

Reactive states for animation, input, and value simplification.

Memory

Manual and automatic cleanup, preventing memory leaks.

Connections

Signal-based reactivity based on given input.

Preset Components

[NOT YET DOCUMENTED] Out-of-the-box components you can use with From().

Spring

An animation state using the spring method

TypeSinceScoped
State0.0.1Yes

Constructor

Spring(Target : Value | any, Speed : number, Dampening : number)

Properties

Value : any

The position of the spring.

Velocity : any

The velocity of the spring.

Target : Value | any

The target value that the spring position should reach.

Dampening : number

A value between 0 and 1 describing the friction of the spring. Going over 1 applies overdamping.

Speed : number

The speed of the spring.

Events

Changed

Fired when the value of the spring changes.

Usage

Springs are animation objects that simulate hooke’s law in any Roblox type. There are four types of springs:- Undamped (dampening = 0)
- Underdamped (1 > dampening > 0)
- Critically damped (dampening = 1)
- Overdamped (dampening > 1)
Each of these provide different levels of simulated friction, with undampended being the least and overdamped being the most. Critically damped springs create just enough friction to have no “bounce”.Springs can be created on their own, like this:

Or as a property of a hydrated Seam object, like this:

Tween

An animation state using the tween method

TypeSinceScoped
State0.0.1Yes

Constructor

Tween(Target : Value | any, TweenInfo : TweenInfo)

Properties

Value : any

The position of the tween.

Target : Value | any

The target that the tween should reach.

TweenInfo : TweenInfo

The TweenInfo associated with the tween object.

Events

Changed

Fired when the value of the tween changes.

Usage

Or as a property of a hydrated Seam object, like this:

Computed

A reactive state that updates based on when other values update

TypeSinceScoped
State0.0.1Yes

Constructor

Computed(CalculationFunction : (Use : (Value : Value) -> Value.Value) -> nil)

Properties

Value : any

The current value of the compute.

Usage

Computed acts as a state that is updated every frame. For example, if you want the x-position of a frame instance to be based on a number value, then you can do:

Computeds can be created on their own, like this:

Or embedded like this:

Value

A core state representing a single value that can be set or read at any time

TypeSinceScoped
State0.0.1Yes

Constructor

Value(Value : any)

Properties

Value : any

The value of the value object. Can be either set or read.

Events

Changed

Fired when .Value changes

Usage

To create a value object, simply call Value(), passing in any value type. In this case, we will be doing a number.

Value objects can lead to a reaction in another state. For example, in either springs or tweens, you can pass a value object in the first parameter. If you do, updating the value updates the animation.

Values can also be used in computeds to update calculations, like so:

New

Constructs a Roblox instance, or hydrates an existing one with Seam states

TypeSinceScoped
Declaration0.0.1Yes

Constructor

New(Object : string | Instance, Properties : {[any] : any}, From : From?) -> Instance

Usage

New is the heart of Seam, giving everything the framework functionality. It’s a constructor to make new instances, or hydrate existing ones.To make a brand new instance, use New like this:

Or alternatively, hydrate an existing instance by replacing the string with the instance you want, like this:

There are three parameters: object (as a string or instance), properties (as a dictionary), and optionally a common component (read more about From() to learn about this third parameter).You can use states and other declarations with New. Read more about it in the rest of the documentation!

Children

Declares children of an instance when paired with New()

TypeSinceScoped
Declaration0.0.1No

Usage

Children is used as in index in the New constructor to declare the children of said instance. It’s used like this:

If you wanted children to be more reactive/dynamic, you can alternatively pass in a Computed() state. When the computed instance updates, it will update the children. For this to work, Computed() must return a table of instances every time.

DeclareComponent

A simple constructor/callback to tell Seam that you made a component

TypeSinceScoped
Declaration0.0.1No

Constructor

DeclareComponent(ComponentName : string, Constructor : (HydratedInstance : Instance, ...any) -> Instance)

Usage

DeclareComponent is used to declare components that you can later use. Components declared with this function can be called back to by using From.Let’s assume we want to declare a component that turns a frame into a blue one. We can declare this component by typing:

To use this, we can later use From, like so:

From

Uses a preset or declared component

TypeSinceScoped
Declaration0.0.1Yes

Constructor

From(ComponentName : string)

Usage

From is a callback used in the New constructor to call back to an already-declared component. You can read about this in the documentation for DeclareComponent.

Scope

A core memory manager in Seam

TypeSinceScoped
Memory0.0.1No

Constructor

Scope {[ObjectName : string] = Object : SeamScopableObject}

Methods

InnerScope() -> Scope

Returns an inner scope, which a sub-scope derived from the main scope.

Destroy() -> nil

Destroys the scope and cleans up all descendants.

Usage

Scope is a janitor-like organization object that groups instances together. Anything created with a Scope-declared Seam object will be cleaned up when the scope itself is destroyed.To make a scope, you declare what Seam objects you want to include. Be weary that an object must be marked as scopable, otherwise you will get an error.

You can also create a generic scope, inheriting all methods, like this:

In this example, you can make an object with the scope by calling Scope:New:

Let’s continue this example. Let’s say we want to create a child group of frames. To do so, we can call InnerScope():

And we can use it the same way:

If we want to clean up the frames in this example, we can call FramesScope:Destroy(). Alternatively, or in addition, we can also call MyScope:Destroy().

OnChanged

Used to track changes in states or instances

TypeSinceScoped
Connection0.0.1Yes

Usage

OnChanged is an Seam index to be used in the New constructor. OnChanged detects when an instance changes, e.g. when it changes color or size.You can use it like so:

You can also track states, like so:

OnEvent

Used to track any events in a Roblox instance

TypeSinceScoped
Connection0.0.1Yes

Usage

OnEvent is an Seam index to be used in the New constructor. OnEvent detects a specified rbx event that could be fired.You can use it like so:

Rendered

A reactive state that force-updates every frame

TypeSinceScoped
State0.0.3Yes

Constructor

Rendered(CalculationFunction : () -> Value.Value) -> nil)

Properties

Value : any

The current value of the render.

Usage

Similar to Computed(), Rendered() acts as an ever-changing reactive state. However, it does not include the Use() method, and instead can react to any userdata. As such, it force-updates every RunService.RenderStepped.

Lifetime

Forces new and hydrated instances to be temporary.

TypeSinceScoped
Declaration0.0.3No

Usage

Usage is simple; when using New(), set an index to [Lifetime], with a value equal to the lifetime in seconds.

FollowProperty

Tracks property changes and propagates updated userdata to states.

TypeSinceScoped
Declaration0.0.3No

Usage

Using it as a constructor index, declare FollowProperty() with a string parameter matching the property name you want followed, and set the value to the value you want updated.

FollowAttribute

Tracks attribute changes and propagates updated userdata to states.

TypeSinceScoped
Declaration0.0.3No

Usage

Similarly to FollowProperty(), it as a constructor index; declare FollowAttribute() with a string parameter matching the attribute name you want followed, and set the value to the value you want updated.

Attribute

Sets an object's attribute to any value

TypeSinceScoped
Declaration0.0.3No

Usage

When using New(), you can input property names and associate them with any values. However, if you want to set an attribute instead, you can use Attribute(), like so:

OnAttributeChanged

Used to track attribute changes in states or instances

TypeSinceScoped
Connection0.0.3Yes

Usage

OnChanged is an Seam index to be used in the New constructor. OnChanged detects when an instance changes, e.g. when it changes color or size. Similarly, OnAttributeChanged tracks changes from attributes, with a key difference being that you can declare what attribute should be tracked.You can use it like so: