An interactive spelling bee practice application built with React and Vite.
- Interactive spelling bee game with voice recognition
- 12 grade-level word databases (K-12) with offline support via IndexedDB
- Multiple difficulty levels
- Progress tracking and statistics
- Mastered words system
- Feedback system with D1 database storage and Slack integration
- Admin dashboard for feedback management
- Progressive Web App (PWA) with offline-first architecture
- Node.js (v18 or higher recommended)
- npm or yarn
- Cloudflare account (for D1 database and Pages deployment)
npm installThis project is gradually migrating from JavaScript to TypeScript to improve type safety and developer experience.
- Migration Strategy - Phased migration approach, best practices, and progress tracking
- Training Guide - TypeScript patterns for React, practical examples from this codebase
- Style Guide - Naming conventions, coding standards, and best practices
- Migration Checklist - Step-by-step guide for converting files
Phase 1 - Core Type Definitions (In Progress)
- ✅ Phase 0 Complete: TypeScript infrastructure and tooling
- 🚧 Phase 1 In Progress: Adding type definitions to existing code
- 🚧 Phase 2 In Progress: All new code written in TypeScript
- ⏳ Phase 3 Planned: Gradual migration of existing files
New to TypeScript?
- Read the Training Guide - Start with React basics
- Review the Style Guide - Learn project conventions
- Use the Migration Checklist - Follow step-by-step process
Contributing TypeScript code?
- Follow the Style Guide for naming and patterns
- Run
npm run typecheckbefore submitting PRs - See CONTRIBUTING.md for full guidelines
This application is a Progressive Web App with comprehensive offline-first capabilities:
- Online/Offline Detection: Real-time connection status tracking
- Background Sync: Automatic data synchronization when connection is restored
- Sync Queue Management: IndexedDB-based queue with exponential backoff retry logic
- Service Worker: Caches assets and handles sync events
- Offline UI Indicators: Status badges, pending sync counts, and reconnection toasts
📚 Complete Documentation: Phase 4 PWA Implementation Guide
Includes architecture diagrams, API requirements, browser compatibility matrix, troubleshooting guide, and usage examples.
This application uses a grade-based word database system (grades 1-12) with offline support:
- Word Generation: Run
npm run generate:wordsto create 12 grade-level JSON files inpublic/data/words/ - Automatic Build: The
prebuildhook automatically generates word databases before building - Offline Support: Words are cached in IndexedDB for offline gameplay
- Storage: Uses the
idblibrary for efficient IndexedDB operations
For detailed implementation, see docs/WORD_DATABASE.md.
The application uses Cloudflare D1 (SQLite) as the primary database for feedback storage.
-
Create D1 database (if not already created):
npx wrangler d1 create buzzy-feedback
-
Update
wrangler.tomlwith your database ID:[[d1_databases]] binding = "DB" database_name = "buzzy-feedback" database_id = "your-database-id-here" migrations_dir = "migrations/d1"
-
Run migrations:
# Apply all pending migrations npx wrangler d1 migrations apply buzzy-feedback -
Verify schema:
npx wrangler d1 execute buzzy-feedback \ --command="PRAGMA table_info(feedback)"
For detailed deployment instructions, see docs/deployment/feedback-system.md.
This project uses different environment variables depending on where code runs (browser, Vite dev server, or Cloudflare Pages Function).
| Variable | Where it is read | Required? | Purpose |
|---|---|---|---|
FEEDBACK_WEBHOOK_URL |
Cloudflare Pages Function (functions/api/feedback.js) |
Required for production Slack delivery | Server-side Slack webhook used by /api/feedback. |
ALLOWED_ORIGINS |
Cloudflare Pages Function (functions/api/feedback.js) |
Recommended in production | Comma-separated origin allowlist for CORS enforcement. |
ADMIN_API_KEY |
Cloudflare Pages Function (functions/api/admin/feedback.js) |
Required for admin dashboard | Authentication key for admin dashboard API access. Generate with openssl rand -base64 32. This key must be entered by the user to access the admin dashboard. |
VITE_FEEDBACK_WEBHOOK_URL |
Vite dev server proxy (vite.config.js) |
Required for local Slack proxy testing | Dev-only target for proxying /api/feedback to Slack. |
VITE_SUPABASE_URL |
Browser app (src/lib/supabase.js) |
Optional fallback | Supabase project URL for feedback persistence fallback. |
VITE_SUPABASE_ANON_KEY |
Browser app (src/lib/supabase.js) |
Optional fallback | Supabase anon key used by client fallback insert. |
SUPABASE_SERVICE_ROLE_KEY |
Test runner only (src/lib/__tests__/supabase-rls.test.js) |
Optional (RLS integration tests) | Service key used to verify admin/service-role bypass behavior in integration tests. Never expose in browser env vars. |
VITE_API_BASE_URL |
Browser app (src/api/feedback.js) |
Optional preferred route | If set, feedback is sent to external backend API first. |
VITE_FEEDBACK_API_PATH |
Browser app (src/api/feedback.js) |
Optional | Feedback endpoint path override (/feedback default). |
VITE_SLACK_PROXY_AVAILABLE |
Browser app (src/api/feedback.js) |
Optional (production) | Set to true to enable /api/feedback fallback in production builds. |
Create a .env file in the root based on .env.example:
# Dev-only: used by Vite proxy for POST /api/feedback
VITE_FEEDBACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
# Optional fallback storage
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key
# Optional external backend (preferred route when present)
# VITE_API_BASE_URL=https://api.example.com
# VITE_FEEDBACK_API_PATH=/feedbackImportant: restart npm run dev after changing any .env values.
npm run devThe application will be available at http://localhost:5173
Access the admin feedback dashboard at http://localhost:5173/admin/feedback. You will be prompted to enter the ADMIN_API_KEY (configured in your environment).
Features:
- View all feedback submissions
- Filter by type (bug, suggestion, general), status, and date range
- Update feedback status (new, in_progress, resolved, wont_fix)
- Add internal notes and resolution notes
- Search across username, email, and message content
For detailed admin usage, see docs/admin-feedback-guide.md.
For type checking standards and JSDoc conventions, see docs/TYPE_CHECKING.md.
Use hover styles only on controls that perform an action when clicked or tapped.
- Interactive badges (filters, hint replay, status chips that open menus) should use pointer cursor + hover/focus states.
- Informational badges (static labels, read-only metadata) should not include hover affordances.
- Hint badges are intentionally interactive in the game: clicking a hint repeats it with text-to-speech.
- Keep badge hover contrast high enough for readability (avoid low-opacity text/background combinations).
npm run build
npm run previewThis application is optimized for deployment on Cloudflare Pages.
-
Connect Your Repository
- Go to Cloudflare Pages dashboard
- Click "Create a project"
- Connect your GitHub repository
-
Build Configuration
- Build command:
npm run build - Build output directory:
dist - Root directory:
/
- Build command:
-
D1 Database Binding
Ensure your D1 database is bound to the Pages project:
- In Cloudflare dashboard: Settings → Functions → D1 database bindings
- Add binding:
DB→buzzy-feedback
-
Environment Variables
Set these in Cloudflare Pages dashboard (Settings → Environment variables):
Pages Function (server-side, production):
FEEDBACK_WEBHOOK_URL=https://hooks.slack.com/services/... ALLOWED_ORIGINS=https://buzzygame.app,https://www.buzzygame.app ADMIN_API_KEY=<generate with: openssl rand -base64 32>Client-side build variables:
VITE_SLACK_PROXY_AVAILABLE=true VITE_SUPABASE_URL=https://your-project.supabase.co VITE_SUPABASE_ANON_KEY=your-anon-key # Optional external API route # VITE_API_BASE_URL=https://api.example.com # VITE_FEEDBACK_API_PATH=/feedback -
Deploy
- Push to your main branch
- Cloudflare Pages will automatically build and deploy
The feedback system uses a multi-tier approach:
-
Primary (Production): Cloudflare D1 database
- Feedback stored in D1 SQLite database
- Accessed via
/api/feedbackendpoint - Admin dashboard queries via
/api/admin/feedbackwithAuthorization: Bearer <ADMIN_API_KEY>header
-
Slack Integration: Cloudflare Pages Function at
/api/feedback- Uses server-side
FEEDBACK_WEBHOOK_URL - Sends async notifications to Slack (failure doesn't affect D1 storage)
- Never exposes Slack webhook to the browser
- Applies origin checks using
ALLOWED_ORIGINSwhen configured
- Uses server-side
-
Development: Vite proxy at
/api/feedback- Uses
VITE_FEEDBACK_WEBHOOK_URLduringnpm run dev - Proxy config lives in
vite.config.js
- Uses
-
Fallback: Supabase database
- Client-side fallback only: Used when preferred routes fail or are unavailable
- Requires
VITE_SUPABASE_URLandVITE_SUPABASE_ANON_KEY - Not triggered by D1/Slack failures - operates independently in the client
OPTIONSandPOSTare supported for/api/feedback.- If
ALLOWED_ORIGINSis set, only exact origins in that comma-separated list are allowed. - If
ALLOWED_ORIGINSis not set, origin checks are permissive. - Responses include:
Access-Control-Allow-Methods: POST, OPTIONSAccess-Control-Allow-Headers: Content-Type
Example restrictive configuration:
ALLOWED_ORIGINS=https://buzzygame.app,https://www.buzzygame.app- Feedback payload is validated with Zod in
functions/api/feedback.js:text: required, max 1000 charsuser: optional with defaultAnonymous, max 50 charstype: one ofbug,suggestion,general
- Inputs are sanitized before forwarding to Slack (HTML tag stripping + Slack markdown escaping).
- Admin API (
/api/admin/feedback) requires anAuthorizationheader with a Bearer token matchingADMIN_API_KEY(e.g.,Authorization: Bearer <key>). - Secure Authentication: The admin dashboard requires the user to enter the
ADMIN_API_KEYmanually. The key is verified by the backend and stored only in the browser'ssessionStorage. It is never embedded in the client-side JavaScript bundle. - CORS restricted to allowed origins only.
- All admin actions are authenticated.
- Client fallback writes to
feedbacktable throughVITE_SUPABASE_URL+VITE_SUPABASE_ANON_KEY. - RLS baseline and policy SQL is version-controlled in
supabase/sql/feedback_rls.sql. - Full database/RLS documentation lives in
docs/database.md(table inventory, policy intent, verification queries). - Optional integration test exists at
src/lib/__tests__/supabase-rls.test.jsand can be enabled withRUN_SUPABASE_RLS_TESTS=true.
Run the targeted RLS integration test:
RUN_SUPABASE_RLS_TESTS=true \
VITE_SUPABASE_URL=https://YOUR_PROJECT_REF.supabase.co \
VITE_SUPABASE_ANON_KEY=YOUR_ANON_KEY \
SUPABASE_SERVICE_ROLE_KEY=YOUR_SERVICE_ROLE_KEY \
npx vitest run src/lib/__tests__/supabase-rls.test.jsExpected behavior:
- anon
INSERTtofeedbacksucceeds - anon
SELECT/UPDATEtofeedbackis blocked - service-role client can read rows for admin workflows
After configuring environment variables:
- Run the app:
npm run dev
- Submit feedback from the UI and verify one of the delivery paths succeeds.
- Verify dev proxy is configured (if using Slack locally):
echo "$VITE_FEEDBACK_WEBHOOK_URL"
- Verify production Function variables in Cloudflare dashboard:
FEEDBACK_WEBHOOK_URLis setALLOWED_ORIGINSmatches deployed domainsADMIN_API_KEYis set
- Verify D1 database binding:
npx wrangler d1 execute buzzy-feedback --command="SELECT COUNT(*) FROM feedback" - Access admin dashboard:
- Navigate to
/admin/feedback - Enter the
ADMIN_API_KEY - Verify feedback loads
- Navigate to
The application can be deployed to any static hosting service that supports:
- Node.js build process
- Environment variables
- Optional: Serverless functions for the feedback proxy
For platforms without serverless functions, you'll need to:
- Deploy a separate backend to handle
/api/feedbackendpoint - Set
VITE_API_BASE_URLto point to your backend - Ensure your backend proxies requests to the Slack webhook
# Unit and integration tests
npm run test
# E2E tests (Playwright)
npm run test:e2e
# E2E tests with UI
npm run test:e2e:ui
# Security penetration tests
npm run test:security
# Test coverage
npm run test:coverage- Unit Tests: Component logic, hooks, utilities
- Integration Tests: API endpoints, database operations, feedback system
- E2E Tests: Full user workflows with Playwright (desktop + mobile configs)
- Security Tests: Input validation, XSS prevention, CORS enforcement
For detailed testing documentation, see docs/TEST_FIXES.md.
# Enable Supabase RLS integration tests
RUN_SUPABASE_RLS_TESTS=true
# Admin dashboard tests (entered manually in the UI or provided via state)
ADMIN_API_KEY=your-test-key
# Slack delivery tests (optional)
SLACK_BOT_TOKEN=xoxb-...
SLACK_FEEDBACK_CHANNEL_ID=C...buzzy-game/
├── functions/ # Cloudflare Pages Functions (serverless)
│ └── api/
│ ├── feedback.js # Public feedback endpoint (stores to D1 + Slack)
│ └── admin/
│ └── feedback.js # Admin API for feedback management
├── migrations/ # Database migrations
│ └── d1/ # D1 SQLite migrations
│ ├── 001_create_feedback_table.sql
│ └── 002_add_admin_notes.sql
├── scripts/ # Build and utility scripts
│ ├── generate-word-databases.js # Generate grade-level word files
│ ├── audit-word-coverage.js # Audit word database coverage
│ ├── start-entrypoint.cjs # Dev server entrypoint
│ └── run-*.mjs # Test and lint runners
├── src/
│ ├── api/ # API client code
│ ├── components/ # React components
│ ├── contexts/ # React contexts
│ ├── data/ # Static data files
│ ├── game-engine/ # Game logic
│ ├── hooks/ # Custom React hooks
│ │ └── useOnlineStatus.ts # Online/offline detection
│ ├── lib/ # Third-party integrations
│ │ ├── db.js # IndexedDB layer (word caching + sync queue)
│ │ ├── sync.js # Background sync logic with retry
│ │ └── wordLoader.js # Offline-first word loading
│ ├── pages/ # Page components
│ │ └── AdminFeedback.jsx # Admin dashboard
│ └── utils/ # Utility functions
├── public/
│ ├── service-worker.js # PWA service worker with sync event handler
│ └── data/
│ └── words/ # Generated grade-level word databases (1-12)
├── tests/ # E2E tests (Playwright)
├── docs/ # Documentation
│ ├── deployment/ # Deployment guides
│ ├── dev/ # Developer guides
│ ├── PHASE4_IMPLEMENTATION.md # PWA offline/sync architecture
│ ├── typescript-migration-strategy.md # TypeScript migration plan
│ ├── typescript-guide.md # TypeScript training materials
│ ├── typescript-style-guide.md # TypeScript coding standards
│ ├── typescript-migration-checklist.md # File migration process
│ ├── WORD_DATABASE.md # Word database system docs
│ └── admin-feedback-guide.md # Admin dashboard usage
└── dist/ # Production build output
See CONTRIBUTING.md for local development requirements and CI expectations.
See CLAUDE.md for AI assistant guidelines.
MIT