Skip to content

dstahl11/StrongCoachAI

Repository files navigation

πŸ‹οΈ StrongCoach

A self-hosted strength-training app with an AI coach that programs for you and holds you accountable.

Plan and log your lifts set-by-set, track PRs, estimated 1RMs, tonnage and consistency over time β€” and train alongside an AI coach that knows your history, respects your injuries, and emails you when you skip a session.

Next.js React TypeScript Tailwind CSS Postgres Claude CI


AI Coach Β Β·Β  Notifications Β Β·Β  Dashboard Β Β·Β  Quickstart Β Β·Β  Features


πŸ€– AI coach

Programs your next session, remembers your injuries and goals, and nudges you when you slip.

πŸ“ˆ Real progress

PRs, estimated-1RM, tonnage and consistency β€” every metric derived from the sets you actually log.

🐳 Self-hosted

One docker compose up to a running app with your own admin. Your box, your data.


πŸ€– Meet Hank β€” your AI coach

Chat with a Starting-Strength coach that has your full training history in context. He remembers your injuries and weight caps, adapts programming around them, schedules your sessions, and won't let you push into a bad idea.

AI coach chat

Above, Hank hears that a knee's been cranky, logs it to memory (the green pill), pulls the athlete's real last sessions and 405 lb deadlift goal from context, and programs a knee-friendly day with the reasoning spelled out β€” then offers to write it straight onto the calendar.

Give your coach a soul

Every coach is editable β€” its name, voice, and coaching philosophy are sent with every message. Tell it what to remember (injuries, caps, goals), and it shapes every answer and every programmed session.

Editable coach persona Coach memory
The persona / β€œsoul” β€” fully editable, per user Long-term memory the coach reasons from

πŸ”” Notifications your way

A morning digest and missed-workout nudges, delivered over email, ntfy push, or both β€” at your local send time, with quiet hours and a per-channel test button.

Per-channel notification settings

πŸ“Š Dashboard & progress

Consistency heatmap, stacked tonnage-by-exercise, and an estimated-1RM strength trend β€” all range-filterable (30d β†’ all time).

Dashboard

πŸ—“οΈ Calendar & workout logging

A scrollable month view (infinite scroll + month/year jump) and a list view, with completion dots, coach-programmed badges, and ✈️ travel blackouts. Tap a day to log it set-by-set.

Month calendar Workout day view
Month calendar β€” completion dots + travel days Day view β€” per-set logging, warm-ups, comments

πŸ’ͺ Exercise library

A searchable catalog with demo videos, per-exercise stats & history, and full create / edit / delete (delete is guarded when an exercise has history).

Exercise library

✨ Features

  • AI Coach ("Hank") β€” chats with your full history in context; remembers facts about you (injuries, caps, goals). Runs on Claude via Portkey. He can:
    • schedule & adjust workouts from chat, respecting your weight caps and excluded lifts,
    • autonomously program upcoming Starting-Strength sessions, progressed from your real lifts,
    • honor blackout days (travel) β€” never programs or nags on them,
    • send a morning digest + missed-workout reminders over email (Resend) and/or ntfy push, at each user's local send time, with per-channel "send test" buttons, quiet hours, and no duplicate sends across restarts.
  • Calendar β€” infinite-scroll month view + list view with completion dots and travel markers.
  • Workout logging β€” exercise cards (A / B / C…), N Γ— reps @ weight, expandable per-set logging, warm-up calculator, demo links, comments, skip, and Mark Complete.
  • PRs & Estimated 1RMs β€” auto-computed per workout (Epley formula).
  • Stats & history β€” per exercise: working-weight, e1RM and PR lines with 30d…all ranges.
  • Dashboard β€” consistency heatmap, tonnage-by-exercise, strength-trend charts.
  • CSV import β€” bring in workout-history exports; completed sessions without per-set actuals fall back to the prescription so they still feed PRs and charts.
  • Multi-user + admin β€” email/password auth, per-user data isolation, an admin area to create users and manage roles, and a separate coach per user.

πŸ‘₯ Multi-user & admin

Every user sees only their own workouts and gets their own coach (cloned from a shared "Hank" template β€” personas can diverge). Admins get an /admin area to create users, set roles (admin / user), reset passwords, and edit any user's coach. Auth is a lightweight custom email + password with database sessions β€” no external service, so it runs fully self-hosted.

