i.c.stars|* Milwaukee

Code Sandbox

A library of guided tech learning workshops. Every one of them runs in a browser, ends in something that works, and stays here after the session is over.

Nothing in here is a lecture. A workshop is two things: a deck you can present, and one app that already runs — small enough to read in a sitting. No install, no npm, no accounts: if you can open this page you can do the work. Walk out with the thing built.

The shelf

 

How every workshop is built

Same three passes at the same artifact, every time. People quit this subject when night one is forty new words and a blank file. They don't quit when they watched it work first.

Pass 1

I do

Hands off keyboards. Typing along means debugging instead of watching. The instructor builds the smallest version that works.

Pass 2

We do

Keyboards up, nobody types ahead. A checkpoint after every step — “you should see this. Thumbs up.”

Pass 3

You do

Three TODOs in a file that already runs. An answer key exists, and looking at it is allowed. Saying STUCK out loud is encouraged.

The live editor

A workshop folder is the app: an index.html and a js/main.js that open and run straight off disk — no server, no build step, nothing installed. The live editor is a full-screen editor over those files: a sidebar you pull files from, the code in the middle, the running app on the right. Click the red live editor chip on any card above.

┌─ live editor ─────────────────────────────────────────┐ │ ☰ i.c.stars|* ← the app [ Run ▸ ] [Reset file] [Reset all] │ ├──────────────────┬───────────────────────┬──────────────────────┤ │ THE APP │ JS js/main.js │ RESULT │ │ [ search… ] │ 1 const API_URL = │ │ │ │ 2 "https://poke…" │ [ silhouette ] │ │ index.html runs │ 3 │ │ │ ▾ js/ │ 4 const sprite = │ [bulbasaur][pidgey] │ │ main.js │ 5 document.get… │ [pikachu ][ eevee ] │ │ │ 6 │ │ │ │ 7 async function │ SCORE 3 / 4 │ │ │ 8 load() { ├──────────────────────┤ ├──────────────────┤ 9 const response = │ CONSOLE │ │ Break it on │ 10 await fetch(… │ line 9 answer is not │ │ purpose. │ 11 │ defined │ └──────────────────┴───────────────────────┴──────────────────────┘ the app's files the file you grabbed, what it did, and (search them) Ctrl+Enter to run what went wrong

Every run rebuilds the preview from scratch, so nobody debugs state left over from the last attempt. Errors land in the console in red, with the line number counted from line 1 of the file you are editing. Your edits are kept per file, so a refresh costs nothing — and Reset all puts everything back.

Every js/main.js ends with a BREAK IT ON PURPOSE list: a few things to change, and what each one teaches when it goes wrong. Delete an await and you get [object Promise] — you printed the waiting instead of the thing. That is a better lesson than a paragraph about promises, and it costs one keystroke.

Add the next workshop

Fifteen minutes of setup, then you're writing content. The template is a working app with the words taken out — it opens and runs before you change a thing.

  1. Copy workshops/_template/ to workshops/0N-your-slug/.
  2. Rewrite REF-deck.html. Arrow keys drive it, Ctrl+P saves it as a PDF. Do not touch the <style> block — the palette is the house palette.
  3. Rewrite the app: index.html and js/main.js. Only the lesson's code — if a feature is not the lesson, it is something a student reads past to find the point.
  4. End js/main.js with a BREAK IT ON PURPOSE list.
  5. Run python tools/build-playground.py. It reads your app and writes playground.html — nothing to maintain by hand.
  6. Add one object to js/workshops.js, with live: true. The card and the live editor chip build themselves.
  7. Teach it to real people, then change status to "ready". That word means survived a cohort, not finished writing.

Full checklist in CONTRIBUTING.md, including the parts of the house style that are not up for redesign.

The source tree

Plain static site. Pages are HTML, styles are CSS, scripts are JS, and the whole thing is served straight off GitHub Pages. There is no build step to break.

icstars-code-sandbox/ ├── index.html the front door — you are here ├── CONTRIBUTING.md how to add a workshop, and the house rules ├── .nojekyll keeps GitHub Pages from hiding _template/ │ ├── css/ │ ├── theme.css the house theme. Shared by every workshop. │ ├── playground.css the live editor │ └── library.css front-door-only styling │ ├── js/ │ ├── workshops.js THE CATALOG — add your workshop here │ ├── preview-core.js the engine. No dependencies. │ └── playground.js the sidebar, editor and console │ ├── tools/ │ └── build-playground.py regenerates each playground.html │ └── workshops/ ├── _template/ copy this to start │ ├── README.md the checklist │ ├── index.html THE APP │ ├── js/main.js THE APP'S CODE │ ├── REF-deck.html the house deck, empty │ └── playground.html GENERATED by the tool above │ └── 01-hello-api/ Who's That Pokémon? · fetch, JSON, async ├── index.html THE APP ├── js/main.js THE APP'S CODE ├── REF-deck.html 16 slides, three live demos └── playground.html GENERATED