Each one is separately runnable and separately resumable. The first two need nothing but Bun — no Docker, no network, no account, no browser tab open on somebody else's site.
fli tutor:app
11 steps
An app that runs
Scaffold an app, start it, register an account, add a model of your own, push it, write a row through the API and read it back out of the SQLite file the app wrote. Then write a Mesa component, and ask the dev server for the compiled module. Then build it, and check the built page actually loads its JavaScript.
fli tutor:tools
6 steps
The four tools, and when
Four surfaces whose whole job is to report on a running app, and one question each. The GUI is the front door — what is here, what is up, and does anything fail a check. Then the database as it really is, the call feed with a refusal in it named and coded, and the chain that handled the request.
fli tutor:ui
6 steps
A screen you did not write
A form is not written, it is read off the schema — which is easy to nod at and easy to fake, so this one opens a real browser. Every control, the type each column implies, and nothing for the columns the server owns. Then one attribute is added to one column of the schema, no form is touched, and the same page starts refusing.
fli tutor:access
9 steps
Who may do what
Authorization is declared in the schema rather than written in hooks, which is easy to nod at and hard to believe. So this one changes one line of db/schema.lite at a time and shows the answer to the same HTTP request changing: a gate that refuses, a policy that filters, a column that silently declines a write.
fli tutor:live
8 steps
A change reaching somebody else
A row is written over plain HTTP and a socket that asked for nothing is told about it. Then the second question, which most frameworks never ask: who is on the other end? Two sockets, one signed in and one not, watched against a single publish before and after the gate goes up.
fli tutor:jobs
6 steps
Work that outlives the request
A queue that is a SQLite file, a job named by its own filename, and a dispatch from a service hook. What is asserted is the order — the response comes back with the work not yet done, and the row changes afterwards. A test that only checked the final state would pass with the work done synchronously.
fli tutor:notify
8 steps
Telling somebody something
One notification, declared in one file, delivered as a row in the app and as an email — and the file names it, so the type nothing states is the type the database carries. Renaming the file renames the type and orphans every row already written, in silence, which is why a stated type exists. Then a transport declared with no formatter, refused before anything is delivered.
fli tutor:site
8 steps
The public half
A prerendered site is a peer surface, not a folder in the SPA. One HTML file per page with the data already in it — and a build that refuses to emit a page whose load() read something gated, because a published page cannot be recalled. You watch the refusal, then the override that gets past it.
fli tutor:deploy
10 steps
A deploy you can take back
A deploy target may be localhost, so this is the real pipeline: an image, a journal on disk, a health poll, a swap. Deploy, change a line and deploy again, then revert — and revert the revert. Asserted against the image id the container is on, because a pipeline that reports success while leaving the old container up passes everything else.
fli tutor:change
6 steps
The schema you already deployed
Month two: rows in production and a release already serving them. Three changes, each classified — an optional column you can take back, a required one that makes the deploy a pivot and comes back with the three-deploy split, and a raised gate that touches no column and is still a contract.
fli tutor:test
6 steps
Knowing it is right
Most of what you would write tests for has already been declared, and a declaration can be executed: four calls run every gate at every level, every protected column, every validator and every row policy, with no fixtures to author. Then the schema is mutated on purpose — a gate dropped, a guard removed — and the checks derived from the ORIGINAL are run against the mutant, so anything that survives is a hole in the checks and names itself.
fli tutor:fleet
8 steps
A machine that takes orders
The other release story. A control plane holds the fleet as rows, a machine runs an outpost so the control plane has hands on it, and nobody types a deploy. A signed command from the control plane really runs on your machine — and then a release: sources built into an image there, a container started, and the bytes recorded, because a tag is a name two builds share.
fli tutor:adopt
7 steps
A database you already have
The other door. A SQLite database made by somebody else, with rows in it, read into a schema — and the half a converter can quietly skip: every construct the reading could not carry, graded changed, lost or noted. It checks the reading against itself by building a database from it and reading that, then serves a row written by raw SQL before there was an app. The last step is the finding an inherited schema comes with, and it is kept rather than fixed: a baseline the number may never pass.