The context
Physio Xpert is a rehabilitation platform for physiotherapists, running in production at app.physio-xpert.com. The practitioner runs a clinical assessment, the platform derives medical flags from it, those flags drive the prescribed exercises, and the patient completes their sessions from a mobile app, reporting tolerance after each exercise.
I designed and built all of it solo over eight months: the API, the practitioner back-office, the patient mobile app, the data schema, the hosting and the test suite. Three constraints explain nearly every technical decision that follows.
Clinical logic has to evolve without a redeployment. Alert criteria follow practice, not release cycles: they live as data, editable by practitioners themselves from the back-office.
This is health data. Certified hosting, encryption, explicit consent and access traceability form a regulatory frame that is set at design time, not at delivery.
One developer, over time. Every piece has to stay understandable and changeable by a single person five years from now, which rules out over-engineering as much as shortcuts.
The clinical decision chain
This is the piece to understand first: everything else in the architecture exists so that this chain stays correct, traceable and editable without a redeployment.
practitioner
Clinical assessment
An assessment whose content is configured, not coded.
platform
Decision engine
Answers are matched against the clinical criteria in force.
platform
Medical flags
Red flags (contraindication) and yellow flags (caution).
platform
Exercise prescription
Flags filter and weight the proposed programme.
patient
Guided session
The session runs on mobile, with tolerance feedback.
Tolerance feedback loops back into progression: the next session is stepped up, held or eased. It is a loop, not a funnel: the same patient goes through this cycle at every session.
Two properties of this chain shaped the rest of the work. First, one link is configured, not coded: a practitioner can change their assessments and alert criteria without me deploying anything. Second, the output of the last link feeds back into the first: progression is not a pure function of an initial assessment, it is a state machine accumulating the patient's history.
The technical choices
API
Java and Spring Boot
End-to-end strong typing and an ecosystem whose maintenance and documentation will still be there in ten years: two properties that matter more than concision on a health product.
Boundaries
Modular monolith, a single process
Every business module owns a boundary, enforced at build time: a forbidden dependency breaks compilation instead of going to review. The isolation of microservices, without their operational cost for a team of one.
Clinical logic
Configured, not coded
Assessments and alert criteria are versioned data, edited from the back-office and effective immediately. The product stops depending on my release cycles.
Mobile
React Native and Expo
The patient app displays exercises and collects tolerance feedback: nothing that demands native. One codebase for iOS and Android halves the surface to maintain.
The architecture that follows
All 310 API routes live under /api/v1. The back-office and the mobile app
update at different rhythms, and an app installed on a phone does not redeploy
with a git push: API versioning is not a theoretical precaution here.
What the test suite covers
Working solo changes the method: with no reviewer, the only thing that can contradict a line of reasoning is a test. Coverage is therefore not spread evenly: it is concentrated where a silent mistake would have clinical or regulatory consequences.
Progression and training load
The most sensitive piece: it decides whether a patient steps up or eases off. It is locked down by reference corpora replayed on every run, one of them covering 19,440 transitions. Any divergence breaks the suite; the new expected behaviour has to be justified explicitly.
Clinical criteria evaluation
Every comparison operator and every combination of answers has to produce the expected flag, including degraded cases: a missing answer, an out-of-range value, a criterion referencing a question that was removed from the assessment.
Authorisation, route by route
Authorisation is declared explicitly on each route rather than inferred from the presence of a token. One test per route checks that a practitioner unrelated to the record is refused, not merely that an authenticated user is accepted.
Persistence and migrations
Tests run against a real PostgreSQL started in a container, not an in-memory database that would accept queries production rejects. The schema is rebuilt from scratch on every run: a migration that fails to replay is caught before it ships.
GDPR lifecycle
Consent collection and withdrawal, soft deletion, effective purge once retention expires, completeness of the access log. These are verifiable requirements, so they are verified.
Back-office journeys
In a real browser: login, record creation, running an assessment, reading the flags it raised, prescription. The full journey, not isolated screens.
Module boundaries
Allowed dependencies between business modules are declared and enforced at compilation. A shortcut taken on a Friday evening does not compile.
The volume is not the argument, quotable as it is: 4,658 tests on the API, whose actual execution I verified rather than just counting. The argument is that none of these areas can change behaviour silently.
What health data demands
Compliance is not a layer added before going live, it is a set of constraints written into the earliest migrations. Consent is explicit, timestamped data rather than a ticked box; deletion is soft, with a 30-day retention window; every read of a patient record is logged. These requirements belong in the schema because an audit log added afterwards leaves a historical gap nothing can fill. Hosting follows the same logic: HDS certification in a French region is a legal prerequisite, settled before it is an infrastructure choice.
The same principle applies to external dependencies. A monitoring tool will happily ship a name or a clinical answer inside an error context, so sensitive data is scrubbed before anything is sent, at the source rather than by filtering downstream.
Where the product stands
The platform is in production and still evolving: a 310-route API covered by 4,658 tests, a practitioner back-office, a mobile app on both stores, HDS-certified hosting in France, and roughly 235,000 lines of Java and TypeScript maintained by one person.
The central bet holds up over time: practitioners evolve their assessments and alert criteria without going through me. That is exactly what the decision engine was meant to make possible.



