E. Leveque
ENTheme: system
← Back to the course (P3 · km 58,2)

Oltre

A personal app to organize work and personal life in one full calendar: sport, expenses, tasks, appointments.

A walk through Oltre: expenses, tasks, meals. Dummy data.

The problem

My daily life was scattered: runs in Garmin, expenses in one place, tasks and appointments in another. I wanted to see everything in one place, with my sports activities in it.

The decisions

Garmin in a separate service

Trade-off: Garmin offers no official access: I use an unofficial library, which I isolated from the back end. One more service to run and protect, but a fragile dependency that doesn't contaminate the rest. And when Garmin refuses the connection, the real error reaches the screen instead of a vague message.

Gemini rather than Anthropic for the AI coach

Trade-off: Gemini has a free tier, the Anthropic API doesn't: for a personal project, the choice was quick. Downside: the coach stays silent without a key, and the model name has already needed a fix.

Login lockout by email and by IP

Trade-off: A stranger can't lock my account from their own machine. Downside: the counter lives in memory, resets to zero on restart and isn't shared across instances.

The architecture

Oltre architectureThe Angular frontend calls the Spring Boot backend over REST with a JWT. The backend reads MySQL and calls the garmin-mcp service with an internal token, which queries the unofficial Garmin Connect API (the fragile point). The backend also optionally calls Gemini for the coach.Angular frontendnginx, SPASpring Boot backendsport, expenses, tasks,appointments, meals, coachStateless security (JWT)MySQL 8.4Flyway schemagarmin-mcpREST, PythonGarminConnectunofficialGeminicoach, optionalREST + JWTJPAinternal tokenAPI keyOltre architectureAngular frontend, then the Spring Boot backend, which reads MySQL, calls garmin-mcp and then Garmin Connect (unofficial API, fragile point), and optionally calls Gemini.Angular frontendnginx, SPAREST + JWTSpring Boot backendsport, expenses, tasks,appointments, meals, coachJPAMySQL 8.4Flywaytokengarmin-mcpRESTGarmin Connectunofficial APIAPI keyGeminicoach, optional
Solid line: always called. Dashed: optional. Orange: the dependency I have no control over.

The wall at km 60

The hardest part wasn't the code: it was pinning down my idea and giving it shape. Going from a fuzzy need, organizing my work and personal life, to a concrete product.

What I take from it

Depending on an unofficial API means planning from day one where it will break, and telling the user plainly.