diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 0000000..25943ca --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,40 @@ +--- +name: Bug report +about: Something is broken or behaving unexpectedly +title: "As a [user/developer] I want to [fix] so I can [benefit]" +labels: "bug" +assignees: "" +--- + +## Summary + +One paragraph describing what is broken and what the expected behaviour is. + +## Priority + +High / Medium / Low + +## Steps to reproduce + +1. +2. +3. + +## Expected behaviour + + + +## Actual behaviour + + + +## Acceptance criteria + +- [ ] +- [ ] + +## Out of scope + + + +- diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md new file mode 100644 index 0000000..f4f06be --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -0,0 +1,42 @@ +--- +name: Feature / improvement +about: Suggest a new feature or improvement +title: "As a [user/developer] I want to [action] so I can [benefit]" +labels: "" +assignees: "" +--- + +## Summary + +One paragraph describing the problem and the goal. + +## Priority + +High / Medium / Low + +## UI spec (Carbon g100) + + + +- + +## Data model + + + +```sql + +``` + +## Acceptance criteria + +- [ ] +- [ ] + +## Out of scope + + + +- diff --git a/CHANGELOG.md b/CHANGELOG.md index 1947b64..bba7f4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to Workout Lens are documented here. ## [Unreleased] +### Added +- **Open source housekeeping** — repository prepared for public release: added MIT `LICENSE`, `CONTRIBUTING.md`, and GitHub issue templates (feature + bug). `README.md` updated with contributing and license sections; instance-specific infrastructure IDs removed. `CLAUDE.md` stripped of internal deployment identifiers. `app/package.json` updated with `author`, `license`, and `repository` fields. + ### Fixed - **Gym class name deduplication** — `sportySync.js` now strips quoted annotations (e.g. `"SVART TRØYE"`) from class names before storing them, preventing duplicate filter chips in Report when sporty.no temporarily appends labels to existing class names. A one-time SQL migration cleaned all existing rows. Handles both straight (`"`) and curly (`"`) double quotes generically. diff --git a/CLAUDE.md b/CLAUDE.md index 63f5409..95f30a5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -298,8 +298,7 @@ Rules of thumb when adding tests: Coverage (`npm run test:ci`) is configured in `vite.config.js` to scope to `src/lib/**` and `api/claudeUtils.js`. Current line coverage: `utils.js` ~80%, `prompts.js` 100%, reducer & `calcMuscles` ~100% within tested files; `db.js` and `bodymap.jsx` SVG render code are intentionally untested. ## Azure deploy notes -- **Resource group:** `rg-muskelkart` (West Europe) — **Azure resource name:** `muskelkart` -- **Supabase Auth redirect URLs** — three entries in Authentication → URL Configuration → Additional redirect URLs: `http://localhost:4280` (local dev), `https://workout.umulig.org` + `https://workout.umulig.org/**` (prod), and `https://white-island-090dfd003-*.westeurope.7.azurestaticapps.net` (PR preview wildcard — safe because the `white-island-090dfd003` prefix is unique to this SWA instance). The app uses `emailRedirectTo: window.location.origin` so no per-PR config is needed (#135) +- **Supabase Auth redirect URLs** — add the following in Supabase → Authentication → URL Configuration → Additional redirect URLs: `http://localhost:4280` (local dev), your production URL + `/**` (prod), and `-*.westeurope.7.azurestaticapps.net` (PR preview wildcard). The app uses `emailRedirectTo: window.location.origin` so no per-PR config is needed (#135) - For secrets/settings/live URL, see README → Deployment section ## Known pitfalls (previously hit, fixed, must not regress) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..bfe4587 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,82 @@ +# Contributing + +Thanks for your interest in Workout Lens. This document covers everything you need to run the project locally and submit changes. + +## Prerequisites + +| Tool | Version | Notes | +|---|---|---| +| Node.js | 22.x LTS | Use [fnm](https://github.com/Schniz/fnm) or [nvm](https://github.com/nvm-sh/nvm) | +| Azure Static Web Apps CLI | latest | `npm install -g @azure/static-web-apps-cli` | + +## One-time setup + +```bash +# Install frontend dependencies +cd app && npm install + +# Install API dependencies +cd api && npm install + +# Copy and fill in the env files +cp app/.env.local.example app/.env.local # VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY +cp app/api/local.settings.json.example app/api/local.settings.json # ANTHROPIC_API_KEY, SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, VITE_SUPABASE_ANON_KEY, SUPABASE_ANON_KEY +``` + +You will need: +- A [Supabase](https://supabase.com) project with the schema from `supabase/migrations/` +- An [Anthropic](https://console.anthropic.com) API key + +## Running locally + +Start both the Vite dev server and the Azure SWA emulator: + +```bash +# Terminal 1 — Vite +cd app && npm run dev + +# Terminal 2 — SWA emulator (proxies /api/* to local Azure Functions) +swa start http://localhost:5173 --api-location app/api +``` + +Open **http://localhost:4280** — not port 5173. The API routes (`/api/claude`, `/api/sporty-sync`) only work through the SWA proxy. + +> On Windows, a `dev.ps1` script can automate this. See the local development section in CLAUDE.md. + +## Running tests + +```bash +cd app +npm test # one-shot +npm run test:ci # one-shot with coverage +npm run test:watch # watch mode +``` + +The test suite is pure-logic (reducers, date helpers, validators, prompt builders, API guards) — no DOM, no live Supabase. It runs in under 2 seconds. + +## Branch and commit conventions + +| Branch type | Pattern | Example | +|---|---|---| +| Feature | `feat/` | `feat/weekly-planner` | +| Bug fix | `fix/` | `fix/history-date-parse` | +| Docs / chore | `docs/` or `chore/` | `docs/contributing` | + +Commit messages follow the pattern: `type: description (#issue-number)` + +Examples: +``` +feat: add weekly training planner (#59) +fix: resolve muscle hover tooltip collision (#18) +docs: update CLAUDE.md for recommendation cache (#150) +``` + +## Submitting a pull request + +1. Fork the repo and create a branch from `master` +2. Make your changes — keep scope tight and linked to one issue +3. Run `npm test` and confirm all tests pass +4. Open a PR against `master` with the issue number in the title +5. Fill in the PR template (Summary + test plan) + +Issues use a structured format — see the issue templates in `.github/ISSUE_TEMPLATE/` or the issue format section in README.md. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0176b19 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Christopher Rotnes + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index bb91f90..49e083c 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Add the following to Supabase **Authentication → URL Configuration → Additio | URL | Purpose | |---|---| | `http://localhost:4280` | Local dev (SWA emulator) | -| `https://white-island-090dfd003-*.westeurope.7.azurestaticapps.net` | Azure SWA PR previews (wildcard covers all PR numbers) | +| `https://-*.westeurope.7.azurestaticapps.net` | Azure SWA PR previews (wildcard covers all PR numbers) | The app uses `emailRedirectTo: window.location.origin` so magic-link emails automatically point back to whichever environment the login was initiated from. @@ -164,7 +164,7 @@ Live URL: `https://workout.umulig.org` |---|---| | `VITE_SUPABASE_URL` | Injected into frontend bundle via `env:` block on the build step | | `VITE_SUPABASE_ANON_KEY` | Injected into frontend bundle via `env:` block on the build step | -| `AZURE_STATIC_WEB_APPS_API_TOKEN_WHITE_ISLAND_090DFD003` | Azure deploy token | +| `AZURE_STATIC_WEB_APPS_API_TOKEN_` | Azure deploy token (the exact name is generated by Azure when you create the SWA resource; find it in the deployment workflow Azure downloads to your repo) | ### Required app settings (Azure SWA) @@ -178,6 +178,16 @@ Live URL: `https://workout.umulig.org` > **Note:** The frontend is built in the GitHub Actions runner (not by Oryx inside Azure SWA's Docker container). Oryx strips `VITE_*` env vars before spawning Vite, so they would never reach the bundle if built there. The workflow pre-builds `app/dist/` and the Azure SWA action uploads it directly via `app_location: "app/dist"`. Do not revert this. +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for setup instructions, branch conventions, and how to submit a pull request. + ## Backlog Open work is tracked in [GitHub Issues](https://github.com/ChristopherRotnes/BodyMapTraining/issues). + +## License + +MIT — see [LICENSE](LICENSE). + +IBM Plex fonts are licensed under the SIL Open Font License 1.1 — see [`app/public/fonts/LICENSE.txt`](app/public/fonts/LICENSE.txt). diff --git a/app/package.json b/app/package.json index 9f89b67..8f0bc43 100644 --- a/app/package.json +++ b/app/package.json @@ -1,7 +1,13 @@ { - "name": "app", + "name": "workout-lens", "private": true, "version": "1.1.0-rc.1", + "author": "Christopher Rotnes", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/ChristopherRotnes/BodyMapTraining" + }, "type": "module", "scripts": { "dev": "vite",