← Sol Thiessen

Apr 2026 – present · Built and hosted, schema to deploy

Athlete platform

One record per athlete, shared by everyone who works with them: injuries, testing and performance plans in one place. Each role on the staff sees exactly what it should, in English or French.

Open the demo ↗Source is private. Happy to walk through it.

Backend
Java · Spring Boot
Frontend
React 19 · TypeScript
Data
PostgreSQL · 19 migrations
Languages
English · French
Deploy
Docker · GHCR · CI/CD

Who it's for

A sports-science team looks at the same athlete through many lenses. The platform gives each staff role its own view of one shared record, and gives athletes a dashboard of their own.

CoachStrength & conditioningMedicalParamedicalNutritionMental performanceAthleteAdmin

The public demo has a role switcher, so you can see how the same athlete looks to each member of staff.

What's in it

Injuries

Triage, injury cards with typed updates, and expected against actual return dates.

Testing

Physical and technical performance, with trends over time and cohort comparisons.

Performance plans

Individual plans broken into domains, action items and a worklist of what's open.

Excel import

Legacy workbooks parsed on upload, so existing data comes in without retyping.

Engineering notes

A

The demo can't leak into production

The demo's login panel, role switcher and published password exist only in a separate frontend image. The production image tree-shakes them away, and CI greps the built bundle to prove the demo credentials aren't in it.

B

Test once, deploy everywhere

Tests run on every pull request, and main only accepts branches that are up to date. A push to main builds each image once per commit, then fans out to every server as parallel jobs. Server secrets live on deploy environments, where a pull request can't reach them.

C

Invitations double as email verification

Athletes arrive through Excel import without accounts. An admin invites one by email and gets a one-time link that expires after 48 hours. Only a SHA-256 hash of the token is stored, and re-inviting supersedes the old link.

D

Bilingual from the schema up

Labels are translated in the database as well as the interface, messages use ICU formatting, and a key checker and lint rules catch any string that's missing its French.

How it's built

BackendJava, Spring Boot, Flyway migrations, Apache POI for workbook parsing
FrontendReact 19, TypeScript, Vite, Tailwind, Chart.js, i18next with ICU
DataPostgreSQL; integration tests run against a real Postgres in Testcontainers
InfraDocker Compose, nginx, TLS, GitHub Actions, GitHub Container Registry
ProcessNon-technical stakeholders file issues in a separate repository, so nobody outside engineering is near the deploy secrets
© 2026 Sol ThiessenBack to the start