From c0ce033f8d995caa49b00eac73615123d288cdec Mon Sep 17 00:00:00 2001
From: engmung <122682380+engmung@users.noreply.github.com>
Date: Tue, 29 Sep 2026 23:27:38 +0900
Subject: [PATCH 01/12] web: a new install always erases, and the build guide's
first hour matches the device
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The flasher no longer asks whether to erase. A board whose firmware does
not answer Improv is treated as new and wiped, which is ESP Web Tools'
own default; a board already running Patternflow (every edition answers
with that name) is still updated in place and keeps its patterns and
Wi-Fi. It also removes one way the Wi-Fi step went missing: an install
without erase finishes on the dashboard instead of provisioning.
BUILD_GUIDE §8/§9 now say what a first install actually shows: the
Pattern tab, typing the SSID (no list, case-sensitive, 2.4 GHz), RST and
reconnect when the install ends without asking for Wi-Fi, Format storage
before the Basics pack lands, the Device address field on Android, up to
five saved networks on the console's Wi-Fi page, that download mode now
means an erase, that the hotspot arrives after v3.10.4 (Performance
v0.4.0 has it), and that K2 opens NETWORK, not an OSC screen.
Co-Authored-By: Claude Opus 5.5
---
BUILD_GUIDE.md | 17 ++++++++++-------
web/public/flash/manifest.json | 2 +-
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/BUILD_GUIDE.md b/BUILD_GUIDE.md
index 39d6f5c9..7528c48e 100644
--- a/BUILD_GUIDE.md
+++ b/BUILD_GUIDE.md
@@ -244,13 +244,14 @@ The ESP32-S3 module is flashed **separately, outside the PCB**. Already seated i
No installation required — desktop **Chrome or Edge** only (Web Serial; Firefox/Safari won't work).
-> 🔌 **Use the LEFT USB-C port** — the one on your left when the two ports face you. On the ESP32-S3 DevKit that's the board's **native USB** port (labeled `USB`); the browser flasher (Web Serial + Improv) talks to it directly. The right-hand port goes through a separate USB-to-UART bridge chip and is the one Arduino IDE uses (§8.2) — the browser flasher won't see the board on that one.
+> 🔌 **Use the LEFT USB-C port** — the one on your left when the two ports face you. On the ESP32-S3 DevKit that's the board's **native USB** port (labeled `USB`); the browser flasher (Web Serial + Improv) talks to it directly. The right-hand port goes through a separate USB-to-UART bridge chip and is the one Arduino IDE uses (§8.2) — the flasher may still write the firmware through it, but the Wi-Fi step never appears there, because the firmware only listens for it on the left port.
1. Visit **[patternflow.work](https://patternflow.work)** on a desktop browser.
2. Connect the ESP32-S3 to your computer with a USB-C **data cable**, using the **left port** (see above).
-3. Scroll to the **Patterns** section, click **"Flash Patternflow"**, pick the serial port, and follow the on-screen steps. Wi-Fi can be provisioned right there too (Improv-Serial).
-4. Disconnect, seat the module back into the board sockets (orientation per silkscreen), and connect power.
-5. **Load the patterns.** The image ships with **Origin only** — the rest live on the device's filesystem instead of inside the firmware, which is what freed the memory for everything else. Open **[the decks shelf](https://community.patternflow.work/community/decks)** and press **Install to my board** on the **Basics** pack: 33 patterns, one click, no account. Your browser fetches the pack and hands it to the board over your Wi-Fi, so the board is never talking to the internet itself.
+3. Open the **Pattern** tab, find **Got the hardware?**, click **"Flash Patternflow"**, pick the serial port, and follow the on-screen steps. A new install erases the module first; a module already running Patternflow is updated in place and keeps its patterns and Wi-Fi.
+4. **Wi-Fi.** When the install finishes, press **Next** and the flasher asks for your network (Improv-Serial). Type the name exactly — there is no list to pick from, and it is case-sensitive — and use a **2.4 GHz** network; the ESP32-S3 cannot see 5 GHz. If the install ends without asking, press **RST** on the module once, click **Flash Patternflow** again, pick the port, and choose **Connect to Wi-Fi**. Some modules do not restart into Patternflow on their own after flashing; the button does it.
+5. Disconnect, seat the module back into the board sockets (orientation per silkscreen), and connect power.
+6. **Load the patterns.** The image ships with **Origin only** — the rest live on the device's filesystem instead of inside the firmware, which is what freed the memory for everything else. Open **[the decks shelf](https://community.patternflow.work/community/decks)** and press **Install to my board** on the **Basics** pack: 33 patterns, one click, no account. Your browser fetches the pack and hands it to the board over your Wi-Fi, so the board is never talking to the internet itself. On a freshly flashed board the device's page first says **Storage needs formatting**: press **Format storage**, confirm, and the pack installs by itself as soon as the format is done. On Android, `patternflow.local` does not resolve — type the board's IP address (hold **K2**) into the **Device address** field on the Basics card instead.
> 🎛️ **One pattern after flashing is correct, not a failed install.** It used to be 34 baked into the image. They moved out so that patterns can be added and removed without reflashing, which is also how anything you make yourself reaches the panel.
@@ -262,11 +263,13 @@ No installation required — desktop **Chrome or Edge** only (Web Serial; Firefo
>
> The picker should now offer a line like `USB JTAG/serial debug unit (COM4) – Paired`. The number depends on which USB port you used.
>
+> In download mode the firmware cannot answer the flasher, so it treats the module as new and **erases it** — installed patterns and saved Wi-Fi included. Press **RST** alone to bring a module back to normal first if you only meant to update it.
+>
> Still nothing? It is almost always the cable — a charge-only USB-C one enumerates nothing at all. **There is no driver to install on this port**: the ESP32-S3 handles USB itself, so the CP2102 / CH34x links on the flasher's troubleshooting screen do not apply here.
-> 📶 **Changing Wi-Fi later.** The network you set during flashing is **saved on the device and reused on every boot** — it stays until you overwrite it. To move Patternflow to a different Wi-Fi, either **re-flash from the browser** (you'll set the new network during Improv provisioning), or in Arduino IDE do a **full erase** (Tools → *Erase All Flash Before Sketch Upload* → *Enabled*) and re-upload. A plain re-upload does **not** clear the stored credentials.
+> 📶 **Changing Wi-Fi later.** The network you set during flashing is **saved on the device and reused on every boot**. The panel remembers up to five networks — home, studio, a venue — and tries the most recent first, so moving it does not mean reflashing. Add or forget networks on the device's **Wi-Fi** page (the console at `patternflow.local`, or the board's IP address). A plain Arduino IDE re-upload does **not** clear the stored networks; **Tools → *Erase All Flash Before Sketch Upload*** does.
-> 📡 **No Wi-Fi where you are? The panel is one.** About fifteen seconds after it finds no known network, the panel raises its own hotspot: `patternflow-xxxx` (the name on its NETWORK screen - hold K2), password `patternflow`. Join it from a phone or a laptop and open `http://192.168.4.1/` - the whole console, including the Wi-Fi page, so you can add the network for wherever you are next and the panel joins it at once. The phone will say the network has no internet; that is true, and it stays connected. Mode (`auto`, `always`, `off`) and the password are on the console's Wi-Fi page.
+> 📡 **No Wi-Fi where you are? The panel is one.** *(Firmware after v3.10.4; the Performance edition v0.4.0 has it already.)* About fifteen seconds after it finds no known network, the panel raises its own hotspot: `patternflow-xxxx` (the name on its NETWORK screen - hold K2), password `patternflow`. Join it from a phone or a laptop and open `http://192.168.4.1/` - the whole console, including the Wi-Fi page, so you can add the network for wherever you are next and the panel joins it at once. The phone will say the network has no internet; that is true, and it stays connected. Mode (`auto`, `always`, `off`) and the password are on the console's Wi-Fi page.
*Photos from the v2 guide — the flashing flow is identical on v3.*
@@ -290,7 +293,7 @@ OSC, network MIDI and audio-react ship in the **Audio** edition: open [patternfl
2. The panel lights up with the default pattern (Origin) within a second or two.
3. Turn all four knobs — each should visibly change the pattern.
4. Press-click each encoder once; long-press **K4** (~1s) to enter pattern select, rotate to browse, long-press again to exit.
-5. Long-press **K1** for the global brightness mode; **K2** long-press shows the OSC info screen.
+5. Long-press **K1** for the global brightness mode; **K2** long-press shows the NETWORK screen (Wi-Fi state and IP address); **K3** long-press puts each knob's number on the panel.
6. Power-cycle once and confirm it boots cleanly with no RESET press needed (see the GPIO0 note in Section 5 if it doesn't).
7. All good? **Close the back panel**: hook the right edge in first, then press along the snap-fit until it clicks shut (shown at **09:11** in the [assembly video](https://youtu.be/J9C9bZgkNKs)). Press the knobs onto the shafts last.
diff --git a/web/public/flash/manifest.json b/web/public/flash/manifest.json
index 6da49afe..c606a0dc 100644
--- a/web/public/flash/manifest.json
+++ b/web/public/flash/manifest.json
@@ -1,7 +1,7 @@
{
"name": "Patternflow",
"version": "v3.10.4",
- "new_install_prompt_erase": true,
+ "new_install_prompt_erase": false,
"new_install_improv_wait_time": 20,
"builds": [
{
From 6e494867b532fc48e5df557d401de0a71cbaf0af Mon Sep 17 00:00:00 2001
From: engmung <122682380+engmung@users.noreply.github.com>
Date: Tue, 29 Sep 2026 23:27:40 +0900
Subject: [PATCH 02/12] docs: stale references across the guides and specs
- README: the Capture panel is Graphic Export; batch generation needs a
Gemini key or an AI chat
- AUDIO_GUIDE: "Mapping editor", the mic's switch is Microphone (AUD is
the extension and phone input), MIDI is switched off on the console's
MIDI page - the Audio edition's NETWORK screen has room for two rows
- mqtt-spec: two panels follow each other on Live; channels 1-4 force
Subscriber, so the old example could not have a leader
- EDITIONS: three editions are on the shelf, not four
- rest-api: the clock is in the Performance edition
- pfst-v2-spec, LICENSE-SUMMARY, the Ableton README and web/ARCHITECTURE
point at what exists now
- sitemap lists /editions instead of the /variants redirect
Co-Authored-By: Claude Opus 5.5
---
AUDIO_GUIDE.md | 10 +++++-----
README.md | 2 +-
docs/EDITIONS.md | 5 +++--
docs/LICENSE-SUMMARY.md | 2 +-
docs/mqtt-spec.md | 2 +-
docs/pfst-v2-spec.md | 2 +-
docs/rest-api.md | 2 +-
integrations/ableton/README.md | 2 +-
web/ARCHITECTURE.md | 4 ++--
web/src/app/sitemap.ts | 5 +++--
10 files changed, 19 insertions(+), 17 deletions(-)
diff --git a/AUDIO_GUIDE.md b/AUDIO_GUIDE.md
index f6bcf373..f0448d77 100644
--- a/AUDIO_GUIDE.md
+++ b/AUDIO_GUIDE.md
@@ -48,7 +48,7 @@ the active tab) → enter your panel's address (`patternflow.local` or its IP)
→ the knobs move with the music. (Make sure **Audio-React (AUD)** is turned on
at the top of the console's **Audio** page or via the panel's NETWORK screen.)
-**Then open the editor** (*Editor ↗* in the popup) — this is where it gets
+**Then open the editor** (*Mapping editor ↗* in the popup) — this is where it gets
good. Each of the four knobs is a **box drawn on the live spectrum**: the
box's width is the frequencies it listens to, its height the loudness window
it maps. Drag a box over the bass and knob 1 becomes a bass knob. Inside
@@ -67,7 +67,7 @@ Boxes map to knobs 1:1 and that's fixed on purpose — box 2 *is* knob 2.
A small PDM microphone soldered to the DevKit lets the panel react to the
room itself — no browser, no phone, nothing else running. This is an
optional add-on: the firmware ships with the mic **off** and costs nothing
-until you build and enable it.
+until you solder one on and switch it on.
### What to buy
@@ -125,7 +125,7 @@ Stick the mic wherever sound reaches it. Done.
### Turn it on
-Console → **Audio** page (`/audio-in`) → flip **Microphone** or **Audio-React (AUD)** on. That's the
+Console → **Audio** page (`/audio-in`) → flip **Microphone** on. (**Audio-React (AUD)** beside it is the other input, the extension and the phone app.) That's the
whole switch: on means listening and driving the knobs, off releases the
hardware completely. The **gain** slider (1–16, default 8) is there if your
room runs quiet — PDM mics on this chip are famously low-amplitude, and gain
@@ -175,8 +175,8 @@ computer's address so it reconnects itself after a reboot — is
This is the missing half of [`docs/director-midi.md`](docs/director-midi.md):
the Director's `.mid` export writes CC 20–23, so drop the clip on a MIDI
track, set the track's output to the panel's port, and the show plays on the
-panel from Live's transport. The `MIDI` row on the panel's NETWORK screen
-switches it off without reflashing; `/api/status` reports the session,
+panel from Live's transport. The switch on the console's **MIDI** page turns it
+off without reflashing; `/api/status` reports the session,
sensitivity and message counts under `midi`.
## OSC — Ableton today, anything tomorrow
diff --git a/README.md b/README.md
index 512b0114..2f294b3d 100644
--- a/README.md
+++ b/README.md
@@ -70,7 +70,7 @@ You don't need hardware to start. The **[Live Editor](https://patternflow.work/p
-**[Pattern Lab](https://patternflow.work/pattern-lab)** is the full studio, and where a pattern reaches the hardware. Generate variations in batches, shape color ramps, retune knob ranges, then send it to your device: it builds into a small `.pfm` module and installs over Wi-Fi, about ten seconds start to finish. You never plug in a cable, reflash the board, or open an IDE. The Capture panel takes the same pattern off the panel: a PNG at print size for a business card, or an MP4 loop for a post, rendered in your browser with nothing uploaded.
+**[Pattern Lab](https://patternflow.work/pattern-lab)** is the full studio, and where a pattern reaches the hardware. Generate variations in batches (in the Lab with your own Gemini key, or through any AI chat), shape color ramps, retune knob ranges, then send it to your device: it builds into a small `.pfm` module and installs over Wi-Fi, about ten seconds start to finish. You never plug in a cable, reflash the board, or open an IDE. The Graphic Export panel takes the same pattern off the panel: a PNG at print size for a business card, or an MP4 loop for a post, rendered in your browser with nothing uploaded.
When it looks right, publish it to the **[Community](https://community.patternflow.work/community)**. More than a hundred patterns are up already and the range keeps widening, from quiet waves to chaos-theory studies, every one written as code and every one playable under the same four knobs. Collect patterns into a deck and send it to your board in one click. Browsing needs no account, and publishing asks a username and password, no email. The **[Pattern Guide](PATTERN_GUIDE.md)** walks the whole loop.
diff --git a/docs/EDITIONS.md b/docs/EDITIONS.md
index 06bd50f3..a4469d33 100644
--- a/docs/EDITIONS.md
+++ b/docs/EDITIONS.md
@@ -57,14 +57,15 @@ itself and any settings it needs different.
**An edition** is a composition somebody published — a firmware with a name, a
version of its own, and a card on
[patternflow.work/editions](https://patternflow.work/editions) that installs it
-in one click. Four exist:
+in one click. Three are on the shelf:
| | carries | whose |
|---|---|---|
| **Patternflow** | nothing — the device itself | the product |
| **Audio** | OSC, MIDI, browser audio, the on-board microphone | SeungHun Lee |
| **Performance** | sequences, MQTT, FlowLocal, the Director, weather, the clock | Simone Majocchi |
-| **Clock** | the time, cut out of the running pattern | SeungHun Lee |
+
+The clock and USB MIDI also build as bundles of their own, with a try-out image each on the features page and no card (below).
The word "addon" is retired. It suggested something optional or third-party,
and none of these are: they are first-class capabilities that happen to live
diff --git a/docs/LICENSE-SUMMARY.md b/docs/LICENSE-SUMMARY.md
index 6a7d2a64..d6661299 100644
--- a/docs/LICENSE-SUMMARY.md
+++ b/docs/LICENSE-SUMMARY.md
@@ -52,7 +52,7 @@ These are different things and are governed by different documents.
| Where | GitHub PR / issue | The community site, from the Pattern Lab |
| What | Code, hardware files, docs, build-map entries | Patterns |
| License | Inbound = outbound: MIT for code, CC BY-SA 4.0 for the rest | The author's choice, above |
-| Governed by | [CONTRIBUTING.md](../CONTRIBUTING.md) | Terms of use *(not yet written)* |
+| Governed by | [CONTRIBUTING.md](../CONTRIBUTING.md) | [Terms of use](https://patternflow.work/terms) |
## Trademark
diff --git a/docs/mqtt-spec.md b/docs/mqtt-spec.md
index 533efc43..97252a56 100644
--- a/docs/mqtt-spec.md
+++ b/docs/mqtt-spec.md
@@ -68,7 +68,7 @@ mqtt:
Node-RED, driving knob 2 of an `absoluteReady` pattern from a slider: an `mqtt out` node on topic `patternflow/param/2` with the slider's `0`–`1000` value; put the panel on Broadcast in Subscriber role first.
-Two panels following each other: point both at the same broker, same prefix on a show channel (`patternflow1`), one as Publisher and the other as Subscriber.
+Two panels following each other: point both at the same broker, same prefix on Live (`patternflow5`), one as Publisher and the other as Subscriber. Not channels 1–4: they force every panel on them to Subscriber, so neither would lead.
## Version history
diff --git a/docs/pfst-v2-spec.md b/docs/pfst-v2-spec.md
index 71fad293..f1d74888 100644
--- a/docs/pfst-v2-spec.md
+++ b/docs/pfst-v2-spec.md
@@ -16,7 +16,7 @@ layout, which is why v1 tables still load unchanged.
**Status:** shipped in Patternflow firmware v3.6.3
(`firmware/patternflow/features/show/core_show.h`) and in the site's
encoder/decoder
-(`web/src/lib/community/performance.ts`). v1 tables are byte-identical to
+(`web/src/lib/pattern/pfst.ts`). v1 tables are byte-identical to
what they always were.
---
diff --git a/docs/rest-api.md b/docs/rest-api.md
index f11dc7d8..a07557e1 100644
--- a/docs/rest-api.md
+++ b/docs/rest-api.md
@@ -358,7 +358,7 @@ toggles — from the console's `/audio-in` bar.
| `GET /api/audio` | `audioRuntime` (the switch) and `audioClients` (WebSocket senders connected on :81). |
| `POST /api/audio` | `on=0/1`. Persisted in NVS; answers with the new state. |
-## Clock (Clock edition)
+## Clock (Performance edition)
Gated on `"clock"` in `caps`; the page is `/clock`. Settings persist in NVS
under the feature's own namespace, and `/api/status` carries a `clock` block
diff --git a/integrations/ableton/README.md b/integrations/ableton/README.md
index c86bce27..a74f69df 100644
--- a/integrations/ableton/README.md
+++ b/integrations/ableton/README.md
@@ -26,7 +26,7 @@ integrations/ableton/
OSC ships in the **Audio** edition. Open [patternflow.work/editions](https://patternflow.work/editions), pick Audio, and install it from the browser; your patterns, Wi-Fi networks and settings stay. No rebuild, no secrets file. (Building your own image with the OSC feature is also possible; that is [docs/EDITIONS.md](../../docs/EDITIONS.md).)
-You do **not** need to set your computer's IP: the device learns it from the bridge's ping. Check the K2 long-press info screen: OSC should read `READY` or `WAIT HOST`.
+You do **not** need to set your computer's IP: the device learns it from the bridge's ping. Check the K2 long-press NETWORK screen: the OSC row should read `ON`.
## 2. Install the bridge device
diff --git a/web/ARCHITECTURE.md b/web/ARCHITECTURE.md
index caf187c2..0fc02e27 100644
--- a/web/ARCHITECTURE.md
+++ b/web/ARCHITECTURE.md
@@ -41,7 +41,7 @@ HomeView (src/components/HomeView.tsx)
└── RightPanel (components/sections/) ← tabbed content panel
├── Hero.tsx / Deck.tsx ← hero copy + panel open/close orchestration
├── BuildPanel.tsx ← build paths, flasher entry
- ├── PatternPanel.tsx ← preset browser + knobs; every CTA leads to /pattern-lab
+ ├── PatternPanel.tsx ← preset browser + code editor; every CTA leads to /pattern-lab
├── InsidePanel.tsx + InsideGlobe/ ← concept content + community builds globe
└── Sponsor.tsx
```
@@ -114,7 +114,7 @@ PostHog (`src/providers/PostHogProvider.tsx`, event helpers in `src/lib/posthogE
- Styling: Tailwind v4 (`@import "tailwindcss"` in `globals.css`) + global custom CSS; larger components use CSS Modules (`*.module.css`).
- **Layering:** `lib/` is the bottom. `app/` and `components/` import from it; it never imports from them (ESLint enforces it). A type a component and a serializer share belongs in `lib/` — `lib/community/cardTypes.ts` is the precedent.
-- Adding a preset: add the JS file under `src/lib/presets/`, register it in `index.ts`, then generate the firmware `.h` with the Pattern Lab "Copy C++ prompt" flow.
+- Adding a preset: add the JS file under `src/lib/presets/`, register it in `index.ts`, then generate the firmware `.h` with the Pattern Lab's **To hardware** → *Copy the conversion prompt* flow.
- Tests are the `check:*` scripts in `package.json` — bespoke smoke suites under `scripts/*-smoke.ts`, one per subsystem — plus `check:panels`, a Vitest + jsdom + Testing Library harness (`vitest.config.ts`, `test/setup.ts`) for the Pattern Lab panels, where pointer gestures, keyboard shortcuts, undo and the Director's keyframes need a DOM. Those tests live beside the panels (`panels/*.test.tsx`) and read the store's buffers rather than the canvas, which jsdom does not have. `npm run check:ci` runs every one that needs nothing a CI runner lacks; `check:module` wants the Xtensa toolchain and stays local.
- CI (`.github/workflows/web-ci.yml`) lints, typechecks (`npm run typecheck`), builds and runs `check:ci` on every PR touching `web/`.
- **Deployment weight:** Vercel meters storage per *retained deployment* — every one counts at its full output size, static files and function bundles both, with nothing shared between deployments — so size × push count is what the Hobby allowance (10 GB each) is spent on. Only `main` deploys: `vercel.json` turns deployments off for `dev`, which was three quarters of them and whose previews nobody opened. `public/` is ~90 % of a deployment's static weight (journal and build-map photos). Server functions must carry none of it: `outputFileTracingExcludes` in `next.config.ts` keeps `public/` out of every function, and a build that prints "Dynamic filesystem access causes tracing of the whole project" has found a new way in — the comment there has the history.
diff --git a/web/src/app/sitemap.ts b/web/src/app/sitemap.ts
index 0901cef1..dc7d6023 100644
--- a/web/src/app/sitemap.ts
+++ b/web/src/app/sitemap.ts
@@ -13,9 +13,10 @@ export default function sitemap(): MetadataRoute.Sitemap {
{ url: `${siteUrl}/build`, lastModified: now, changeFrequency: "monthly", priority: 0.8 },
{ url: `${siteUrl}/inside`, lastModified: now, changeFrequency: "monthly", priority: 0.7 },
{ url: `${siteUrl}/roadmap`, lastModified: now, changeFrequency: "weekly", priority: 0.6 },
- // The shelf of firmwares built on core. A device running a variant links
+ // The shelf of firmwares built on core. A device running an edition links
// here from its own console, so this needs to be findable from outside too.
- { url: `${siteUrl}/variants`, lastModified: now, changeFrequency: "monthly", priority: 0.6 },
+ // (/variants only redirects here.)
+ { url: `${siteUrl}/editions`, lastModified: now, changeFrequency: "monthly", priority: 0.6 },
// The catalogue of features, with a reel of each - the other axis of the shelf.
{ url: `${siteUrl}/features`, lastModified: now, changeFrequency: "monthly", priority: 0.6 },
{ url: `${siteUrl}/contact`, lastModified: now, changeFrequency: "yearly", priority: 0.5 },
From 09548275c4e7868698579805b1ff419cf6cf72e2 Mon Sep 17 00:00:00 2001
From: engmung <122682380+engmung@users.noreply.github.com>
Date: Wed, 30 Sep 2026 09:15:37 +0900
Subject: [PATCH 03/12] web: /guide, an interactive usage guide (work in
progress)
A scroll-driven page over a fixed 3D Patternflow: the landing page's model
re-wired to a firmware simulator (lib/guide/deviceSim.ts, the device's own
screens ported from patternflow.ino in panelScreens.ts), the v3.9 board
exported from KiCad, the ESP32 DevKit, chapters one to four in English and
Korean, and a Guide link in the site nav. Checkpoint before the case model,
the flasher screens and the console window land.
Co-Authored-By: Claude Opus 5.5
---
web/public/guide/console/home-desktop.webp | Bin 0 -> 24614 bytes
web/public/guide/console/home-phone.webp | Bin 0 -> 23854 bytes
web/public/guide/console/knobs.webp | Bin 0 -> 13712 bytes
web/public/guide/console/patterns.webp | Bin 0 -> 10432 bytes
web/public/guide/console/wifi.webp | Bin 0 -> 25400 bytes
web/public/guide/devkit.glb | Bin 0 -> 391652 bytes
web/public/guide/pcb-v39.glb | Bin 0 -> 256528 bytes
web/src/app/guide/ko/page.tsx | 21 +
web/src/app/guide/page.tsx | 21 +
web/src/app/sitemap.ts | 2 +
web/src/components/guide/Extras.tsx | 485 +++++++++
web/src/components/guide/Guide.module.css | 959 +++++++++++++++++
web/src/components/guide/GuideExperience.tsx | 236 +++++
web/src/components/guide/copy.ts | 574 ++++++++++
web/src/components/guide/scenes.ts | 259 +++++
web/src/components/guide/stage/Device.tsx | 412 ++++++++
web/src/components/guide/stage/Fx.tsx | 603 +++++++++++
.../components/guide/stage/GuideCanvas.tsx | 384 +++++++
web/src/components/guide/stage/KitFx.tsx | 212 ++++
web/src/components/guide/stage/geometry.ts | 43 +
web/src/components/guide/stage/parts.ts | 85 ++
web/src/components/guide/stage/views.ts | 28 +
web/src/components/guide/store.ts | 54 +
.../components/journal/HeroJournalLink.tsx | 1 +
web/src/lib/guide/basicsNames.ts | 42 +
web/src/lib/guide/deviceSim.ts | 540 ++++++++++
web/src/lib/guide/glcdFont.ts | 318 ++++++
web/src/lib/guide/panelScreens.test.ts | 257 +++++
web/src/lib/guide/panelScreens.ts | 979 ++++++++++++++++++
web/src/lib/guide/tomThumbFont.ts | 274 +++++
30 files changed, 6789 insertions(+)
create mode 100644 web/public/guide/console/home-desktop.webp
create mode 100644 web/public/guide/console/home-phone.webp
create mode 100644 web/public/guide/console/knobs.webp
create mode 100644 web/public/guide/console/patterns.webp
create mode 100644 web/public/guide/console/wifi.webp
create mode 100644 web/public/guide/devkit.glb
create mode 100644 web/public/guide/pcb-v39.glb
create mode 100644 web/src/app/guide/ko/page.tsx
create mode 100644 web/src/app/guide/page.tsx
create mode 100644 web/src/components/guide/Extras.tsx
create mode 100644 web/src/components/guide/Guide.module.css
create mode 100644 web/src/components/guide/GuideExperience.tsx
create mode 100644 web/src/components/guide/copy.ts
create mode 100644 web/src/components/guide/scenes.ts
create mode 100644 web/src/components/guide/stage/Device.tsx
create mode 100644 web/src/components/guide/stage/Fx.tsx
create mode 100644 web/src/components/guide/stage/GuideCanvas.tsx
create mode 100644 web/src/components/guide/stage/KitFx.tsx
create mode 100644 web/src/components/guide/stage/geometry.ts
create mode 100644 web/src/components/guide/stage/parts.ts
create mode 100644 web/src/components/guide/stage/views.ts
create mode 100644 web/src/components/guide/store.ts
create mode 100644 web/src/lib/guide/basicsNames.ts
create mode 100644 web/src/lib/guide/deviceSim.ts
create mode 100644 web/src/lib/guide/glcdFont.ts
create mode 100644 web/src/lib/guide/panelScreens.test.ts
create mode 100644 web/src/lib/guide/panelScreens.ts
create mode 100644 web/src/lib/guide/tomThumbFont.ts
diff --git a/web/public/guide/console/home-desktop.webp b/web/public/guide/console/home-desktop.webp
new file mode 100644
index 0000000000000000000000000000000000000000..e111553740989342c57ae03f64226bf400cd591b
GIT binary patch
literal 24614
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