πŸ› οΈ Tech stack

  • Next.js 16 β€” App Router, React 19, Server Components + Server Actions
  • Tailwind CSS v4 Β· Recharts Β· lucide-react Β· date-fns
  • Drizzle ORM on Postgres via the standard node-postgres driver β€” runs against any Postgres (local Docker, self-hosted, managed)
  • Claude via Portkey for the coach Β· pluggable notifications (Resend email, ntfy push) Β· node-cron for the daily tick (catch-up + persistent dedupe)
  • bcryptjs + DB sessions for auth

πŸš€ Getting started (one command)

Requires Docker β€” that's it.

git clone https://github.com/dstahl11/StrongCoachAI && cd StrongCoachAI
docker compose up -d

That brings up Postgres, applies the schema, creates an admin account, and starts the app at http://localhost:3000. Grab the generated admin password from the init logs (you'll be asked to change it at first sign-in):

docker compose logs init | grep -A2 "admin account"

Optional knobs β€” set as environment variables (or in a .env file next to docker-compose.yml) before docker compose up:

Variable Effect
ADMIN_EMAIL / ADMIN_PASSWORD choose the first admin's credentials instead of generated ones
SEED_DEMO=1 load ~16 weeks of demo training history (pairs with TODAY_OVERRIDE=2026-06-27)
CRON_SECRET enables POST /api/coach/tick for an external cron (the built-in scheduler runs regardless)
PORTKEY_API_KEY + PORTKEY_INTEGRATION turn on the AI coach (chat + personalized notification copy)
RESEND_API_KEY + COACH_FROM_EMAIL turn on the email notification channel
NTFY_SERVER default ntfy server for push notifications (default https://ntfy.sh; topics are per-user in Settings)
TZ container timezone (users can also set a per-user timezone in Settings)

Everything optional stays dormant when unset β€” the app runs fine without any of it, and the startup log prints a friendly summary of what's configured.

Local development

Requires Node β‰₯ 20.9 (pinned to 22.14.0 via .nvmrc β€” run nvm use).

npm install
docker compose up -d db          # just the database
cp .env.example .env.local       # then fill in keys as needed

npm run db:push                  # sync schema
npm run db:seed                  # optional demo history
npm run db:create-admin -- you@example.com 'your-password' 'Your Name'

npm run dev                      # http://localhost:3000

πŸ“œ Scripts

Script What it does
npm run dev Start the dev server
npm run build Production build + typecheck
npm run db:push Sync the Drizzle schema to Postgres
npm run db:seed Wipe + reseed demo training history
npm run db:create-admin -- <email> <pw> [name] Create an admin and assign existing data
npm run import -- <csv> [--append] [--user=<id>] Import a workout-history CSV
npm run db:studio Open Drizzle Studio

πŸ—„οΈ Data model

users own everything. exercises is a shared catalog; workouts β†’ workout_exercises β†’ set_groups (prescriptions) and logged_sets (actual performance). PRs, e1RM, tonnage and the charts are all derived from logged_sets. The coach adds coach_profile, coach_memories, chat_messages, blackout_days, and coach_events. See src/db/schema.ts.

⏰ Notifications & scheduling

Delivery is a small pluggable notifier interface (src/lib/notify/) with email + ntfy backends β€” adding Pushover/Telegram/webhooks later is a ~50-line backend plus a settings card. The daily tick runs in-process every 15 minutes with catch-up semantics: each user fires once their local hour reaches their configured send hour, dedupe is persisted per-channel in coach_events (failed sends retry a few times; restarts never double-send), and quiet hours suppress late catch-ups. Admins get a "Run check now" button and every user sees a recent-notifications log in Settings. Prefer an external scheduler? Set COACH_CRON=0 and point a system cron at POST /api/coach/tick with your CRON_SECRET.

πŸ“ Notes

  • Deploys as a Docker container with a Postgres container alongside it (see Dockerfile + docker-compose.yml; the init service makes first-run and upgrades idempotent).
  • The coach explicitly respects stated injury limits and defers pain to a professional β€” it is not medical advice.
Built with Claude Code.

About

strength training log with AI coach

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages