{"id":47087986,"url":"https://github.com/trystan2k/padelbuddy-web","last_synced_at":"2026-04-19T09:04:33.171Z","repository":{"id":343889594,"uuid":"1176186983","full_name":"trystan2k/padelbuddy-web","owner":"trystan2k","description":"A mobile-first, client-only Padel score tracker optimized for courtside use with Bluetooth remote and touch controls.","archived":false,"fork":false,"pushed_at":"2026-04-14T15:46:03.000Z","size":13831,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-14T17:27:22.929Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trystan2k.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-08T18:26:53.000Z","updated_at":"2026-04-14T15:46:00.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/trystan2k/padelbuddy-web","commit_stats":null,"previous_names":["trystan2k/padelbuddy-web"],"tags_count":50,"template":false,"template_full_name":null,"purl":"pkg:github/trystan2k/padelbuddy-web","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trystan2k%2Fpadelbuddy-web","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trystan2k%2Fpadelbuddy-web/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trystan2k%2Fpadelbuddy-web/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trystan2k%2Fpadelbuddy-web/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trystan2k","download_url":"https://codeload.github.com/trystan2k/padelbuddy-web/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trystan2k%2Fpadelbuddy-web/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32000744,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T20:23:30.271Z","status":"online","status_checked_at":"2026-04-19T02:00:07.110Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-03-12T08:49:57.182Z","updated_at":"2026-04-19T09:04:33.139Z","avatar_url":"https://github.com/trystan2k.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Padel Buddy Web\n\nA mobile-first, client-only Padel score tracker optimized for courtside use. Supports Bluetooth remote controllers, touch scoring, match persistence, and multi-language (English, Spanish, Portuguese).\n\nThe web app is also packaged as native **Capacitor** apps for **Android** and **iOS**, embedding the production web bundle from `dist/client`.\n\n## Tech Stack\n\n- **Framework**: TanStack Start (SSR-capable but deployed as static SPA)\n- **UI**: React 19 + Base UI + CSS Modules\n- **Routing**: TanStack Router (code-split, type-safe)\n- **Build**: Vite 8\n- **Testing**: Vitest (unit) + Playwright (E2E)\n- **i18n**: react-i18next\n- **Persistence**: IndexedDB\n- **Deployment**: Cloudflare Pages\n- **Native Wrappers**: Capacitor Android + iOS\n\n## Requirements\n\n- Node `24.14.1`\n- pnpm `10.33.0`\n\nUse `mise` for automatic Node version switching — `package.json` declares the required version.\n\n## Local Development\n\n```bash\npnpm install\npnpm dev\n```\n\nThe app runs at `http://localhost:3000`.\n\n## Scripts\n\n| Command                 | Description                                                       |\n| ----------------------- | ----------------------------------------------------------------- |\n| `pnpm dev`              | Start dev server with hot reload                                  |\n| `pnpm build`            | Build for production (outputs to `dist/client`)                   |\n| `pnpm cap:sync`         | Sync the built web app into both Capacitor native projects        |\n| `pnpm cap:sync:android` | Sync the built web app into the Android project                   |\n| `pnpm cap:sync:ios`     | Sync the built web app into the iOS project                       |\n| `pnpm cap:open:android` | Open the Android project in Android Studio                        |\n| `pnpm cap:open:ios`     | Open the iOS project in Xcode                                     |\n| `pnpm test`             | Run unit tests with coverage                                      |\n| `pnpm test:e2e`         | Run E2E tests (requires Chromium)                                 |\n| `pnpm test:e2e:ui`      | Open Playwright UI for debugging                                  |\n| `pnpm lint`             | Lint with Oxlint + Stylelint                                      |\n| `pnpm lint:fix`         | Auto-fix lint issues                                              |\n| `pnpm format`           | Format with Oxfmt                                                 |\n| `pnpm typecheck`        | TypeScript type check                                             |\n| `pnpm complete-check`   | Full verification: typecheck → lint → format → test → e2e → build |\n\n## App Structure\n\n```\nsrc/\n├── components/     # React components (screens, UI primitives)\n├── core/           # Match engine, scoring logic, game state\n├── lib/            # Utilities (i18n, persistence, speech, input)\n├── routes/         # TanStack Router route definitions\n└── styles.css      # Global styles + design tokens\n\nandroid/            # Capacitor Android wrapper project\nios/                # Capacitor iOS wrapper project\nscripts/            # Utility scripts, including native asset generation\n```\n\n## Capacitor Native Apps\n\nThe native wrappers load the production web build from `dist/client`.\n\nTypical native update flow:\n\n```bash\npnpm build\npnpm cap:sync\n```\n\nPlatform-specific flow:\n\n```bash\npnpm build\npnpm cap:sync:android\npnpm cap:open:android\n```\n\n```bash\npnpm build\npnpm cap:sync:ios\npnpm cap:open:ios\n```\n\n### Native Branding\n\n- iOS launch and icon assets live under `ios/App/App/Assets.xcassets/`\n- Android launcher and splash assets live under `android/app/src/main/res/`\n- Native branded assets can be regenerated with:\n\n```bash\nswift scripts/generate_capacitor_brand_assets.swift\n```\n\n### Android Launch Flow\n\nAndroid uses a dedicated native launcher activity before Capacitor opens the WebView:\n\n- `LaunchActivity` shows a branded native launch layout with the app icon and `Padel Buddy` text\n- `MainActivity` remains the Capacitor host activity\n\nThis avoids Android 12+ splash API limitations, where the system splash screen cannot reliably show a centered freeform `icon + text` composition.\n\n### Routes\n\n- `/` — Home/Setup screen (new match configuration)\n- `/match/:id` — Active match scoring\n- `/match/finish/:id` — Match end summary and stats\n\n### Key Features\n\n- **Score tracking**: Real-time padel scoring with game/set/match logic\n- **Side-switch prompts**: Alerts at 1-1 in deciding set\n- **Bluetooth remote**: Web Bluetooth API for physical scoring buttons\n- **Match persistence**: IndexedDB stores in-progress matches\n- **i18n**: English, Spanish, Portuguese\n- **PWA**: Installable, offline-capable\n- **Share**: Export match stats as image\n\n## Testing\n\nInstall Playwright browsers once:\n\n```bash\npnpm exec playwright install chromium\n```\n\nRun tests:\n\n```bash\npnpm test          # Unit tests\npnpm test:e2e     # E2E tests\npnpm test:e2e:headed  # Watch tests run in browser\n```\n\n## Production Deployment\n\nProduction deploys to Cloudflare Pages on GitHub release. The `dist/client` folder is uploaded as a static artifact.\n\n- **Production URL**: `https://padelbuddyweb.pages.dev`\n- **Preview releases**: Deployed automatically for `release-please--branches--main` branch\n\n## CI/CD\n\nGitHub Actions runs on every PR and push to `main`:\n\n1. `typecheck` → `lint` → `format:check` → `test` → `build`\n\nRelease Please manages versioning and changelog. Merging a release PR triggers the production deployment workflow.\n\n## Design\n\nVisual design uses design tokens defined in `design-tokens/` and compiled to `src/styles.css` via Style Dictionary. See `docs/design/padelbuddyweb.pen` for the Pencil source file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrystan2k%2Fpadelbuddy-web","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrystan2k%2Fpadelbuddy-web","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrystan2k%2Fpadelbuddy-web/lists"}