Stop tracking workspace/; bundled-demos/ is the canonical demo source

`workspace/` is runtime state (per-user folders, no-auth dev's `code/`)
and shouldn't be in git. The same files were previously committed under
both `workspace/code/` and `src/static/bundled-demos/`, which forced a
Docker `diff -q` sync check and leaked user-scoped paths into version
control.

- /workspace/ added to .gitignore; all previously tracked files removed
  via `git rm --cached`.
- src/static/bundled-demos/ becomes the single source of truth: panel16
  demos, led_tutorial, led_patterns, neopixel demos, and main.py move
  here alongside the existing canonical demos.
- New BUNDLED_DEMOS_DIR config; user_workspace seeders read from it.
- main.py lifespan seeds WORKSPACE_ROOT/code/ on startup so a fresh
  clone running `pipenv run dev` still gets the full sample set
  (existing files never overwritten — user edits survive restarts).
- Dockerfile drops `COPY workspace` and the diff sanity check.
- README/LED_TUTORIAL repointed at the new canonical paths.
- test_led_patterns loads led_patterns.py from bundled-demos.
- test_api uses mkdir(exist_ok=True) for `code/` (startup pre-creates).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-10 06:55:59 +12:00
parent b8d62e01d9
commit 7ee15f8eac
24 changed files with 86 additions and 418 deletions

View File

@@ -0,0 +1,50 @@
"""LED tutorial script for NeoPixel in the browser editor.
Run this file and watch the in-app NeoPixel simulator panel.
"""
from machine import Pin
import neopixel
import time
LED_COUNT = 12
np = neopixel.NeoPixel(Pin(4), LED_COUNT)
def show_step(title: str):
print(f"\n--- {title} ---")
show_step("Step 1: single colors")
np.fill((0, 0, 0))
np.write()
time.sleep(0.2)
np[0] = (255, 0, 0) # red
np[1] = (0, 255, 0) # green
np[2] = (0, 0, 255) # blue
np.write()
time.sleep(0.8)
show_step("Step 2: fill strip")
np.fill((40, 0, 120))
np.write()
time.sleep(0.6)
show_step("Step 3: moving pixel")
for i in range(len(np)):
np.fill((0, 0, 0))
np[i] = (255, 120, 0)
np.write()
time.sleep(0.06)
show_step("Step 4: simple pulse")
for level in list(range(0, 200, 20)) + list(range(200, -1, -20)):
np.fill((level, 0, level // 3))
np.write()
time.sleep(0.05)
show_step("Done")
np.fill((0, 0, 0))
np.write()
print("Tutorial complete.")