Engineering

Run App: my first project — a fitness platform with Strava, Garmin, and AI run analysis

The first thing I built at DRCODE, as an intern — a microservice fitness platform that syncs Strava and Garmin, predicts training paces with a small ML model, and analyzes runs with an AI agent.

Mokshit Jain · · 6 min read

Run App was the first project I built at DRCODE, when I was still an intern. It’s a running/fitness platform, and I built it from the ground up alongside my QA-automation work. Looking back, it’s where I learned to structure a real multi-service system rather than a single app.

What it does

At its core it helps runners train: it generates phased workout plans (5K, 10K, half, and full marathon), tracks activities, logs nutrition, and gives AI-driven feedback on each run.

The two things I’m still happy with:

  • It syncs real data from Strava and Garmin. Both are full OAuth 2.0 integrations — Garmin uses PKCE — pulling activities, heart rate, and training data through background job queues (BullMQ).
  • It analyzes runs with AI. A Google Gemini agent looks at a completed run lap by lap, compares what actually happened against the planned workout, and sends a personalized summary — including over WhatsApp, through the Evolution API.

There’s also a small Python/Flask ML service that predicts training paces from a 5K time using a scikit-learn random-forest model, which the main backend calls over HTTP.

How it’s put together

The frontend is Astro with React components. The backend is five NestJS microservices — the main API plus dedicated Strava and Garmin connectors — with a Flask ML service alongside. Data lives across three PostgreSQL databases (about 20 Prisma models) with Redis for caching and queues. Everything runs as Docker Compose services behind Nginx, and it deploys to AWS EC2 through GitHub Actions.

I also exposed the app’s capabilities through an MCP server — greeting, activities, nutrition, workout plans, and pace prediction as tools — so an AI agent could drive it.

Astro/React  →  NestJS API  →  { Strava connector, Garmin connector }  →  BullMQ jobs

                    ├─ Flask ML (pace prediction)
                    └─ Gemini agent (run analysis → WhatsApp)

What I took away

As a first project, the biggest lesson was service boundaries — deciding what belongs in the main API versus a dedicated connector, and how they talk to each other cleanly. Wiring up two real third-party OAuth integrations (Strava and Garmin) also taught me how much of “integration” is handling the unhappy paths: token refresh, rate limits, and webhooks that arrive out of order.

Share
Written by
Mokshit Jain

AI engineer & full-stack developer building LLM products, automation, and RAG pipelines.

Continue reading

Engineering·

The Astro + NestJS monorepo I actually reuse

A reusable full-stack starter I built so I stop wiring up the same architecture every time — Astro, NestJS, tRPC, and Prisma in one pnpm/Turbo monorepo, set up with a single command.

Mokshit Jain · 5 min