Build, Encounter, Learn, Return
Build the feature; hit a gap; take the one focused lesson; practise the primitive; return to the feature. Against the other order — learn HTML, CSS, JavaScript, React, Node, SQL, and eventually build something — which teaches everything except how to build the thing you wanted.
The situation, the reflex, and why it stalls
Every lesson starts where being stuck starts: someone has a problem, and the first move that comes to mind feels like progress.
You want to build a cart and you do not know enough. Do you learn first and build later, or build first and learn what stops you — and what does each order actually produce after a month?
You have a list of things you apparently need before the cart: JavaScript properly, then TypeScript, then React, then something for the backend, then databases. The list is a curriculum, and the cart is at the end of it. Six weeks in, you know some of each and the cart is not started, and the reason you wanted any of it is getting harder to remember.
Finish the curriculum first. It is orderly, each course has a progress bar, and starting the cart before "knowing enough" feels like building on sand. The tutorials are good, so following them feels like the responsible order.
Every course teaches its whole subject, so most of each is not needed for the cart and is forgotten before the cart needs any of it. The loop you will need for findExisting was in week one; by week six it is a vague memory next to closures and prototypes.
- Every course teaches its whole subject, so most of each is not needed for the cart and is forgotten before the cart needs any of it. The loop you will need for findExisting was in week one; by week six it is a vague memory next to closures and prototypes.
- Nothing learned was tested against a need, so nothing is known to be known. You can watch a loop be written and still not know whether you can write one, because you have never had to.
- The cart, when finally started, still stalls — at "look for the existing item" — because the course taught arrays as a topic and not as the answer to that sentence. The gap arrives anyway; the curriculum only postponed it.
- The tutorial that finally "builds a cart" builds its own, and the store you inherit has decisions you did not make: a client-only cart because the video was shorter, no rule for duplicates because the demo never added twice.
The move
Precisely enough to apply it to a problem you have never seen — not a slogan.
- Reverse the order: build the thing, and let the gaps decide what to learn. Start the cart from its meaning and state; write addItem; stop at the line you cannot write. That line is a *knowledge gap with a name* — "find an entry in a collection by a property" — and a named gap is the best possible learning request, because it says exactly how much to learn and when you are done.
- Take the focused lesson, not the subject. The gap "find an entry by a property" needs arrays and iteration — the array lesson, one exercise, an afternoon at most. It does not need the language's whole collections chapter. The measure of "enough" is that you can now write the line.
- Practise the primitive alone, once, so that it is yours: a loop that prints each entry, a loop that returns the first match. Then return to addItem and write the line with it. The return is not optional; it is the step that turns a lesson into a capability, because the primitive is used for the reason it was learned.
- Repeat per gap. The cart will stop again at "serialise to storage" and again at "an endpoint the page can call", and each stop is a lesson-sized detour with a return ticket. After a month you have a cart you understand and exactly the knowledge it needed — and a list of what it did not.
The loop
Five steps, and the last one is the one that gets skipped. A lesson without a return is a course; a gap without a name is a curriculum.
- 1Build
Start the feature from its meaning and state; write the first operation.
fails by Waiting to feel ready — readiness is what the gap defines.
- 2Encounter
Stop at the line you cannot write and name what it needs.
fails by Naming it as a subject ("JavaScript") instead of a primitive ("find by property").
- 3Learn
One lesson, one section, the smallest example.
fails by The lesson becomes the course; the cart waits a week.
- 4Practise
Write the primitive alone, once, on a two-line example.
fails by Reading it and believing it is known.
- 5Return
Write the line in the feature with the primitive, the same day.
fails by Never returning — the primitive is learned for no reason and forgotten for the same one.
The loop runs once per gap. A cart produces three or four gaps in its first version; each is an afternoon.
The gaps of one cart, as a board
The gaps that the cart produced, each as it was first felt and as it was named. The experiment column is the practice step; the return is implied by the feature waiting.
- ✓The cart's meaning, state, operations, rules and examples — English, no gap.
- ✓Conditionals and arithmetic — the rejections and the total need nothing new.
- ~One shopper and one process until V1 — so "which cart?" is not a gap yet, and is written down as the next one.
? I don't know how to write the find.
becomes How do I loop over a collection and return the first entry whose productId equals a given id — and what do I return when none does?
experiment One loop over [ Laptop × 1 ] returning the entry; the same loop over [] returning nothing.
? It forgets everything on reload.
becomes How do I keep cart.items across page loads in the browser, and what happens when storage is cleared or holds a product that no longer exists?
experiment Store one string, reload, read it back; then delete it and read again.
? The page needs to talk to the server.
becomes What does one route look like that takes { productId, quantity } as JSON, calls addItem, and returns the cart or a 400 with the rule?
experiment One POST handler and one curl; a quantity of 0 must come back as a 400 naming the rule.
Every gap is a primitive or one section of one lesson. None of them is a course, and the cart moved after each.
The two orders, side by side
The comparison is not about effort — both orders take a month. It is about what exists at the end and what the learner can explain.
HTML, CSS, JavaScript, React, Node, SQL — six courses, each complete, then a tutorial that builds its own cart. At the end: six progress bars and a cart whose duplicate-entry rule was never decided.
The cart from its meaning; three named gaps — find by property, browser storage, one route — each an afternoon with a return; a tutorial's cart read afterwards as a comparison. At the end: a tested cart, three primitives that are known because they were needed, and a written list of what was deliberately not learned.
Knowledge used for the reason it was learned is retained and can be explained; knowledge learned ahead of need has no test of whether it was learned at all. The second order also produces the list of what is *not* known, which the first order hides behind completed courses.
The implementation ladder
Concept, examples, pseudocode, code, tests, production — for the concept this lesson is about. Code is the fourth tab, not the first.
Shopping Cart = A temporary collection of products the user intends to purchase, held between browsing and checkout.
- Does a cart have identity? Yes, weakly. Two carts with the same items are still two carts, because each belongs to someone and will become a different order. It needs an id once it leaves memory; in memory the variable is the identity.
- Who owns it? A shopper — a logged-in user or an anonymous session. The owner is part of the state because "my cart" has to be findable again.
- How long does it exist? From the first add until checkout or abandonment. Whether it survives a reload, a closed browser or a login is not a property of the concept; it is a persistence decision made later, and each answer changes where the cart lives.
- Should it survive reload? Usually yes for a store, usually no for a demo. V1 in memory says no; V2 browser storage says yes on one device; V3 server storage says yes everywhere the user is logged in.
- Should it survive login? Only if an anonymous cart and a logged-in cart are merged — a rule that does not exist in V1 and appears as a modification later.
- itemscollection of CartItemkeepThe cart is its items; without them nothing else means anything.
- items[].productIdidkeepThe reference to what is being bought. The catalog owns the product; the cart only points at it.
- items[].quantityinteger > 0keepTwo laptops is one entry with quantity 2, not two entries — the rule "one entry per product" needs a quantity to hold.
- owneruser id or session iddependsSo the cart can be found again by the person it belongs to.
- items[].productNamestringderiveIt would be convenient to render the cart without a catalog lookup.
- items[].pricemoneydependsThe total needs a price per item.
- totalmoneydropEvery screen shows the total.
- currencycodedependsPrices need a currency to be added.
- createdAttimestampdropAbandoned carts might be expired or emailed about.
- update Add item — the updated cart
- delete Remove item — the updated cart
- update Change quantity — the updated cart
- read View items — the list of entries — product id and quantity — for rendering
- domain Calculate total — the sum of price × quantity over the entries
- delete Clear cart — the empty cart
- • Every quantity is greater than zero.
- • One logical entry per product.
- • The total is never negative.
- • An unknown product cannot be added.
- • Quantity cannot exceed available stock — if inventory is enforced here.
How to do it
Most important first.
- Start the feature before you feel ready; the first gap will tell you what "ready" meant (I Know What I Need, But I Don't Know How to Build It).
- When you stop, write the line you cannot write as a sentence, then as a question with a name — "how do I find an entry in a list by a field?" (Unknown to Specific Question).
- Find the one lesson for the name, read only the section that answers it, and try its smallest example (A Reading Strategy for an Unfamiliar Library, Teach Me Only What I Need).
- Write the primitive once alone, then return and write the line in the feature the same day (Go One Primitive Lower).
- Use tutorials afterwards as comparison — read their cart against yours and note every difference — rather than as a source of your first cart (Tutorial Dependency, Before You Copy Code).
Worked on a concrete problem
The move has to produce something. This is what it produced.
- Day one: meaning, state, operations, rules, examples for the cart — no gap, because it is English. addItem begins; stops at "look for an existing entry with this product id". Gap named: find-by-property in a collection. Lesson: arrays and iteration. Practice: a loop that returns the first entry whose productId matches, tested on [ Laptop × 1 ] and []. Return: addItem is finished, and add-again passes.
- Day three: the cart works in memory and vanishes on reload. Gap named: keep a value across page loads in the browser. Lesson: browser storage, one section — set on change, get on start. Practice: store and reload one string. Return: V2 serialises cart.items on every change and loads it on start, and the stale-product failure is written down because the lesson mentioned cleared storage.
- Week two: checkout must trust the cart. Gap named: an endpoint the page can call that runs addItem on the server. Lesson: one route, one JSON body, one response — POST /cart/items returning the cart or a 400 with the rule. Return: the same addItem, unchanged, behind the route; the unique (cart_id, product_id) constraint is the next gap, named when two tabs are opened.
- What the month produced: a cart with tests, three primitives that are genuinely known because each was used for a reason, and a written list of what was *not* learned — no React course, no SQL course — each with the requirement that would trigger it. The curriculum-first month produced six progress bars.
How you know it worked
What now exists that did not before, and what question you can now ask.
- Every lesson you took this month can be pointed at by a line in the feature that needed it.
- You stop at gaps with names, and the names are specific enough to find one lesson.
- Detours end the same day they start, with the feature moved forward.
- You can list what you deliberately have not learned, with the requirement that would change that.
The questions you can now ask
The field this whole domain exists for. After this lesson, these are the questions to put to an unfamiliar problem.
- ?What is the exact line I cannot write, and what is the name of the thing it needs?
- ?Which single lesson answers that name, and how will I know I have learned enough — which line will I be able to write?
- ?Have I returned to the feature today, and did the primitive get used for the reason I learned it?
- ?What am I choosing not to learn yet, and which requirement would change that?
What can go wrong
- The detour eats the return. The array lesson leads to the iterator lesson leads to generators, and the cart waits a week. The lesson is done when the line can be written; everything after that is a different decision.
- Gaps are named too loosely — "I need to learn JavaScript" — so the lesson taken is a course, and the order has collapsed back into curriculum-first.
- Build-first is applied to a gap that is genuinely foundational. A learner who does not know what a variable is cannot name gaps yet; a short foundation comes first, and the cart is the first thing built after it, not the tenth.
- Tutorials are avoided rather than reordered. A tutorial's cart, read after yours exists, is a free code review; refusing it is throwing away comparison.
- Build-first means starting without a map, and the first day of a feature can be uncomfortable in a way a course never is.
- Learning only what the gap needs leaves real holes — you may not meet closures for months — and some of those holes will bite in a later feature.
- The order produces a cart that looks worse than a tutorial's cart for a while: no framework, no styling, just working functions.
- "So courses and tutorials are a waste of time." They orient, and they are excellent after the first attempt, when you have questions to bring. The slogan to make precise is "learn the fundamentals first": true if the fundamentals are variables, functions and one loop; false if it means six courses before one feature — and no tutorial's store represents the production one you would build, so reading it first inherits decisions instead of making them.
- "Build-first means never reading documentation." It means reading the section the gap points at, and it means reading it *more* often, because each gap sends you there with a question.
- "This only works for simple features." It works for any feature whose gaps can be named; a feature whose gaps cannot be named yet needs the Discover stage, not a curriculum.
Where this applies
Problem-solving advice is stated as universal far more often than it is. These labels say what each method is specific to — and where CONTESTED appears, the note gives the strongest form of the opposing view.
- GENERALBuild, encounter a named gap, take the focused lesson, practise, return — the loop is the same for a first cart and for a senior meeting a new language.
- TEAM-SPECIFICA solo learner runs the loop alone with documentation and lessons; on a team the "lesson" is often a colleague and the return is a pull request, and the danger flips — a team can hand you the answer before you name the gap.
- ILLUSTRATIVEThe six-week curriculum, the days and the month are invented for the shape of the comparison; the cart's V2 and V3 are the concept record's own versions.
Where the depth lives
This domain asks the question and hands the answer off by name.
- — The manifesto's "Learning without AI" route at /manifesto/without-ai is this loop with the hint ladder in place of the lesson: your attempt first, then one rung.