Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ All notable changes to Patternflow will be documented in this file, newest first

### Web

- **Pattern Lab's Preview, Pixel, Color Ramp and Knobs rules live with their panels.** The 20 rules only one panel file read moved from the dock's `LabPanels.module.css` to that panel's stylesheet, Pixel's in a new `PixelPanel.module.css`, and a test fails when the dock file holds a class only one panel file reads. Computed styles in 13 Lab states at 390px and 1440px match `dev`.
- **A moving text layer whose words are deleted goes blank, and a long scroll opens again still moving.** Emptying the text of a scrolling or ramp-running layer left the old letters moving in the preview and both exports. A line too long for a 64 × 128 source after the panel was turned, or set right of its X past 4,096 columns, saved but reopened standing still; every step that makes or reads a source now places it the same way. The Text panel no longer says a font file is kept for next time when this browser would not keep it.
- **The guide's practice wall turns a knob as the community's cards do.** Its cards kept a copy of the old card step, floored at 0.001 and rounded to three decimals, so a knob declared 0.0001..0.0004 fell to 0 on the first notch and its bar showed the middle of that range as 15%. Both cards now call `knobWheelValue` in `lib/pattern/controls.ts`, and the guide's device simulator and the first screen's 3D panel read a knob's 0..1 through `normalizeKnob`.
- **The Make guide's Lab window shows the Lab as it opens now.** Its picture, on the phone card and under the desk's live Lab, still had the Gallery tab removed on 23 October. Retaken at the same 1024 × 680, it has the Text tab and + Text.
- **Pattern Lab reads a saved frame size and a moving text's source through typed helpers.** Seven non-null assertions are gone. A hand-edited size of 127.6 now opens as 128, and a scroll frame asked of a layer with no source leaves the frame alone instead of throwing.
- **The global stylesheet drops 377 lines of old Inside panel rules.** `InsidePanel` moved to its own CSS module, and nothing read the 24 `inside-*` and `reddit-*` classes left in `globals.css`. The CSS chunk every page loads is 6,107 bytes smaller (1,104 gzipped), and computed styles on five pages at 390 and 1440 px are unchanged.
- **Five CSS modules outside Pattern Lab drop 23 classes no component used.** The roadmap's old legend and zoom buttons and the community's sign-in gate go with their 30 rules, and the CSS module test now reads every module under `web/src`, not only the Lab's.
- **The site also builds as a Cloudflare Worker.** `npm run cf:build` turns `web/` into the `patternflow-web` Worker through OpenNext, and `web/DEPLOY-cloudflare.md` has the move off Vercel and the way back. Vercel Analytics gave way to a Cloudflare Web Analytics beacon, and the RSS feed and the journal's share cards are drawn at build.
- **Pattern Lab no longer has the AI gallery or a Gemini key.** The Gallery panel, its batch generation and the key field are gone, and so is the `@google/genai` dependency: the site calls no AI itself. Copy prompt stays, with the v-field/rgb choice beside it in the Code tab now. Opening the Lab removes the gallery's saved patterns and the key from the browser, and a saved dock layout opens without the Gallery tab instead of falling back to the default.
- **Pattern Lab has text layers.** + Text adds a layer you type into, set in the site's pixel font, a generic system family, or a .ttf, .otf, .woff or .woff2 file from your own device. The file is read in the browser and never uploaded, and the browser keeps it only when you tick remember. Size, X and Y, alignment, one color or the layer's Color Ramp across or down, sharp or soft edges; a drag on Preview moves the text, by touch too. The text is drawn into a bitmap, so it blends, masks, renders in Graphic Export and travels in both exports as pixel art.
- **Pattern Lab's text layer copies out as code, and its firmware header is checked against the preview.** Copy as code in the Text panel hands the drawn letters to an AI chat as a pattern that needs no font, with a marked place to warp them and another to change their light. To hardware says a stack of text and pixel layers is a finished header with nothing to translate. A new test compiles that header with the host's C++ compiler and finds it lights the same pixels as the Lab preview and the flattened JS, apart from exact half steps at 50% and 25% opacity, where the browser's doubles and the board's floats round one level apart.
Expand Down Expand Up @@ -152,6 +160,7 @@ All notable changes to Patternflow will be documented in this file, newest first

