diff --git a/README.md b/README.md
index f9d14c3..09bad6a 100644
--- a/README.md
+++ b/README.md
@@ -1,54 +1,14 @@
# Notice
-The library is currently in a very early development stage, with breaking changes being made often, out of date documentation and no versioning. Not recommended for use.
-
-
+The library is currently in a very early development stage, with breaking
+changes being made often, out of date documentation and no versioning. Not
+recommended for use.
# Vide
-Vide is a declarative, reactive Luau library for building user interfaces on Roblox.
+Vide is a declarative, reactive Luau library for building user interfaces on
+Roblox.
-## API Reference
+- ### [API Reference](docs/api/index.md)
-### [Reactivity: Core](docs/api/reactivity-core)
-
-- [wrap()](docs/api/reactivity-core#wrap)
-- [derive()](docs/api/reactivity-core#derive)
-- [foreach()](docs/api/reactivity-core#wrap)
-- [match()](docs/api/reactivity-core#match)
-- [watch()](docs/api/reactivity-core#watch)
-
-### [Reactivity: Utility](docs/api/reactivity-utility)
-
-- [isState()](docs/api/reactivity-utility#isState)
-- [unwrap()](docs/api/reactivity-utility#unwrap)
-- [readonly()](docs/api/reactivity-utility#readonly)
-- [mutate()](docs/api/reactivity-utility#mutate)
-
-### [Element Creation](docs/api/creation)
-
-- [create()](docs/api/creation#create)
-- [apply()](docs/api/creation#apply)
-- [Layout](docs/api/creation#Layout)
-- [Children](docs/api/creation#Children)
-- [Event](docs/api/creation#Event)
-- [Changed](docs/api/creation#Changed)
-- [Bind](docs/api/creation#Bind)
-- [Created](docs/api/creation#Created)
-
-### [Animation](docs/api/animation)
-
-- [spring()](docs/api/animation#spring)
-
-### [Types](docs/api/types)
-
-- [State](docs/api/types#State)
-- [Prop](docs/api/types#Prop)
-
-
-
-## Tutorials
-
-### [Crash Course](docs/tutorials/crash-course)
-
-### [Reactive Graph](docs/tutorials/reactive-graph)
+- ### [Crash Course](docs/tut/crash-course/1-introduction.md)
diff --git a/docs/api/index.md b/docs/api/index.md
new file mode 100644
index 0000000..6846cef
--- /dev/null
+++ b/docs/api/index.md
@@ -0,0 +1,22 @@
+# API Reference
+
+### [Reactivity: Core](../api/reactivity-core.md)
+
+- [source()](../api/reactivity-core.md#source)
+- [derive()](../api/reactivity-core.md#derive)
+- [map()](../api/reactivity-core.md#map)
+- [watch()](../api/reactivity-core.md#watch)
+
+### [Reactivity: Utility](../api/reactivity-utility.md)
+
+- [cleanup()](../api/reactivity-utility.md#cleanup)
+
+### [Element Creation](../api/creation.md)
+
+- [create()](../api/creation.md#create)
+
+### [Animation](../api/animation.md)
+
+- [spring()](../api/animation.md#spring)
+
+### [Strict Mode](../api/strict.md)
diff --git a/docs/tut/crash-course.md b/docs/tut/crash-course.md
deleted file mode 100644
index 2f0c3a0..0000000
--- a/docs/tut/crash-course.md
+++ /dev/null
@@ -1,351 +0,0 @@
-# Vide Crash Course
-
-This is a brief tutorial designed to give you a quick run through the usage of
-Vide.
-
-Vide is largely inspired by Solid and Fusion.
-
-
-
-## Why Vide?
-
-Creating UI is a slow and tedious process. The purpose of Vide is to make UI
-declarative and concise, making it faster to create and more importantly easier
-to maintain. Vide achieves this using a reactive style of programming which
-allows you to focus on the flow of data through your application without
-worrying about manually updating UI instances.
-
-Some of the main focuses behind Vide's design choices:
-
-- Concise syntax to reduce verbosity as much as possible.
-- Reducing the amount of imports needed for usage by using Luau's syntax and
- semantics.
-- Being completely typecheckable.
-- Flexibility, particularly with integrating other libraries.
-
-## Creating UI Instances
-
-Instances are created using [`create()`](../api/creation#create).
-
-```lua
-local vide = require(vide)
-local create = vide.create
-```
-
-```lua
-local frame = create "Frame" {
- Name = "Background",
- Position = UDim2.fromScale(0.5, 0.5)
-}
-```
-
-`create()` returns a constructor for a given class which then takes a table of
-properties to assign when creating a new instance for that class.
-
-String keys are assumed to be properties, integer keys are assumed to be
-children.
-
-```lua
-create "ScreenGui" {
- Parent = game.StarterGui,
-
- create("Frame") {
- AnchorPoint = Vector2.new(0.5, 0.5),
- Position = UDim2.fromScale(0.5, 0.5),
- Size = UDim2.fromScale(0.4, 0.7),
-
- create("TextLabel") {
- Text = "hi"
- },
-
- create("TextLabel") {
- Text = "bye"
- }
- }
-}
-```
-
-To connect to an event, just set the event property name to a function.
-
-```lua
-create "TextButton" {
- Activated = function()
- print "clicked!"
- end
-}
-```
-
-All event arguments are passed into the function.
-
-
-
-## State
-
-State in Vide are special objects that store data.
-
-A state object in Vide can be created using
-[`source()`](../api/reactivity-core#source).
-
-```lua
-local source = vide.source
-```
-
-```lua
-local visible = source(false)
-
-local image = create("ImageLabel") {
- Visible = visible -- bind property to state
-}
-
-visible(false) -- image label is hidden
-
-visible(true) -- image label is shown
-```
-
-`source()` creates a new data source which can be set by calling it with the new
-value to set.
-
-Any time the value is set, anything depending on it will automatically be
-updated using the new value.
-
-Vide detects when you assign a state object as a property value. This is known
-as *binding* and doing so will cause the property to *automatically* update
-whenever that state object's value is changed.
-
-You as the programmer do not have to worry about manually updating variables or
-UI instances, you can just focus on defining how the data maps to UI and
-everything will update when changes occur.
-
-
-
-## Derived State
-
-You can create new state from other states. This is known as *deriving state*.
-
-```lua
-local count = source(0)
-
-local function text()
- return "count: " .. count()
-end
-
-create "TextLabel" {
- Text = text
-}
-```
-
-To read from a state, you call without any arguments which returns its stored
-value.
-
-Assigning a non-event property a function will bind that property to that
-function, anytime a state being read from inside that function is changed, the
-function will be re-ran and the property value updated.
-
-Sometimes when using expensive computations to derive state, you only want to
-recalculate it when a source state has changed.
-
-```lua
-local derive = vide.derive
-```
-
-```lua
-local count = source(0)
-
-local factorial = derive(function()
- local n = 1
- for i = 2, count() do
- n *= i
- end
- return n
-end)
-```
-
-`derive()` will cache and return the same value until a source state has
-changed, where it will recompute and cache a new value.
-
-```lua
-create "TextLabel" {
- Text = function()
- return "factorial: " .. factorial()
- end
-}
-
-count(3) -- displays "factorial: 6"
-count(4) -- displays "factorial: 24"
-```
-
-
-
-## Components
-
-Components are custom-made reusable pieces of UI made from other pieces of UI.
-
-```lua
-local function Background(args)
- return create("Frame") {
- BackgroundColor3 = Color3.new(0, 0, 0),
- Position = args.Position,
- Size = args.Size
- }
-end
-
-local background = Background {
- Position = UDim2.new(),
- Size = UDim2.new()
-}
-```
-
-Above is a simple example of a frame component with its background color set to
-black.
-
-A single parameter `args` is used to pass properties to the component.
-
-Components allow you to *encapsulate* behavior. You can only modify the
-component in ways that you allow in the component.
-
-This also promotes code reusability. Anytime you want a black frame all you do
-is call `Background {}` instead of creating a new frame and settings it color
-each time.
-
-
-
-## Stateful components
-
-Often, you need components that maintain their own internal state, such as a
-toggle-able button or a counter.
-
-Below you can see how a simple counter component can be implemented.
-
-```lua
-local function Counter()
- local count = source(0)
-
- return create "TextButton" {
- Text = function()
- return "count: " .. count()
- end
-
- Activated = function()
- count(count() + 1)
- end,
- }
-end
-```
-
-Each time you call `Counter {}`, it will create a new counter component which
-each maintains their own count state.
-
-Clicking on the UI element will automatically increment and display its count.
-
-## Nested Properties and Typechecking
-
-When a key is assigned a table, Vide does not attempt to assign it to a
-property, instead, the table is iterated and processed just like the nesting
-table.
-
-Below is an example of how you can use this to pass groups of similar properties
-together such as position and size, while also using typechecking.
-
-```lua
-type Layout = {
- Layout = {
- Position: UDim2?,
- Size: UDim2?,
- AnchorPoint: Vector2?
- }
-}
-
-local function Button(args: Layout & {
- Text: string,
- Callback: () -> ()
-})
- local count = source(0)
-
- return create "TextButton" {
- Text = args.Text
- Activated = args.Callback,
- Layout = args.Layout
- }
-end
-
-Button {
- Text = "Click me!",
-
- Callback = function()
- print "clicked me!"
- end,
-
- Layout = {
- Position = UDim2.new(),
- Size = UDim2.new()
- }
-}
-```
-
-Here the button component is assigned a position and size as if you passed those
-properties directly.
-
-The same can be done for properties such as children.
-
-```lua
-type Children = {
- Children = Array
-}
-
-local function List(args: Children & Layout)
- return create "Frame" {
- Layout = args.Layout,
- Children = args.Children,
-
- create "UIListLayout" {}
- }
-end
-
-List {
- Layout = {
- Position = UDim2.new()
- },
-
- Children = {
- create "TextLabel" { Text = "1" }
- }
-}
-```
-
-## Tables of data
-
-Vide has functions for dealing with table states.
-
-Below is an example using the above `List` class.
-
-```lua
-type Item = {
- Name: string,
- Icon: number
-}
-
-local items = source({} :: Array- )
-
-List {
- Children = map(items, function(item, i)
- return create "ImageLabel" {
- Image = function()
- return "rbxassetid://" .. item().Icon
- end,
-
- LayoutOrder = i
- }
- end)
-}
-```
-
-Here we map each element in `items` to a value returned by a callback.
-
-The callback is called only *once* per key. The first argument given to the
-callback is a state that has the value of the table key's value.
-
-Anytime the value of the corresponding table key changes, the state value
-changes too. This saves us from having to recreate a UI element any time a
-table index changes.
-
-## WIP
diff --git a/docs/tut/crash-course/1-introduction.md b/docs/tut/crash-course/1-introduction.md
new file mode 100644
index 0000000..20cc3b4
--- /dev/null
+++ b/docs/tut/crash-course/1-introduction.md
@@ -0,0 +1,27 @@
+# [Introduction](./index.md)
+
+This is a brief tutorial designed to give you a quick run through the usage of
+Vide.
+
+Vide is largely inspired by other UI libraries such as Solid and Fusion.
+
+## Why Vide?
+
+Creating UI is a slow and tedious process. The purpose of Vide is to make UI
+declarative and concise, making it faster to create and more importantly easier
+to maintain. Vide achieves this using a reactive style of programming which
+allows you to focus on the flow of data through your application without
+worrying about manually updating UI instances.
+
+Some of the main focuses behind Vide's design choices:
+
+- Concise syntax to reduce verbosity as much as possible.
+- Reducing the amount of imports needed for usage by using Luau's syntax and
+ semantics.
+- Being completely typecheckable.
+- Flexibility, particularly with integrating other libraries and allowing users
+ to use their own patterns.
+
+-------------------------------------------------------------------------------
+
+### [Element Creation →](./2-creation.md)
diff --git a/docs/tut/crash-course/2-creation.md b/docs/tut/crash-course/2-creation.md
new file mode 100644
index 0000000..71a231a
--- /dev/null
+++ b/docs/tut/crash-course/2-creation.md
@@ -0,0 +1,67 @@
+# [Creating UI Elements](./index.md)
+
+Instances are created using [`create()`](../../api/creation.md#create).
+
+```lua
+local vide = require(path_to_vide)
+local create = vide.create
+```
+
+`create()` returns a constructor for a given class which then takes a table of
+properties to assign when creating a new instance for that class.
+
+```lua
+local frame = create "Frame" {
+ Name = "Background",
+ Position = UDim2.fromScale(0.5, 0.5)
+}
+```
+
+String keys are assigned as properties and integer keys are assigned as child
+instances.
+
+```lua
+create "ScreenGui" {
+ Parent = game.StarterGui,
+
+ create "Frame" {
+ AnchorPoint = Vector2.new(0.5, 0.5),
+ Position = UDim2.fromScale(0.5, 0.5),
+ Size = UDim2.fromScale(0.4, 0.7),
+
+ create "TextLabel" {
+ Text = "hi"
+ },
+
+ create"TextLabel" {
+ Text = "bye"
+ }
+ }
+}
+```
+
+To connect to an event, just set the event property name to a function.
+
+All event arguments are passed into the function.
+
+
+```lua
+create "TextButton" {
+ Activated = function()
+ print "clicked!"
+ end
+}
+```
+
+## Summary
+
+In short:
+
+- String keys = properties
+ - Function values = events
+ - Non-function values = property values
+- Numeric keys = children
+
+--------------------------------------------------------------------------------
+
+### [← Introduction](./1-introduction.md) | [Components →](./3-components.md)
diff --git a/docs/tut/crash-course/3-components.md b/docs/tut/crash-course/3-components.md
new file mode 100644
index 0000000..96109ea
--- /dev/null
+++ b/docs/tut/crash-course/3-components.md
@@ -0,0 +1,52 @@
+# [Components](./index.md)
+
+Components are custom-made reusable pieces of UI made from other pieces of UI.
+
+Using components you make your application more modular and better organized.
+
+Components leverage functions to create self-contained UI that can even have
+its own state and behavior.
+
+```lua
+local function Button(props: {
+ Position: UDim2,
+ Text: string,
+ Callback: () -> ()
+})
+ return create "TextButton" {
+ BackgroundColor3 = Color3.fromRGB(50, 50, 50),
+ Size = UDim2.fromOffset(400, 250),
+
+ Position = props.Position,
+ Text = props.Text,
+ Callback = props.Callback
+ }
+end
+
+local button = Button {
+ Position = UDim2.new(),
+ Text = "Click me!",
+
+ Callback = function()
+ print "clicked"
+ end
+}
+```
+
+Above is a simple example of a button component with its background color set to
+a dark grey and with a fixed size.
+
+A single parameter `props` is used to pass properties to the component.
+
+Components allow you to *encapsulate* behavior. You can only modify the
+component in ways that you allow in the component.
+
+This also promotes code reusability. Anytime you want a new button all you do
+is call `Button {}` instead of creating and setting every property each time.
+
+This can be extended to much more complicated UI.
+
+--------------------------------------------------------------------------------
+
+### [← Element Creation](./2-creation.md) | [State →](./4-state.md)
+
diff --git a/docs/tut/crash-course/4-state.md b/docs/tut/crash-course/4-state.md
new file mode 100644
index 0000000..e66f417
--- /dev/null
+++ b/docs/tut/crash-course/4-state.md
@@ -0,0 +1,57 @@
+# [State](./index.md)
+
+State in Vide are special objects that store data.
+
+A state object in Vide can be created using
+[`source()`](../../api/reactivity-core.md#source).
+
+```lua
+local source = vide.source
+```
+
+```lua
+-- create a new source
+local count = source(0)
+
+-- set source value
+count(10)
+
+-- get source value
+print(count()) -- "10"
+```
+
+Below is an example of a counter component that has state.
+
+```lua
+local function Counter()
+ local count = source(0)
+
+ return create "TextButton" {
+ Text = count
+
+ Activated = function()
+ count(count() + 1)
+ end,
+ }
+end
+```
+
+Any time the source value is set, anything depending on it will automatically be
+updated using the new value.
+
+Vide detects when you assign a function to a property. This is known
+as *binding* and doing so will cause the property to *automatically* update
+whenever a state in that function is updated, by rerunning the function and
+assigning its return value. You can only bind non-event
+properties, otherwise the function is connected as the event callback.
+
+You as the programmer do not have to worry about manually updating variables or
+UI instances, you can just focus on defining how the data maps to UI and
+everything will update when changes occur.
+
+Each call of `Counter {}` will create a new counter element, each with their own
+independent count state.
+
+--------------------------------------------------------------------------------
+
+### [← Components](./3-components.md) | [Derived State →](./5-derived-state.md)
diff --git a/docs/tut/crash-course/5-derived-state.md b/docs/tut/crash-course/5-derived-state.md
new file mode 100644
index 0000000..c649758
--- /dev/null
+++ b/docs/tut/crash-course/5-derived-state.md
@@ -0,0 +1,57 @@
+# [Derived State](./index.md)
+
+You can create new state from existing states. This is known as *deriving
+state*.
+
+```lua
+local count = source(0)
+
+local function text()
+ return "count: " .. count()
+end
+
+create "TextLabel" {
+ Text = text
+}
+```
+
+Assigning a non-event property a function will bind that property to that
+function, anytime a state being read from inside that function is changed, the
+function will be re-ran and the property value updated.
+
+Sometimes when using expensive computations to derive state, you only want to
+recalculate it when a source state has changed.
+
+```lua
+local derive = vide.derive
+```
+
+```lua
+local count = source(0)
+
+local factorial = derive(function()
+ local n = 1
+ for i = 2, count() do
+ n *= i
+ end
+ return n
+end)
+```
+
+`derive()` will cache and return the same value until a source state has
+changed, where it will recompute and cache a new value.
+
+```lua
+create "TextLabel" {
+ Text = function()
+ return "factorial: " .. factorial()
+ end
+}
+
+count(3) -- displays "factorial: 6"
+count(4) -- displays "factorial: 24"
+```
+
+--------------------------------------------------------------------------------
+
+### [← State](./4-State.md) | [Table State →](./6-table-state.md)
diff --git a/docs/tut/crash-course/6-table-state.md b/docs/tut/crash-course/6-table-state.md
new file mode 100644
index 0000000..865acd4
--- /dev/null
+++ b/docs/tut/crash-course/6-table-state.md
@@ -0,0 +1,39 @@
+# [Table State](./index.md)
+
+Vide has functions for dealing with table states.
+
+Below is an example using the above `List` class.
+
+```lua
+type Item = {
+ Name: string,
+ Icon: number
+}
+
+local items = source({} :: Array
- )
+
+List {
+ Children = map(items, function(item, i)
+ return create "ImageLabel" {
+ Image = function()
+ return "rbxassetid://" .. item().Icon
+ end,
+
+ LayoutOrder = i
+ }
+ end)
+}
+```
+
+Here we map each element in `items` to a value returned by a callback.
+
+The callback is called only *once* per key. The first argument given to the
+callback is a state that has the value of the table key's value.
+
+Anytime the value of the corresponding table key changes, the state value
+changes too. This saves us from having to recreate a UI element any time a
+table index changes.
+
+--------------------------------------------------------------------------------
+
+### [← Derived State](./5-derived-state.md) | [Property Groups →](./7-property-groups.md)
diff --git a/docs/tut/crash-course/7-property-groups.md b/docs/tut/crash-course/7-property-groups.md
new file mode 100644
index 0000000..65ee8c6
--- /dev/null
+++ b/docs/tut/crash-course/7-property-groups.md
@@ -0,0 +1,78 @@
+# [Property Groups](./index.md)
+
+When a key is assigned a table, Vide does not attempt to assign it to a
+property, instead, the table is iterated and processed just like the nesting
+table.
+
+Below is an example of how you can use this to pass groups of similar properties
+together such as position and size, while also using typechecking.
+
+```lua
+type Layout = {
+ Layout = {
+ Position: UDim2?,
+ Size: UDim2?,
+ AnchorPoint: Vector2?
+ }
+}
+
+local function Button(args: Layout & {
+ Text: string,
+ Callback: () -> ()
+})
+ local count = source(0)
+
+ return create "TextButton" {
+ Text = args.Text
+ Activated = args.Callback,
+ Layout = args.Layout
+ }
+end
+
+Button {
+ Text = "Click me!",
+
+ Callback = function()
+ print "clicked me!"
+ end,
+
+ Layout = {
+ Position = UDim2.new(),
+ Size = UDim2.new()
+ }
+}
+```
+
+Here the button component is assigned a position and size as if you passed those
+properties directly.
+
+The same can be done for properties such as children.
+
+```lua
+type Children = {
+ Children = Array
+}
+
+local function List(args: Children & Layout)
+ return create "Frame" {
+ Layout = args.Layout,
+ Children = args.Children,
+
+ create "UIListLayout" {}
+ }
+end
+
+List {
+ Layout = {
+ Position = UDim2.new()
+ },
+
+ Children = {
+ create "TextLabel" { Text = "1" }
+ }
+}
+```
+
+--------------------------------------------------------------------------------
+
+### [← Table State](./6-table-state.md)
diff --git a/docs/tut/crash-course/index.md b/docs/tut/crash-course/index.md
new file mode 100644
index 0000000..6f88c82
--- /dev/null
+++ b/docs/tut/crash-course/index.md
@@ -0,0 +1,15 @@
+# Crash Course
+
+1. ### [Introduction](./1-introduction.md)
+
+2. ### [Element Creation](./2-creation.md)
+
+3. ### [Components](./3-introduction.md)
+
+4. ### [State](./4-introduction.md)
+
+5. ### [Derived State](./5-introduction.md)
+
+6. ### [Table State](./6-introduction.md)
+
+7. ### [Property Groups](./7-introduction.md)
diff --git a/test/tests.luau b/test/tests.luau
index b8cd10e..d49e85c 100644
--- a/test/tests.luau
+++ b/test/tests.luau
@@ -486,7 +486,6 @@ end)
TEST("cleanup()", function()
local source = vide.source
- local derive = vide.derive
local watch = vide.watch
local cleanup = vide.cleanup
diff --git a/todo.md b/todo.md
index d20ec85..5d020d9 100644
--- a/todo.md
+++ b/todo.md
@@ -11,52 +11,3 @@
- batch
- async/loading/suspense
- define order with nested properties
-
-```lua
-type Action = {
- type: T,
- priority: number,
- callback: (Instance) -> ()
-}
-
-local function action(priority: number, fn: (Instance) -> ()): Action
-
-end
-
-local function changed(property: string, callback: () -> ())
- return action(1, function(instance)
- instance:GetPropertyChangedSignal(property):Connect(callback)
- end) :: Action<"Changed">
-end
-
-create "TextBox" {
- Text = "test",
-
- changed "Text" < function(self, data)
-
- end
-}
-```
-
-## version 1
-
-```lua
-map(items, function(item, i)
- return Item {
- Item = item, -- primitive
- LayoutOrder = i
- }
-end)
-```
-
-## version 2
-
-```lua
-each(items, function(item, i)
- return Item {
- Item = item, -- state
- LayoutOrder = i
- }
-end)
-```
-