Records the real thing
No slides and no mockups. A headless browser signs in to your live app and performs the walkthrough, so what ships is what a customer would see.
Tooto takes a short spec, drives your real app in a real browser, records it, narrates it and hands back a finished tutorial video. The project that made it stays editable afterwards, by you or by an agent.
What it does
A tutorial video is a recording, a script, an edit and a listing. Each one is a different afternoon, and the result is stale the week the product changes.
How it works
One file per video: the slug, the title, the URL to drive, the beats in order and the script lines. Length rules and per-line word budgets are checked before a frame is recorded, so a bad spec fails in seconds rather than after a full render.
topics/agency-suite-crm.mjs
Sign in, navigate, click, scroll, and hold on the thing being explained. The cursor path, the marks and the interaction events are captured alongside the frames, so the edit knows where the attention was and not only what the screen showed.
track.json · cursor samples, marks, events
Video, voice, effects, music and captions, each clip with an id that survives an edit. Time is seconds rather than frames, sources are referenced rather than embedded, and a field a newer editor wrote survives a round trip through an older one.
tooto.project v1
Quality gates run against the finished master. Listing metadata is generated from the same spec that drove the recording, operator overrides win over generated text, and cross-links to earlier videos are stitched in at publish rather than at render.
qa → meta → upload
The project document
Nothing in the format executes, records or encodes. It describes what the finished video is, and a renderer turns that into pixels. That split is the point: an agent, a script, a UI and a person all edit the same document.
// every clip carries a stable id, so a re-render is scoped
// to what changed rather than to the whole film
{
"format": "tooto.project",
"version": 1,
"canvas": { "width": 1920, "height": 1080, "fps": 50 },
"theme": { "mode": "dark", "palette": "midnight" },
"tracks": [
{ "id": "video", "clips": [
{ "id": "v_roster", "start": 12.4, "duration": 6.32 }
] },
{ "id": "voice", "gainDb": 0, "clips": [] }
],
"provenance": { "steps": [] }
}
Frames are a render concern and they change with the canvas. A project that stores them breaks when the output does.
Which keeps a whole film small enough to read, diff and review in a pull request like any other file.
A newer editor writing a field this version does not understand cannot lose it, so two tools can work on one document without a migration.
Insert, update, remove, move and ripple are operations on the document, so an agent and the interface share one code path and undo is the inverse patch.
Who it is for
Pricing
These numbers are genuinely undecided. The waitlist is how they get decided, so the note you leave on it is worth more to us than the address.
Early access
One email, when there is something to open. No sequence, no newsletter, and the note is read by a person.
6 projects
Open editoragency-suite-crm
4 templates
What a spec looks like
// The third question every agency asks before buying, answered on
// the live CRM, because "full CRM" means nothing until you see it.
export const topic = {
slug: 'agency-suite-crm',
title: 'The CRM your whole team works from',
kicker: 'TIK.TOOLS · AGENCY TUTORIALS',
url: 'https://tik.tools/',
beats: [
['roster', 'Open the roster and scroll to the signed talent'],
['notes', 'Add a note, then reload to prove it stuck'],
['seats', 'Invite a manager and set their region access']
]
}
Word budgets are per template and per line. A spec that is too long, too short, or that carries a line nobody could read at pace fails before a frame is recorded rather than after a full render.
The gate
Quality gates run against the finished master, not against the plan that produced it, because the two disagree exactly when it matters.
| Gate | What it measures | Result |
|---|---|---|
| Loudness and peak | Programme level and true peak across the master | Pass |
| Voice against picture | Every narration line checked against the beat it belongs to | Pass |
| Caption timing | No caption outlives its line or is shorter than it reads in | Pass |
| Dropped frames | Counted across the assembly, not sampled | Checking |
The listing
| Field | Where it comes from | Source |
|---|---|---|
| Title and chapters | From the beat list, so chapters match what the video does | Auto |
| Thumbnail | A nominated frame, set in the project palette | Auto |
| Share image | Rendered per project at 1200x630 and signed | Auto |
| Series cross-links | Stitched in at publish, because video two does not exist at render | Auto |
| Destination | Operator overrides win over anything generated | YouTube |
This view is a picture of the pipeline the engine already runs. The panel is not wired to it yet, and that is what early access is for.
Appearance
The theme belongs to you and follows your system until you pin it. The palette belongs to the project and travels with the document.
Theme
Light, dark, or whatever the operating system is asking for.
Project palette
The five that ship with the project format. Every render and this panel follow it.
Canvas defaults
Both canvas dimensions must be even, because yuv420p cannot encode an odd one. A project written by a newer build refuses to open here rather than opening wrong.
About
This panel is HTML, one thin stylesheet and one script over bare.style, served by a node:http server with no dependencies. The project format is the same: node builtins and nothing else.