### Docs

- **The Pattern Guide's two Lab screenshots show the current Lab.** `11-pattern-lab.png` and `13-color-ramp.png` still had the Gallery tab. They are retaken at 1920 × 1080 with the same scenes, the hsv short ramp included.
- **The build service docs describe the worker that runs today.** `docs/SERVICES.md` and `web/.env.example` still said the worker compiles firmware with arduino-cli and offered `ARDUINO_CLI_PATH` and `BUILD_FQBN`, which nothing has read since whole-image builds ended on 12 August. `.env.example` now lists `PF_XTENSA_BIN`, `PF_TARGET_ABI` and `GITHUB_TOKEN`, and `src/lib/envExample.test.ts` fails when it, the code and the table in `web/ARCHITECTURE.md` disagree.
- **The docs index, the repository map and the contributor guide describe the tree as it is.** `docs/README.md` lists the cleanup RFC and its log, the rename list in `docs/REPOSITORY.md` names all 30 files the site's absolute links reach (it had ten and the BOM), `CONTRIBUTING.md` names the four build kinds and `originId`, and `docs/EDITIONS.md` says `build.sh all` builds five compositions.
- **The cleanup's progress log records steps 1 to 5 and the gate.** `docs/rfc-cleanup-progress.md` has an entry for each step and checks the six items of §2.12 at `9dff573`, and all six hold. `docs/rfc-cleanup.md` is marked done.
Expand Down
Binary file modified docs/images/pattern-guide/11-pattern-lab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/pattern-guide/13-color-ramp.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion web/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
NEXT_PUBLIC_POSTHOG_KEY=phc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com

# Cloudflare Web Analytics: the site's token, from the Cloudflare dashboard
# (Web Analytics, manual setup). Read when the site is built, so it belongs in
# the build's environment and not in `wrangler secret`. Unset, no beacon loads.
#NEXT_PUBLIC_CF_WEB_ANALYTICS_TOKEN=

# ── Roadmap ─────────────────────────────────────────────────────────────────
# /api/roadmap reads the repository's open issues from the GitHub API on the
# server. A token raises GitHub's rate limit; the repository is public, so the
Expand All @@ -10,7 +15,8 @@ NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com

# ── Community (self-hosted deployment only) ──────────────────────────────────
# The community runs where this flag is set (the Raspberry Pi / VPS). Leave it
# unset on Vercel — community pages then show a pointer to the community host.
# unset on Vercel and on the Cloudflare Worker — community pages then show a
# pointer to the community host.
COMMUNITY_ENABLED=1

# Better Auth session signing secret. Generate one:
Expand Down
5 changes: 5 additions & 0 deletions web/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,8 @@ next-env.d.ts

# community database (SQLite) — data never enters the public repo
/data

