Skip to content

Repository files navigation

GymTrace

An after-hours training journal. Log sets, track body weight and steps, detect PRs automatically, and watch your volume history render as a live heatmap.


Features

Session Builder

  • Horizontal exercise columns with drag-to-reorder (dnd-kit)
  • Drag-gesture numeric inputs — pull up/down on weight, left/right on reps
  • Automatic PR detection per set using the Epley e1RM formula
  • PR sets glow with an animated chrome-to-acid conic gradient
  • Rest timer with 60/90/120/180s presets and an AudioContext ping at zero
  • Press A to open the exercise picker without touching the mouse

Exercises

  • Image upload with drag-and-drop, browser-side AVIF re-encode before upload
  • Images stored on Backblaze B2 via signed PUT URLs (5-min TTL)
  • YouTube reference link per exercise (opens technique video inline)
  • Live search

Dashboard

  • Weekly volume with % delta vs prior 7 days
  • Session count, set count, weekly PRs, training streak
  • 12-month volume heatmap rendered with Three.js InstancedMesh (371 tiles, sqrt-normalized brightness)
  • Stalled lifts — exercises with no e1RM improvement in 4+ weeks
  • Latest body weight + 7-day step average

Weight & Steps

  • Scrubbable SVG line chart — acid raw line, violet 7-day rolling average, floating tooltip
  • Drag-gesture quick-log input
  • Full history with delete

Shell & Navigation

  • ⌘K command palette
  • G-chord keyboard navigation: G E → Exercises, G S → Sessions, G D → Dashboard, G W → Weight, G T → Steps
  • Acid-green stripe sweeps the top of the screen on every route change (View Transitions API)
  • Installs as a PWA — offline shell cached via service worker

Auth & Security

  • Argon2id password hashing (OWASP 2024 parameters)
  • Iron-session sealed cookie (30-day TTL, httpOnly, SameSite=strict)
  • CSRF double-submit pattern (csrf-csrf)
  • Helmet with strict Content-Security-Policy
  • CORS restricted to WEB_ORIGIN only
  • All queries scoped to the authenticated owner — no cross-user data access possible
  • Rate limiting on auth endpoints (5/min register, 10/min login)

Tech Stack

Layer Choice
Monorepo Turborepo + pnpm workspaces
Frontend Next.js 16 (App Router, Turbopack)
Styling Tailwind v4 CSS-first @theme
Animations Motion/React
3D Three.js (InstancedMesh heatmap)
Drag & drop dnd-kit
Server state TanStack Query v5
Backend NestJS 11
Database PostgreSQL via Prisma 7 + pgBouncer
Auth iron-session + Argon2id
Storage Backblaze B2 (S3-compatible)
Validation Zod (shared contracts package)
Logging nestjs-pino

Monorepo Structure

gymtrace/
├── apps/
│   ├── api/              # NestJS backend (port 3001)
│   └── web/              # Next.js frontend (port 3000)
└── packages/
    ├── contracts/        # Shared Zod schemas + DTOs (built to dist/)
    ├── ui/               # Shared React component library
    └── config-tailwind/  # Night Garage design tokens + base CSS

Getting Started

Prerequisites

  • Node.js 20+
  • pnpm 9+
  • A PostgreSQL database (e.g. Supabase free tier)
  • A Backblaze B2 bucket with S3-compatible API enabled

1. Install dependencies

pnpm install

2. Configure the API

Copy the example env file and fill in the values:

cp apps/api/.env.example apps/api/.env
Variable Description
DATABASE_URL PostgreSQL connection string (pooled, for runtime)
DIRECT_URL PostgreSQL connection string (direct, for migrations)
SESSION_SECRET ≥32 random chars — openssl rand -hex 32
CSRF_SECRET ≥32 random chars — openssl rand -hex 32
B2_KEY_ID Backblaze B2 application key ID
B2_APPLICATION_KEY Backblaze B2 application key
B2_BUCKET_NAME Bucket name
B2_ENDPOINT S3 endpoint URL e.g. https://s3.eu-central-003.backblazeb2.com
B2_PUBLIC_BASE_URL Public CDN URL e.g. https://f003.backblazeb2.com/file/bucket-name
WEB_ORIGIN Frontend origin for CORS e.g. http://localhost:3000

3. Run database migrations

pnpm --filter api prisma:migrate:dev

4. Start development servers

pnpm dev

This starts both the API (:3001) and the web app (:3000) in parallel.

Open http://localhost:3000 and create an account.


API Overview

All routes require authentication except /auth/login, /auth/register, /auth/csrf, and /health/*.

GET    /health/live
GET    /health/ready

GET    /api/auth/csrf
POST   /api/auth/register
POST   /api/auth/login
POST   /api/auth/logout
GET    /api/auth/me

GET    /api/exercises?q=
POST   /api/exercises
PATCH  /api/exercises/:id
DELETE /api/exercises/:id

GET    /api/sessions
POST   /api/sessions
GET    /api/sessions/:id
DELETE /api/sessions/:id
POST   /api/sessions/:id/exercises
PATCH  /api/sessions/:id/exercises/order
DELETE /api/sessions/:id/exercises/:seId
POST   /api/sessions/:id/exercises/:seId/sets
PATCH  /api/sessions/:id/exercises/:seId/sets/:setId
DELETE /api/sessions/:id/exercises/:seId/sets/:setId

GET    /api/body-weight?days=
POST   /api/body-weight
DELETE /api/body-weight/:id

GET    /api/steps?days=
POST   /api/steps
DELETE /api/steps/:id

GET    /api/stats/dashboard

GET    /api/media/upload-url?filename=&contentType=

Scripts

pnpm dev                                      # start all apps in watch mode
pnpm build                                    # build all apps and packages
pnpm check-types                              # type-check entire monorepo

pnpm --filter api prisma:generate             # regenerate Prisma client
pnpm --filter api prisma:migrate:dev          # run migrations (development)
pnpm --filter api prisma:migrate:deploy       # run migrations (production)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages