Skip to content
ndleytonPublic

About

Fitness tracker + AI coach web app

Resources

Contributing

Stars

1 star

Watchers

1 watching

Forks

Repository files navigation

PersonalBestie

PersonalBestie is a full-stack fitness tracker designed to help users log workouts, routines, and exercises, featuring a local-first guest mode and an AI-powered coaching layer built with server-side function calling.

License: MIT FastAPI React 19 Python pnpm Gemini


Key Features

  • Local-First Guest Mode: Instantly log workouts without an account. All data is persisted locally in the browser's IndexedDB and seamlessly synced to the database once you sign in.
  • AI Coaching and Recaps: Undergoes automated post-workout analysis using Google Gemini to summarize performance, detect personal records (PRs), and provide evidence-based workout insights.
  • Server-Side Function Calling: AI capabilities are validated and executed securely server-side using typed schemas and FastAPI-backed endpoints rather than ungrounded prompt generation.
  • Bring Your Own AI Assistant (MCP): Connect a compatible assistant to explore exercises, review your training history, create routines, and log workouts. Choose read-only or read-and-write access, and revoke it anytime.
  • Responsive UI: Modern interface optimized for both desktop and mobile screens, built with Tailwind CSS v4 and React 19.

Connect Your AI Assistant (MCP)

Your training history can inform conversations with the AI assistant you already use. PersonalBestie exposes two Model Context Protocol (MCP) servers over Streamable HTTP:

Server URL Access
Exercise catalog https://app.personalbestie.com/api/mcp/catalog/ Public, read-only exercise search, details, muscle taxonomy, and substitutions.
Personal trainer https://app.personalbestie.com/api/mcp/trainer/ Personal access token required for workout history, routines, workout logging, and recaps.

Connect to your account

  1. Sign in to PersonalBestie and open Personal Access Tokens / MCP in your profile settings.
  2. Create a token with trainer:read to review your training. Include both trainer:read and trainer:write to create routines, log workouts, and generate recaps.
  3. Copy the token when it is shown; it is displayed only once.
  4. In an MCP client that supports Streamable HTTP and custom bearer authentication, add the trainer URL above and configure Authorization: Bearer <your-token>.

Keep the trailing slash in the server URL. Revoke tokens from your profile settings whenever you want to remove access. The public catalog needs no token.

Try asking your connected assistant:

  • “Review my recent workouts and summarize my progress.”
  • “Find an alternative to bench press using dumbbells.”
  • “Create a three-day routine based on my recent training.”

Run locally

The normal FastAPI startup also mounts each MCP endpoint when MCP_ENABLED and its corresponding catalog or trainer setting are enabled:

  • Catalog: http://localhost:8000/api/mcp/catalog/
  • Trainer: http://localhost:8000/api/mcp/trainer/

Use the backend setup below to configure the database and apply migrations. For a client that launches a local stdio process, run these from backend/:

uv run python -m src.mcp.cli catalog
PE_BE_USER_ID=<your-user-id> uv run python -m src.mcp.cli trainer

Trainer stdio is a trusted local mode: it grants access as the specified database user without a PAT. Use the authenticated HTTP endpoint for remote connections.

Deploy on the VM

MCP runs inside the existing backend container. Set these values in backend/.env.production before rebuilding and recreating it:

MCP_ENABLED=true
MCP_CATALOG_ENABLED=true
MCP_TRAINER_ENABLED=true
MCP_PUBLIC_BASE_URL=https://app.personalbestie.com/api/mcp
MCP_ALLOWED_HOSTS=app.personalbestie.com,origin-api.personalbestie.com
MCP_ALLOWED_ORIGINS=https://app.personalbestie.com
MCP_ALLOW_TRUSTED_STDIO_USER=false
MCP_PAT_PEPPER=<persistent-random-secret>

Generate the pepper once with openssl rand -hex 32. Keep it private and retain it across deployments; changing it invalidates existing tokens. Substitute your own domains when self-hosting. The public proxy must forward /api/mcp/* and the Authorization header to the backend.

The current Deploy VPS workflow rewrites .env.production without these MCP settings. Update its environment generation before using it to deploy MCP; manually added settings would otherwise be overwritten.


Project Structure

Path Purpose
backend/ FastAPI application, SQLAlchemy models, Alembic migrations, and backend tests.
pe-be-tracker-frontend/ React 19 + Vite frontend application.
docker-compose.yml Local multi-container development configuration.
CONTRIBUTING.md Open-source contributor guidelines and conventions.
AGENTS.md Reference file for AI agents and developer rule setups.

Stack Overview

Backend

  • Language & Runtime: Python 3.10–3.12 managed by uv
  • Web Framework: FastAPI
  • ORM / Migrations: SQLAlchemy + Alembic
  • Database: PostgreSQL
  • AI Integration: google-genai (Google Gemini)
  • Observability: Langfuse (tracing and prompt management)

Frontend

  • Library: React 19 (TypeScript)
  • Build Tool: Vite
  • Router: React Router v7
  • State Management: Zustand
  • Data Fetching: TanStack Query
  • Styling: Tailwind CSS v4
  • Testing: Vitest & Playwright

AI Layer & Architecture

What makes this project technically interesting is that the AI layer is not just free-form chat. It is structured around server-side function calling, typed inputs, real data grounding, and consistent image generation:

  • Server-Side Function Calling: Instead of relying on prompt-only instructions, the chat assistant uses Google Gemini with application-owned tools. The backend defines and exposes these tools to Gemini.
  • Input Validation: Tool inputs are validated using typed schemas before execution, ensuring reliability and security.
  • Data Grounding: The assistant answers questions by running tools that query the database for real, user-specific workout metrics (PRs, volume deltas, history) and notes.
  • Post-Workout AI Recaps: Automated, evidence-based coaching summaries are triggered asynchronously upon workout completion. Generated via backend/src/workouts/recap.py (WorkoutRecapService), it gathers workout statistics and qualitative notes to compose personalized coaching feedback.
  • Consistent Image Generation Pipeline: An advanced multi-phase image generation system in backend/src/genai/google_images.py produces consistent, multi-frame exercise guide illustrations. It uses the first generated frame (or an uploaded reference) as a visual anchor image, feeding it back into the model to generate the subsequent exercise phases (e.g., start/eccentric vs concentric positions) while maintaining anatomical consistency, clothing, art style, and framing.
  • Observability: Prompt versions, traces, and LLM latency are tracked in real-time using Langfuse. Details can be found in backend/LANGFUSE_INTEGRATION.md.

Quick Start (Local Development)

The backend and frontend are typically run separately for a better hot-reloading experience.

Prerequisites

  • Python 3.10 to 3.12 with uv
  • Node.js 20+ with Corepack-enabled pnpm
  • PostgreSQL running (you can start a PostgreSQL container using docker compose up db -d from the root)

1. Launch the Backend

Navigate to backend/:

cp .env.example .env
uv sync
uv run alembic upgrade head
uv run uvicorn src.main:app --reload --host 0.0.0.0 --port 8000
  • API Base: http://localhost:8000/api/v1
  • Health Check: http://localhost:8000/health

2. Launch the Frontend

Navigate to pe-be-tracker-frontend/:

corepack enable
pnpm install
cp env.example .env.development
pnpm run dev
  • Local URL: http://localhost:5173

Docker Compose Alternative

To run the entire full-stack application inside containers:

docker compose up --build
  • Frontend: http://localhost:3000
  • Backend: http://localhost:8000
  • Postgres: localhost:5432

To stop containers and tear down resources including database volumes:

docker compose down -v

Common Development Commands

Backend Commands

From backend/:

uv run pytest                            # Run full test suite with coverage
uv run pytest --no-cov tests/test_file.py # Run a single test file without coverage checks
uv run ruff check .                      # Lint codebase
uv run ruff check . --fix                # Auto-fix lint errors
uv run alembic current                   # Inspect current migration status
uv run alembic upgrade head              # Apply all migrations

Frontend Commands

From pe-be-tracker-frontend/:

pnpm run dev                             # Start development server
pnpm run lint                            # Run ESLint validation
pnpm run typecheck                       # Check TypeScript compilability
pnpm test                                # Run unit tests via Vitest
pnpm run test:coverage                  # Run unit tests and generate coverage report
pnpm run test:e2e                        # Run Playwright E2E tests

Architecture & Conventions

Time and Timezones

  • All datetime metrics are transported and stored in UTC.
  • Conversions to UTC happen prior to database insertions/updates.
  • User-facing components in React format timestamps into the client's local timezone.

Contributing

For details on database optimization (such as joinedload vs selectinload), branching strategy (main as the PR target), and defensive Alembic migration patterns, please read our dedicated CONTRIBUTING.md guide.


License

PersonalBestie is open-source software licensed under the MIT License.

About

Fitness tracker + AI coach web app

Resources

Contributing

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages