Skip to content

tishlang/learn

Repository files navigation

tish-learn

A 100%-Tish, in-browser learn-to-code platform. Forty beginner chapters, twenty-eight Tish-deep chapters, and twenty-one capstone-project chapters across six builds — all running in your browser tab.

Same spirit as tish-playground: the compiler, the VM, the lessons, and the live code execution all run on your machine, in your browser, with no backend involved.

The two rules

1. Almost zero JS dependencies (runtime is still pure Tish)

The in-browser stack is pure Tish (Lattish + panels + tailwind emitter + browser-server). There is no React, Webpack, or Tailwind CLI.

npm run dev / npm run build are thin wrappers around just dev and just build (see justfile); you can call just directly if you prefer.

public/boot.js is plain ESM (not compiled Tish): it loads wasm + import() of learn.js vs learn_sandbox.js, and can defer heavy work when prerendered pages set <meta name="ll-defer-wasm" content="1">.

Static HTML for each lesson is emitted by tish run --feature fs prerender.tish — same Tishdoc parser and highlighter path as the app (see app/tishdoc.tish deep import of TishHighlight.tish).

CSS is still generated by tish run --feature fs build-css.tish via the pure-Tish tish-tailwind emitter.

2. Zero backend

Even the "server-shaped" capstones — real-time chat, REST API, blog generator — run entirely in your tab. No relay to deploy, no tish run server.tish on your machine, no terminal. The trick is tish-browser-server, a pure-Tish shim that mirrors the 'http' / 'fs' / 'process' API surface over a Service Worker, BroadcastChannel, and IndexedDB.

Each capstone closes with a "Take it real" appendix showing the one-line diff to swap tish-browser-server for the host modules and run the same code on a deployable Tish server.

Three tracks (95 chapters)

Track Chapters Audience
Beginner — Learn to code 40 + 6 best-practice interludes From zero. Starts with no-typing chip-tap puzzles; ends with a static-site export.
Tish, in depth 28 across 5 parts If you already code. Mirrors LANGUAGE.md.
Capstones 21 across 6 projects Real-time chat, Snake, blog generator, REST API, collaborative whiteboard, tiny game engine.

Build and dev

Prereqs: Rust + just + wasm-bindgen-cli, and a sibling checkout of tish (default ../tish, override with TISH_ROOT).

npm install      # one-time: sibling packages (lattish, panels, tailwind, browser-server)
npm run dev      # → just dev → full build + dev-server.tish (:8765)
npm run build    # → just build (includes prerender + sandbox split)
just dev         # same as npm run dev

Targets:

