- Project Description
- Tech Stack
- Project Structure
- Getting Started Locally
- Available Scripts
- Project Scope
- Project Status
- License
10xGains is a streamlined platform designed to lower the entry barrier for powerlifting and weightlifting. The application enables users to create, customize, and track personalized training plans with AI-driven suggestions, ensuring safe and effective workout routines. Key features include secure user registration/login, flexible training plan creation, active workout session tracking, comprehensive workout history, and exercise progress charts.
- Frontend: Angular 22, Angular Material Design 3, Tailwind CSS 4, Chart.js 4 (via ng2-charts)
- Backend: Hono on Azure Functions (Node.js 24) for the API; Supabase for PostgreSQL and authentication
- AI Integration: OpenRouter API for AI-driven training plan suggestions
- Test Suite: Vitest (unit), Cypress (e2e)
- CI/CD and Hosting: GitHub Actions, Azure Static Web Apps (frontend), Azure Functions (API)
This is a pnpm workspace monorepo:
apps/web- The Angular frontend application (@txg/web).apps/api- The backend API: a Hono app hosted on Azure Functions (@txg/api). See apps/api/README.md for architecture and endpoint documentation.packages/shared- Shared code (@txg/shared) consumed by both apps: API DTOs, command models, and generated database types, plus the value unions the database constrains columns to.supabase- Database migrations, tests, and local stack configuration.cypress- System-level end-to-end tests run against a deployed (or locally running) application.
There are two ways to get a working environment. The dev container builds the whole stack — Node, the Supabase services, Azurite, and Claude Code — inside one container, and is the recommended path: it is the same environment for everyone, and an agent running in it cannot reach your machine. The host setup installs the same toolchain directly on your machine.
- A Docker engine. On Windows it must be reachable from WSL2: Docker Desktop with WSL integration (what the steps below assume and what this is tested against) or a Docker Engine installed directly in the WSL2 distro, which skips the integration step. On macOS/Linux, Docker Desktop or the native engine.
- VS Code with the Dev Containers and WSL extensions. Both are in this repo's recommended extensions, so VS Code offers to install them when you open the folder. (You can drive the container with the Dev Containers CLI instead, but VS Code is the least-effort path.)
On Windows there are two extra steps, because the working copy must live on the Linux (ext4) filesystem — never under C:\. A clone under C:\ (or /mnt/c) reaches the container through a slow translation layer that the container's nested Docker daemon cannot create directories on, so Supabase Studio fails to start. Keep the clone in your WSL2 home instead:
- A WSL2 distro. If you don't have one, run
wsl --install -d Ubuntuin an elevated PowerShell and set a username when it first launches. (Docker Desktop's owndocker-desktopdistro does not count.) - Docker reachable from the distro. With Docker Desktop, enable its WSL integration (Settings → Resources → WSL Integration → enable your distro → Apply & Restart) and verify it — a disabled integration is the most common blocker, and its symptom is opaque (
dial unix /var/run/docker.sock: no such file). A Docker Engine installed inside the distro is already reachable and needs nothing here.
The windows-dev-container skill documents this setup and its failure modes in full.
- Clone into the WSL2 filesystem (Windows) or anywhere (macOS/Linux). From a WSL/Ubuntu terminal:
git clone https://github.com/dmngrsk/10xGains.git ~/10xGains - Open it in VS Code:
code ~/10xGains - Reopen in Container when prompted (or Command Palette → Dev Containers: Reopen in Container). The first build is slow — it installs dependencies and pulls the Supabase images — then starts Supabase and Azurite on the container's own Docker daemon and generates the local config files (see Local configuration). Later starts reuse the stack and are fast.
- Run the app with
pnpm devand openhttp://localhost:4200. Sign in with the seeded dev account —dev@10xgains.com/10xGains!— which comes preloaded with sample training data (seepnpm seed).
If you use Claude Code, sign in once with claude in the container terminal. Because the container is the blast radius, Claude Code can be run inside it without permission prompts:
claude --dangerously-skip-permissionsThis is safe for the host — the agent has no route to your machine's files or Docker daemon — but it is not a license to run untrusted code: anything reachable from inside the container, including the working copy and the credentials in ~/.claude, is still fair game. See Anthropic's dev container guidance.
Each container runs a full Supabase stack, so two containers cannot both publish the default ports. To run a second worktree in parallel, set the TXG_* host ports before opening it — the container picks them up, and the generated config points at them:
| Variable | Default | Worktree #2 | Service |
|---|---|---|---|
TXG_WEB_PORT |
4200 |
4300 |
Angular dev server |
TXG_API_PORT |
7071 |
7171 |
Azure Functions host |
TXG_SUPABASE_PORT |
54321 |
54421 |
Supabase API |
TXG_STUDIO_PORT |
54323 |
54423 |
Supabase Studio |
TXG_MAIL_PORT |
54324 |
54424 |
Mailpit |
- Node.js: Version specified in
.nvmrc(e.g.,24.18.0) - pnpm: This project uses
pnpmfor package management (managed via Corepack) - Docker: Required to run Supabase and Azurite locally
- Supabase CLI: Follow the official installation guide
- Azurite: Local Azure Storage emulator required by the API's Functions host
-
Clone the repository:
git clone https://github.com/dmngrsk/10xGains.git
-
Navigate to the project directory:
cd 10xGains -
Install dependencies:
Install the necessary npm packages for all workspace packages.
pnpm install
-
Start the local Supabase services:
This command uses Docker to start the local Supabase stack (database, auth, storage, etc.). On first run, it also creates the database and applies all schema changes from the
supabase/migrationsfolder.pnpm exec supabase startOnce it's running, the CLI will output your local Supabase credentials, including the API URL and the publishable key. You will need these in step 6.
-
Start the Azurite storage emulator:
The API's local Functions host needs a storage backend (
AzureWebJobsStorage). Start it via the rootdocker-compose.yml:docker compose up -d
-
Write the local configuration:
Create the three files listed under Local configuration from their committed templates, filling in the API URL, publishable key and secret key that step 4 printed:
cp .env.example .env cp apps/api/local.settings.json.example apps/api/local.settings.json cp apps/web/src/env.template.js apps/web/src/env.js
-
Seed a local dev account (optional):
Create
dev@10xgains.com/10xGains!with sample training data, so the app has a realistic history to explore:pnpm seed
This reads
SUPABASE_SECRET_KEYfrom.env(printed bysupabase start), and is idempotent — safe to re-run, e.g. aftersupabase db reset.Optional — Google sign-in: the local stack enables the Google OAuth provider, whose credentials are resolved from
SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_ID/SUPABASE_AUTH_EXTERNAL_GOOGLE_SECRETatsupabase starttime (see.env.example). Without them everything else works; the Google button just fails at Google's door. To make it work, create an OAuth 2.0 Web client in the Google Cloud Console withhttp://127.0.0.1:54321/auth/v1/callbackas an authorized redirect URI, export both variables (the dev container exports them from.envautomatically), and restart the stack. -
Start the apps:
Run both the Angular dev server and the API host together with a single command:
pnpm dev
This runs the
devscript of every workspace package in parallel (equivalent topnpm --filter @txg/web start:developmentandpnpm --filter @txg/api startrun side by side), prefixing each line of output with its package name. To run them separately instead (e.g. in two terminals), use those individual commands. -
Navigate to the web app:
Open your browser, navigate to
http://localhost:4200, and sign in withdev@10xgains.com/10xGains!(if you ran the seed step).
Three files hold local settings, and all three are gitignored:
.env— Supabase keys and the canary user credentials, read by Cypress.apps/api/local.settings.json— settings for the local Azure Functions host.apps/web/src/env.js— the API and Supabase URLs the web app reads at runtime, in the browser. Gitignored; deployed builds get the same file with values substituted by CD.
In the dev container, .devcontainer/post-start.sh regenerates all three on every start from the keys the running Supabase stack reports, so they never drift. On a host setup you maintain them by hand, and must refresh the keys yourself after recreating the stack (supabase stop --no-backup followed by supabase start), because a fresh stack mints fresh ones.
Below are the most important scripts defined in package.json.
pnpm dev- Runs the Angular dev server and the API host together, in parallel, each with output prefixed by package name. This is the recommended way to start local development once Getting Started Locally is complete.pnpm seed- Seeds a local dev account (dev@10xgains.com/10xGains!) with sample training data, so the app has a realistic history to explore. Idempotent and local-only (it uses the local service-role key). The dev container runs it automatically on start; run it by hand after resetting the database (e.g.supabase db reset).pnpm --filter @txg/api start- Builds the API and starts the local Azure Functions host athttp://localhost:7071/. Requires Azurite to be running (see Getting Started Locally).pnpm --filter @txg/web start:development- Runs only the Angular application in development mode using thedevelopmentconfiguration. The server is hosted athttp://localhost:4200/and is accessible on your local network (especially to the e2e testing framework) thanks to--host 0.0.0.0.pnpm --filter @txg/web start:[staging|production]- Runs the app locally but with thestagingorproductionenvironment configurations. Useful for debugging environment-specific issues.
pnpm build- Builds the web application for production. The output is placed in theapps/web/distdirectory.pnpm build:[development|staging]- Builds the web application using thedevelopmentorstagingconfiguration.
pnpm lint- Runs each package's lint script: ESLint acrossapps/web,apps/api, and the Cypress test code, plus a TypeScript typecheck (spec files included) forapps/web,apps/api, andpackages/shared.pnpm lint:fix- Runs the same linters but attempts to automatically fix any detected issues.- Note: A pre-commit hook is configured with Husky and
lint-stagedto automatically format your code before every commit.
pnpm test- Runs the complete unit test suite once.pnpm test:watch- Runs bothapps/webandapps/apiunit tests in interactive watch mode, automatically re-running them when you save a file. Ideal for active development.pnpm --filter <@txg/web|@txg/api> test:watch- Runs a single package's unit tests in watch mode instead of both.pnpm test:coverage-Runs the unit tests and generates a code coverage report in the/coveragedirectory.
pnpm e2e- Opens the interactive Cypress Test Runner, allowing you to watch tests run in a browser and debug them visually.pnpm e2e:run- Runs the entire E2E test suite headlessly (in the terminal). This is the command used in CI/CD pipelines.pnpm e2e:smoke- Runs a specific subset of E2E tests tagged as@smoke. Useful for quick sanity checks during development or in a CI/CD pipeline.
These provision the deployed environments and are not needed for local development. See infra/README.md for the layout, the required credentials, and what is deliberately left unmanaged.
pnpm infra:apply <staging|production>- Provisions or converges an entire environment: the Azure resources, the Supabase project, Cloudflare DNS, the database migrations, and this environment's GitHub variables and secrets. Add--checkto run the preflight checks and stop, which reports what is missing without changing anything.pnpm infra:apply <staging|production> --bootstrap-only- Creates only the resource group, Terraform state backend and CI identity - the set CI cannot create for itself - and writes the GitHub environment. Use this when you want CD to build the rest.pnpm infra:destroy <staging|production>- Tears an environment down, Supabase project and all of its data included. Add--keep-bootstrapto leave the resource group, Terraform state backend and CI identity in place, so a rebuild does not need an Owner. Production carriesprevent_destroyon its Supabase project and Terraform refuses both modes there.
The current MVP scope includes:
- User Account System: Secure user registration and login.
- Training Plan Creation: Ability to create personalized training plans with both predefined and custom exercises, incorporating manual adjustments and automated weight progression.
- Active Workout Session Tracking: Real-time tracking of exercises with clickable set markers, detailed editing capabilities, and free-form session and plan notes.
- Workout History: Chronological record of past workout sessions, including access to per-session notes.
- Exercise Progress: Weight-over-time line chart with one line per exercise, defaulting to the active plan and the last 3 months, filterable by training plan (or across all of them) and date range.
- Body Measurement Tracking: Weight and circumference measurements over time on their own chart, with US Navy (tape) and Jackson-Pollock (caliper) body-fat estimates derived from them, and an optional home reminder at a cadence of the user's choosing.
- AI-Driven Training Suggestions: Integrated chat tool offering tailored training plan suggestions and educational resources.
The project is currently in early development. Features are actively being developed and refined.
This project is licensed under the MIT License.