The project is a personal one, but the decisions are documented.
Here are the ones that aren't obvious from the README.
Direct DynamoDB, no API Gateway
Next.js server actions talk to DynamoDB through an IAM role bound to
the Amplify SSR runtime. One layer less than the typical AWS web stack,
same auth boundary — the browser still only sees Next.js endpoints
behind a Cognito-validated cookie.
AI provider abstraction
A single generateText dispatcher sits behind four backends.
Swap with one env var; prompts stay portable. The coach was rebuilt
against Bedrock, Gemini, OpenAI and Anthropic without touching the
prompt code.
i18n without a library
A tiny dictionary module typed against a single Dictionary
interface — both locales must compile, so a missing translation breaks
the build, not production. No URL prefixes, no SSR/CSR mismatches,
no runtime negotiation in the hot path.
The coach prompt is yours to shape
The Profile page holds an athlete description and a free-form notes
field. Both are pasted verbatim into every AI coach prompt — so the
suggestions account for your age, goals, and quirks ("no squats,
bad knee") without you re-explaining them every week. No forking,
no env-var sprawl: the same row drives the rest of the app.