# Cloudflare Workers (OpenNext, wrangler)
/.open-next/
/.wrangler/
.dev.vars*
5 changes: 3 additions & 2 deletions web/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,15 @@ A published header is compiled **once** and kept beside the code in `module_cach

## Analytics

PostHog (`src/providers/PostHogProvider.tsx`, event helpers in `src/lib/posthogEvents.ts`) plus Vercel Analytics / Speed Insights. All no-ops when the env vars are absent. `posthog-js` is fetched with `import()` after the page's load event, and an event captured before then waits in `posthogEvents.ts` with its own time. A static import of it puts 318 KB back into every page's first scripts; `posthogEvents.test.ts` fails on one.
PostHog (`src/providers/PostHogProvider.tsx`, event helpers in `src/lib/posthogEvents.ts`) plus Cloudflare Web Analytics, a beacon `app/layout.tsx` adds when `NEXT_PUBLIC_CF_WEB_ANALYTICS_TOKEN` is set at build. It counts visits and Core Web Vitals, which Vercel Analytics and Speed Insights did until 25 October 2026. All no-ops when the env vars are absent. `posthog-js` is fetched with `import()` after the page's load event, and an event captured before then waits in `posthogEvents.ts` with its own time. A static import of it puts 318 KB back into every page's first scripts; `posthogEvents.test.ts` fails on one.

## Environment variables

`web/.env.example` is the complete, commented list. `src/lib/envExample.test.ts` fails when the code reads a variable the file leaves out, when the file offers one nothing reads, or when this table and the file disagree. The site builds and runs with none set; each group switches on one deployment concern:

| Group | Vars |
| :--- | :--- |
| Analytics | `NEXT_PUBLIC_POSTHOG_KEY`, `NEXT_PUBLIC_POSTHOG_HOST` |
| Analytics | `NEXT_PUBLIC_POSTHOG_KEY`, `NEXT_PUBLIC_POSTHOG_HOST`, `NEXT_PUBLIC_CF_WEB_ANALYTICS_TOKEN` |
| Roadmap | `GITHUB_TOKEN` |
| Community host | `COMMUNITY_ENABLED`, `BETTER_AUTH_SECRET`, `BETTER_AUTH_URL`, `COMMUNITY_DB_PATH`, `COMMUNITY_ALLOWED_ORIGINS`, `COMMUNITY_ADMIN_USERNAMES` |
| Every deployment with a community | `NEXT_PUBLIC_COMMUNITY_URL` |
Expand All @@ -120,4 +120,5 @@ PostHog (`src/providers/PostHogProvider.tsx`, event helpers in `src/lib/posthogE
- 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`) that runs every `src/**/*.test.ts` and `*.test.tsx`, each beside the file it tests. The name is from its first tests, the Pattern Lab panels, where pointer gestures, keyboard shortcuts, undo and the Director's keyframes need a DOM. Those read the store's buffers rather than the canvas, which jsdom does not have. The guide, the landing sections, the community and `lib/` have tests there too now. Some, like `lib/pattern/knobs.test.ts`, call plain functions and never touch the DOM. `npm run check:ci` runs every one that needs nothing a CI runner lacks; `check:module` wants the Xtensa toolchain and stays local. The drift checks are `check:*` scripts too, one file each in `scripts/drift/`. Each compares two things the tree keeps by hand, the BOM and the build guide's parts table for one, and `check:drift`, the last step of `check:ci`, runs them all. Five hold a contract against a running panel instead. `check:rest-vectors`, `check:osc-vectors`, `check:midi-vectors`, `check:mqtt-vectors` and `check:audio-vectors` replay the vectors beside each spec in `docs/` against the virtual panel in `tools/virtual-panel/`, which is `lib/guide/`'s `DeviceSim` behind the firmware's ports. A vector also fails when the spec sentence it quotes is gone. `check:virtual-panel` is not a vector suite: it runs every preset on that panel. A file there whose name starts with `_` is a library the suites share. `_broker.ts` among them is a test broker, because a Patternflow is a broker's client and the MQTT suite has to bring one.
- CI (`.github/workflows/web-ci.yml`) lints, typechecks (`npm run typecheck`, which reads `tools/virtual-panel/` too), builds and runs `check:ci` on every PR touching `web/`. `.github/workflows/drift.yml` runs `check:drift` on every PR, whatever it touches, and `check:human-lock` against the PR's base. It sets `PF_DRIFT_STRICT=1`: at a desk a check skips a side it cannot read (a tag the clone lacks, no `pdftotext`), and in CI that skip fails.
- **Cloudflare Workers:** the same tree builds for Workers with `npm run cf:build` (OpenNext, `wrangler.jsonc`, `open-next.config.ts`). `DEPLOY-cloudflare.md` has the move from Vercel, what differs there and the way back.
- **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.
Loading
Loading