diff --git a/doc/html-proxy.md b/doc/html-proxy.md
new file mode 100644
index 0000000..95b4b24
--- /dev/null
+++ b/doc/html-proxy.md
@@ -0,0 +1,66 @@
+# Skooma.js
+
+```js
+import {html} from "skooma.js"
+```
+
+A functional-friendly helper library for procedural DOM generation and
+templating, with support for reactive state objects.
+
+## Overview
+
+```js
+const text = new State({value: "Skooma is cool"})
+setTimeout(() => {text.value = "Skooma is awesome!"}, 1e5)
+
+document.body.append(html.div(
+ html.h1("Hello, World!"),
+ html.p(text, {class: "amazing"}),
+ html.button("Show Proof", {click: event => { alert("It's true!") }})
+))
+```
+
+## Interface / Examples
+
+### Basic DOM generation
+
+Accessing the `html` proxy with any string key returns a new node generator function:
+
+```js
+html.div("Hello, World!")
+```
+
+Attributes can be set by passing objects to the generator:
+
+```js
+html.div("Big Text", {style: "font-size: 1.4em"})
+```
+
+Complex structures can easily achieved by nesting generator functions:
+
+```js
+html.div(
+ html.p(
+ html.b("Bold Text")
+ )
+)
+```
+
+For convenience, arrays assigned as attributes will be joined with spaces:
+
+```js
+html.a({class: ["button", "important"]})
+```
+
+Assigning a function as an attribute will instead attach it as an event listener:
+
+```js
+html.button("Click me!", {click: event => {
+ alert("You clicked the button.")
+}})
+```
+
+
+
+Generators can be called with many arguments. Arrays get iterated recursively as if they were part of a flat argument list.
+
diff --git a/doc/overview.md b/doc/overview.md
new file mode 100644
index 0000000..a8b9545
--- /dev/null
+++ b/doc/overview.md
@@ -0,0 +1,93 @@
+## Skooma.js
+
+### HTML Proxy
+
+The proxy object that does the actual HTML generation.
+
+```js
+document.body.append(html.div(
+ html.span("Hello, World!")
+))
+```
+
+### Handle helper
+
+Wraps a funcion of the signature `event, ... -> value` so that
+`event.preventDefault` gets called before running the function.
+
+```js
+button.addEventListener("click",
+ handle(() => console.log("click"))
+)
+```
+
+### Fragment helper
+
+Wraps a list of elements in a new document fragment.
+
+```js
+const spans = fragment(
+ html.span("First span"),
+ html.span("Second span")
+)
+document.body.append(spans.cloneNode())
+```
+
+### Text helper
+
+When called as a normal function, returns a new text node with the given
+content. Unlike `document.createTextNode`, it does not fail for non-string
+values.
+
+```js
+const node = text("Hello, World!")
+```
+
+When used as a tagged template, returns a document fragment containing text
+nodes and interpolated values. DOM nodes can be interpolated into the document
+fragment.
+
+```js
+const description = text`Interpolate ${html.b("bold")} text`
+```
+
+For consistency, even tagged templates with no interpolated variables will
+always return a document fragment.
+
+## State.js
+
+### AbortRegistry
+
+`FinalizationRegistry` that takes an `AbortController` and aborts it whenever
+the registered value gets collected.
+
+### ChangeEvent
+
+The event class emitted when a change is detected on a skooma state.
+Provides the `final` getter.
+
+### MapStorage
+
+A utility class that simulates the `Storage` API but is backed by a map. Can be
+used as fallback in environments where persistent storages aren't available.
+
+### SimpleState
+
+Base state class that all other states inherit from, used primarily for class
+checking, as the `State` class introduces behaviours that may be undesireable
+when inheriting.
+
+### State
+
+The main state class that does all the magic.
+
+### ForwardState
+
+Proxy to a named property on another State to be used with APIs that only accept
+single-value states.
+
+### StoredState
+
+State class that is backed by a Storage instead of an internal proxy.
+
+## domLense.js