A cozy jigsaw puzzle game built with React. Pick a puzzle from the catalog or packs using the staged modal flows—then snap pieces together with smooth drag-and-drop and satisfying feedback.
Play: phuzzle.vercel.app
If the GIF doesn’t load, check path and casing (GitHub is case-sensitive).
- Play: Drag, drop, rotate; board and neighbor snap; group merging. Grids from 3×3 to 12×12. Puzzle selection starts from a streamlined mobile home with one clear primary CTA, then staged modals: Quick Play (catalog: category → puzzle → difficulty → start) and Puzzle Packs (pack → puzzle → difficulty → start), with clickable breadcrumbs. The in-game menu is simplified to Resume, New Puzzle, Settings, Leaderboard, and Help; detailed controls live under Settings groups. Piece tray with filters (All, Edges, Color); unified HUD pills (timer, pause, moves, pieces); compact gap between board and tray. Zoom and pan. Undo/redo lives in Settings → Gameplay → Move behavior. Dragged pieces show clearer outlines and shadows, and snap feedback uses target highlights plus “Fits here” / “Almost” labels with non-color icons. Continue and start over. Placed pieces meet seamlessly (no visible gaps); unplaced pieces keep a clear jigsaw look.
- Daily: Daily puzzle, streaks, countdown, streak shield (freeze), a compact home momentum strip, and a 7-day daily-history row with streak nudges. Daily Share — after finishing the daily, share a Wordle-style result (daily #, difficulty, time, moves, emoji grid, play link) via copy or native share. Comments and reactions after completion.
- Modes: Zen, Mystery, Precision, Dynamic Difficulty, Adaptive Personality. Magnetic Snap and Snap Glow toggles. Reference preview, snap combo, piece shapes, percentile badges, themes.
- Social: Stats, profile, leaderboards (Today, Week, All-time, Efficiency). Share result, share card, Challenge Friend links, Daily Share (Wordle-style for daily only), replay viewer. Co-op play with shareable links. Home also surfaces a resume card when you have saved progress and refreshes automatically when daily or save data changes.
- Quality: Bug report with optional screenshots. Mobile layouts: touch drag on the board (pieces follow your finger; page scroll is disabled over the board so drag works), tappable tray and carousel buttons (48px hit areas). PWA install.
In-app What's New (changelog) uses a single bullet per item; source: src/app/data/content/changelog.ts.
Details: docs/CHANGES.md.
All project docs live in docs/. Full index: docs/README.md.
| Doc | Description |
|---|---|
| docs/APP_MAP.md | Where users find features and where those features live in code |
| docs/CHANGES.md | Feature list and recent changes |
| docs/FEATURES_IMPLEMENTED.md | Implemented features and where they live in code |
| docs/FUTURE.md | Ideas and possible future features |
| docs/SHARING.md | Completion share, Daily Share (Wordle-style), co-op share |
| docs/SETTINGS_MENU.md | Play menu settings, submenus, and conditional entries |
| docs/STREAK-FREEZE.md | Streak freeze (streak shield): earn it, when it applies |
| docs/BUG_REPORT.md | In-app bug report: where it is, what it does |
| docs/SUPABASE_SETUP.md | Supabase: leaderboards, stats, co-op, env vars, migrations |
| docs/LIGHTHOUSE.md | Lighthouse CI, reports, "GitHub token not set" warning |
| docs/GAMES_SURFACE.md | Games surface: launch URLs, manifest, acceptance & QA checklist |
| docs/MOBILE_QA.md | Mobile release checklist and regression commands |
| docs/STATS_UI_QA.md | Stats modal QA: Profile, Board, Badges |
| docs/SESSION_SUMMARY.md | Session notes (layout, piece drawer, leaderboards, etc.) |
- Import puzzle from URL
- Stronger offline-first for puzzle images
- Color vision: The UI uses blue as the main brand color (buttons, links, selection), which works well for most color vision types. A Color blind friendly option lives at Play -> Settings -> Appearance and switches progress, “done,” and success states to blue so red-green is not the only cue; it applies to all screens and all themes. We avoid color-only cues: snap and fit feedback uses outlines, icons, and “Fits here” / “Almost” text; low-time warning shows a warning icon as well as red styling; co-op status shows text and icons (e.g. WifiOff, spinner) with color. Menus are keyboard reachable,
Escapebacks out or closes the active panel, focus returns to the menu button, and small screens use constrained panels instead of hover flyouts. Reduced motion is respected for CSS motion and snap/tray emphasis effects. Focus rings and sufficient contrast are used for interactive elements, including light theme menus and panels.
Frontend: React, TypeScript, HTML Canvas Build: Vite, vite-plugin-pwa Test: Vitest, Playwright Deploy: GitHub Actions, Vercel. Optional Supabase for leaderboards, stats, co-op, comments.
git clone https://github.com/NickTheDevOpsGuy/phuzzle.git
cd phuzzle
npm install
npm run doctor
npm run devUseful scripts: npm run doctor, npm run build, npm run preview, npm run test, npm run test:e2e:smoke, npm run test:e2e:layouts, npm run test:e2e, npm run lighthouse, npm run check:images (Vitest and Playwright use 4 workers; run npx playwright install once). The image audit is useful before shipping large social or puzzle assets.
Local quality workflow:
npm run doctorchecks Node version, local dependencies, Playwright availability, Supabase/Docker reachability, and whether port4173is already in use.npm run precheckmatches the pre-push gate locally.npm run test:e2e:smokeruns high-signal flows across Chrome, Firefox, Safari/WebKit, and Edge-compatible Chromium.npm run test:e2e:layoutsruns responsive iPhone, iPad, and Android tablet projects.npm run test:e2eruns the broader multi-browser matrix.
Image budget quick rule:
- Puzzle assets should usually stay under
500 kBeach after optimization. 1 MB+is a warning sign.2 MB+is too large for normal gameplay assets and should be compressed or converted before shipping.- Social/OG images should ideally stay under
250 kB, and500 kB+should be treated as too heavy.
We love help.
Before submitting a PR, run:
npm run lintnpm run typechecknpm run testnpm run build
DM us to join the Discord and get involved.
No gatekeeping. No ego. Just building something fun together.
Built by:
| Name | GitHub | |
|---|---|---|
| Nick Clark | nicholas-a-clark | @NickTheDevOpsGuy |
| Vinay Gajjar | vinaygajjar | @v-gajjar |
| Hannah Olbrich | hannaholbrich | @hannahro15 |
With help from the wider community ❤️ See all contributors here → CONTRIBUTORS.md
Different strengths, shared ownership, great teamwork.
MIT License. See LICENSE.md.
