This is the active planning board: things still to do. Site architecture, design patterns, the chat-to-PR workflow, and history of shipped work live in CLAUDE.md at the repo root. When work is shipped or new items are identified, both files should be updated in the same PR.

🚀

Future Work

Re-enable local development against the live API

Dev experience

The single-server consolidation replaced full URLs (https://data.orcsgirls.org/api/...) with relative paths (/api/...). This is correct for production but breaks local development — running the static frontend on localhost:8000 makes fetch('/api/...') hit localhost:8000/api/... which 404s.

Fix: introduce /api-base.js at the repo root that sets window.API_BASE based on hostname detection.

// /api-base.js
window.API_BASE = (function () {
    var h = location.hostname;
    return (h === 'localhost' || h === '127.0.0.1' || h === '' || h.endsWith('.local'))
        ? 'https://play.orcsgirls.org'
        : '';
}());

Production hostname → empty string (relative paths preserved, no behaviour change). Localhost / 127.0.0.1 / .local → full URL to live API.

Then each fetch('/api/...') becomes fetch(API_BASE + '/api/...'). Touch points (about 10 files):

  • access.js
  • admin/_admin-common.js (in apiGet / apiPost helpers)
  • admin/submissions.html
  • quiz/index.html
  • quiz/host.html
  • quiz/js/quiz-client.js
  • web/showcase.html
  • web/editor.html
  • web/js/unicode-names.js
  • science/js/Fourdem.js

Add <script src="/api-base.js"></script> in <head> of every page that makes API calls — load it next to theme-init.js for consistency.

PHP side: no changes needed. api/_db.php already includes http://localhost, http://localhost:80, http://localhost:8000, and http://127.0.0.1 in its CORS allowlist (lines 18–24). The previous CORS audit during single-server consolidation kept these in deliberately.

Note: this work will eventually fold into the planned shared/api.js module (Code Reuse Step 4 in CLAUDE.md). The minimal api-base.js version is a faster path to unblock local dev now; the full module can absorb it cleanly when that refactor happens.

Quiz — Scoring Enhancements

Ideas

Current scoring: 500 + round(500 × time_remaining / time_limit). Two natural extensions:

  • Answer-order bonus: first player to answer correctly gets a small additional bonus (e.g. +100 for 1st, +75 for 2nd, +50 for 3rd). Order is determinable from quiz_responses.answered_at — no schema change needed, just a COUNT(*) of prior correct responses at submit time in answer.php.
  • Streak multiplier: consecutive correct answers multiply the score (1× → 1.5× → 2×, reset on wrong). Requires a streak column on quiz_players (or computed per-player from quiz_responses at answer time). Rewards consistency; good as an opt-in mode since it changes the feel of the game significantly.

Quiz — Additional Question Types

Ideas
  • True / False: two-option variant — special two-button layout on mobile (large ✓ and ✗). Store as normal 2-answer question, just add a question_type flag for the display layer.
  • Image answers: answers are images rather than text. Useful for "which circuit is correct?" or "which graph matches the data?". Requires storing image_data on quiz_answers (not just quiz_questions).
  • Ordering / ranking: students drag answers into the correct sequence. More complex client-side interaction but high educational value for sequences, timelines, algorithm steps. Would need a new response schema (ordered list rather than single answer_id).
  • Short free-text entry: student types a word or number; teacher marks correct answers as an exact-match or case-insensitive list. Useful for "what year did X happen?" or "type the output of this code snippet". No multiple-choice overhead, but requires manual or automated marking.

Quiz — Image Annotation Tools

Ideas

The crop modal canvas is a natural foundation for lightweight annotation. After cropping, teacher could switch to an "annotate" mode to add:

  • Coloured arrows or circles to highlight specific parts of a diagram
  • Text labels (e.g. "what does this component do?")
  • A question mark overlay on a specific region to draw attention

Annotations would be rendered onto the canvas and baked into the JPEG at confirm time — no additional storage schema needed. The canvas-based architecture already supports this; it's purely a UI addition to the crop modal.

Quiz — Analytics & Results Export

Ideas
  • Per-student breakdown: after a session, show each player's answer to each question (correct/wrong, time taken). Currently only aggregate answer counts are shown on the reveal screen. All data exists in quiz_responses — it's a display feature.
  • CSV export: download session results as a spreadsheet (player, question, answer, correct, points, time). Useful for grading or class analysis. One PHP endpoint + a download button in the admin quiz list.
  • Cross-session tracking: identify which questions are consistently answered incorrectly across multiple runs of the same quiz. Useful for identifying topics that need re-teaching. Requires aggregating quiz_responses across sessions by question_id.

Quiz — Content & Workflow Improvements

Ideas
  • Quiz import from CSV/JSON: teacher prepares questions in a spreadsheet, uploads to populate the quiz builder. Reduces manual data entry for large question sets.
  • Question bank / copy between quizzes: a teacher-library of reusable questions. Drag or select individual questions from any existing quiz into the current editor.
  • Self-paced / practice mode: student joins a quiz without a teacher running it live. They work through questions at their own pace and see results immediately after each answer. Would require a separate session type with no host advance step.
  • Celebration screen: on the final done screen, show a brief confetti animation or podium (1st/2nd/3rd on a visual podium) before the full leaderboard. High motivation value for a classroom setting.

Logic Gate Simulator — Extension Ideas

Ideas
  • Wire labels: click a wire to give it a name displayed mid-wire — useful for tracing signal paths in complex circuits.
  • Export / import: serialise the circuit to JSON; allow dragging a JSON file onto the canvas to load it — enables teachers to share starter circuits.
  • Additional gate types: NAND, NOR, XNOR.
  • Challenge 5 — SR Latch: two NOR gates with cross-coupled feedback; introduces memory and state. Requires NOR gate and handling stable-state feedback in the evaluator.

Site-wide — Code Organisation & Layout Review

Low Priority

Layout consistency

Two layout patterns exist. Pages still needing migration to the sidebar (.tool-split) pattern: data/terminal.html, data/plotter.html, cyber/logic-gates.html. Leave as-is: cyber/binary.html (intentional full-screen), fun/dice.html (acceptable for simplicity).

Reusable code candidates

  • Nav boilerplate: all pages repeat ~12 identical header lines. A nav.js injection would reduce maintenance surface.
  • Toolbar/sidebar CSS: .toolbar-purple, .toolbar-btn, .ctrl-label, .ctrl-sel etc. duplicated across 5+ tools — consolidate into style.css.
  • Admin common JS: already extracted to _admin-common.js — good model to follow for future admin pages.

JS extraction (when touching these files)

  • cyber/binary.html (~625 lines) → cyber/js/binary.js
  • cyber/logic-gates.html (~820 lines) → cyber/js/logic-gates.js
  • fun/button-maker.html (~820 lines) → fun/js/button-maker.js
  • fun/element-name.html (~760 lines) → fun/js/element-name.js

Button Maker — Remaining Ideas

Ideas
  • Multiple designs per sheet: mix different button designs on one print sheet.
  • Border/outline ring: decorative coloured ring inside the button edge — common on name badges.

Cyber — Password Crack Time Visual Simulator

Pending

Standalone companion to the existing Password Strength Checker. Visual timeline of crack times at multiple attack speeds; adjustable inputs (length, character pool, entropy bits). Link from cyber/password.html.

Science — Fourier Camera Improvements

Pending
  • Verify iOS file-picker branch on current Safari
  • Show Retry button when camera permission is denied
  • Spectrum annotation: "Low frequency (shapes)" / "High frequency (edges)" overlay
  • Dedicated download button (currently buried in status bar)

Drawing Pad — Stamps & Mobile Testing

Pending
  • Create fun/stamps/ with paired red/cyan PNGs + manifest.json; loadStamps() fetches manifest — no base64 in source.
  • Test coordinate accuracy on iOS, Android and trackpads.

Separator Generator — Extension Ideas

Ideas
  • Vertical separators (portrait canvas mode)
  • Two-colour mode (alternate dot colours by index)
  • Mirrored symmetry toggle
  • Preset library dropdown
  • Multi-row stacked separators (honeycomb/brick pattern)
  • Responsive CSS export (tiling segment with background-repeat:repeat-x)
  • Live URL hash for shareable parameter links
  • Randomise button

Web Showcase — Future Improvements

Ideas
  • Auto-refresh so the showcase updates live during a class
  • Allow students to update their own submission (one-time secret code returned at submit time)

Internet of Things — Particle IoT Tools

Low Priority

Migrate existing Particle IoT tools into the site. Suggested location: new iot/ section with hub page + nav item. Owner will provide files when ready.

🐛

Bugs & Fixes Identified (Code Review)

The items below are open. Completed bugs from earlier sessions are recorded in CLAUDE.md's history section. Lettering gaps (a–c, e–h) are intentional — those items are closed and the letters are kept stable so commit history and earlier conversations still resolve.

(d) quiz/index.html does not load access.js — by design

Decision

None of quiz/index.html, quiz/play.html, or quiz/host.html include access.js. This is intentional: students should be able to scan the lobby QR code and join a quiz from any device without first holding a class code that day. Documented here so the next person doesn't add the gate by mistake. The other security layers (per-session PIN, host-token auth, rate-limited join.php, content scanner on nicknames) cover the quiz path independently.

(i) Quiz pages do not honour ?mode=standalone

Minor

standalone.js is not loaded on any quiz page. The player view is already chrome-light by design, so this may be intentional, but worth a note in the patterns section so the next person doesn't try to embed a quiz in standalone mode and wonder why the nav is still there. (The host page has a nav-like bar that standalone.js would not currently target either.)

🔧

Technical Debt

ItemFileStatusNotes
science.css consolidation science/science.css ⚠️ Pending Some Fourier Camera styles still inline in fourier-camera.html
Quiz image storage in DB column quiz_questions.image_data Minor Base64 JPEG stored as MEDIUMTEXT (~1 MB limit). Works well for current use. If larger images or better performance become needed, move to file system storage (UUID filename, serve via separate endpoint, store URL in DB instead). Would require an upload endpoint, file permissions, and cleanup logic for orphaned files.
Server-side question timer api/quiz/advance.php Minor Timer only auto-advances when the host screen is open and polling. If the teacher closes the browser mid-question, the question never auto-advances — players are stuck. Fix: a server-side cron job or a lazy check in state.php that auto-advances if question_started_at + time_limit < NOW().
Quiz session cleanup quiz_sessions table Minor Ended and abandoned sessions accumulate indefinitely. Add a scheduled cleanup (cron or lazy in start.php) to archive sessions older than 30 days. quiz_responses and quiz_players cascade-delete, so only the session rows need pruning.
admin/quiz.html size admin/quiz.html Minor ~550 lines including the full crop modal JS. Consider extracting to admin/js/quiz-builder.js and admin/js/crop-modal.js when the file is next substantially modified.