Just target Builds
just build-app learn.js + deps: lattish-runtime.js, learn_sandbox.js
just build-sandbox app/main_sandbox.tishlearn_sandbox.js (standalone /sandbox route)
just build-prerender prerender.tishpublic/<track>/<chapter>/index.html per lesson
just build-runtime Lattish runtime → public/dist/lattish-runtime.js (used in iframe sandboxes)
just build-sw tish-browser-server's SW → public/dist/tish-sw.js
just build-css tish-tailwind scans app/** + content/**public/utilities.css
just build-vm tishlang_wasm_runtime Rust crate → tish_vm.{js,wasm}
just build-compiler tishlang_compiler_wasm Rust crate → tish_compiler.{js,wasm}
just build All of the above
just quick App + sandbox + CSS + prerender (skips Rust builds)
just dev just build + serve via dev-server.tish

learn.config.json at the repo root configures contentDir, tracksDir, outDir, and basePath for prerender.tish (reserved fields documented in that file’s comments if needed).

Layout

tish-learn/
  app/                       # 100% Tish UI sources
    main.tish                # createRoot → LearnApp
    LearnApp.tish            # header, sidebar, content
    router.tish              # History-API router /<track>/<chapter>
    content_loader.tish      # fetches /content/, caches
    progress.tish            # localStorage completion state
    tishdoc.tish             # MDX-style parser (TishDoc subset)
    views/
      TrackPicker.tish       # 3-track home + per-track index
      LessonView.tish        # parse + walk + dispatch directives
    directives/
      Pick.tish              # ::pick   — Duolingo chip-tap
      TryIt.tish             # ::tryit  — MiniRunner without expected
      Exercise.tish          # :::exercise — MiniRunner with expected
      Quiz.tish              # :::quiz radio
      Sandbox.tish           # :::sandbox{kind=console|ide}
      Callout.tish           # :::callout{kind=info|tip|warn|danger|note}
      Project.tish           # :::project — capstone hero
    utils/
      objects.tish           # opt(o, key, fb), has(o, key), isFileError(v)
  content/
    tracks/{beginner,tish-deep,capstones}.json
    beginner/                # 46 chapters
    tish-deep/               # 28 chapters
    capstones/{chat,snake,blog,rest-api,whiteboard,game-engine}/
  public/
    index.html               # shell → boot.js (wasm + route split + optional defer)
    boot.js                 # loads vm/compiler + learn.js or learn_sandbox.js
    base.css                 # hand-written semantic styles
    utilities.css            # generated by tish-tailwind
    dist/                    # learn.js + lattish-runtime.js + tish_vm.{js,wasm} + tish_compiler.{js,wasm} + tish-sw.js
  build-css.tish             # CSS pipeline
  dev-server.tish            # static file server
  justfile                   # build recipes

What gets shipped at runtime?

Only this is JS at runtime:

  1. dist/learn.js — output of tish build --target js app/main.tish. Authored as Tish.
  2. dist/lattish-runtime.js — output of tish build on the Lattish source.
  3. dist/tish-sw.js — output of tish build on tish-browser-server/src/sw_worker.tish.
  4. dist/tish_vm.{js,wasm} + dist/tish_compiler.{js,wasm} — auto-generated wasm-bindgen glue from Rust crates. We don't write these.
  5. public/index.html + public/boot.js — load wasm-bindgen modules, expose __tish* globals, then import() dist/learn.js (main app) or dist/learn_sandbox.js on /sandbox. Prerendered chapter HTML adds <meta name="ll-defer-wasm" content="1"> so the same boot can defer work until idle or first input.

Verification

End-to-end smoke checks performed:

  • tish build app/main.tish --target js produces a working bundle (~5,100 lines).
  • tish build node_modules/lattish/src/Lattish.tish --target js produces the iframe runtime.
  • tish build node_modules/tish-browser-server/src/sw_worker.tish --target js produces the SW.
  • tish run --feature fs --feature http build-css.tish writes public/utilities.css (210 lines, 23/310 utilities used).
  • ✅ Dev server boots on :8765 and serves: index.html, /content/tracks/*.json, /content/<track>/<chapter>.tishdoc.md.
  • tish-playground still builds end-to-end after consuming tish-ide-panels.
  • tish-audio builds via the new pure-Tish tish-tailwind emitter (scripts/build-css.tish).
  • ✅ Audit: rg "(tailwindcss|postcss|autoprefixer|esbuild|webpack|react)" across every new package.json returns zero matches.
  • ✅ Audit: no .js / .jsx / .ts / .tsx files in app/ or src/ — only .tish and assets.

Curriculum quick reference

Beginner (40 + 6 best-practice)

  • Part I — Hello, code (4): print, errors, variables, constants
  • Part II — Numbers, words, choices (7): numbers, strings, methods, booleans, if/else, ternary, logical ops
  • Part III — Repetition and collections (8): while, for, break/continue, arrays, methods, iterating, map/filter/reduce
  • Part IV — Objects and functions (7): objects, iter, functions, arrows, scope, closures
  • Part V — Real-world I/O (7): try/catch, JSON, modules, console tools, reading docs
  • Part VI — Your first webpage (4): JSX, forms, lists, localStorage
  • Part VII — Useful real apps (7): fetch, canvas, Snake, two-tab chat, virtual fs, static-site export, what's next
  • BP-01 to BP-06 interspersed: read errors, name things well, console.log to debug, smaller pieces, comment why, run early/often

Tish-deep (28 across 5 parts)

  • I Orientation (4): why-tish, tour, vs-javascript, blocks/indent
  • II Core (6): scope, functions, control flow, strings/numbers, arrays/objects, new/construct
  • III Async/Errors/I/O (8): promises, async/await, http client, http server, fs, process, regex, feature flags
  • IV Modules and types (4): imports, cargo:, type annotations, type/declare
  • V UI and native compile (6): JSX/Lattish, native macOS, native modules, build targets, tooling, deploy

Capstones (6 projects, 21 chapters)

  • C1 Real-time chat (3) — BroadcastChannel + take-it-real
  • C2 Snake (3) — canvas, input, juice + persistent score
  • C3 Static blog generator (4) — markdown + virtual fs + templates + zip download
  • C4 Tiny REST API (3) — Service-Worker-backed CRUD
  • C5 Collaborative whiteboard (3) — multi-tab sync + WebRTC bonus
  • C6 Tiny game engine (5) — ECS + sprites + AABB + scenes + ship a platformer

Acknowledgements

  • tish-playground — the IDE panels in tish-ide-panels are extracted from here.
  • tish-audio — the Tailwind utility table in tish-tailwind is extracted from tish-audio/tish-tailwind.
  • tish-creator — the TishDoc directive shape (:::name{...} / ::name{...}) follows the parser used there.
  • LANGUAGE.md — the canonical language spec the curriculum teaches.

Releases

No releases published

Packages

 
 
 

Contributors

Languages