Skip to content

Lab-result history, API and web

SmartHealth

An API and a web application that turn the lab's PDF into a per-metric history, with the reference range picked by the owner's sex and age, a body-composition target and a shareable slice behind a link and a password.

Role
API and frontend review, academic project built by a pair
Period
March to November 2023
Status
Open source, completed in 2023
Patient dashboard: one card per exam marker, with its reference range and history, next to the BMI calculation and the anthropometry measurements.

What the system does

  • Reading the lab's PDF and extracting the value of every metric in the catalog.
  • A per-marker history, with the reference range picked by the owner's sex and age.
  • A body-composition target, with skinfold anthropometry and server-side calculation of density, body fat, lean mass and basal metabolic rate.
  • Sharing a slice with the doctor, by link with a password or by QR code, with no signup for the recipient.
  • A clinical catalog of twenty-five metrics and fifty-four reference ranges, loaded by migration.

Architecture

  • A NestJS API with Swagger-documented REST, a global ValidationPipe and eleven domain modules, plus two submodules nested through RouterModule.
  • Dependency by contract: each module declares an operations interface and registers the implementation behind an injection token, so the controller depends on the token and not on the class.
  • Domain modules do not return entities: each has an assembler that builds the DTO, and that is where the user's password disappears.
  • TypeORM over PostgreSQL, with one migration that loads the clinical catalog: twenty-five metrics with their units and fifty-four reference ranges keyed by sex and age interval.
  • JWT authentication in global middleware with an exclusion list, plus a second middleware that matches the token's subject against the id in the URL before letting the request through.
  • PDF reading with pdfjs-dist: each page's text layer becomes a normalized string, and every catalog metric is searched by a regular expression.
  • Result classification happens on write, not on read: the item is compared with the owner's range and the verdict is stored together with the range that was used.
  • Sharing by point-in-time copy across three dedicated tables, opened by a random identifier and a bcrypt-hashed password, on two public routes.
  • A Next.js web app on the pages router, with no API routes of its own, consuming the API through axios, with each marker's series in Chart.js.
  • A two-person flow with mandatory pull-request approval on both production branches, force pushes blocked and the branch-origin policy enforced by a workflow.

Implementation details

  • GraphQL with Apollo existed from March to September 2023, alongside REST. The module and its four resolvers were removed once no consumer was using them.
  • PDF extraction tolerates whitespace between the letters of the word RESULTADO, because the lab's text layer does not always come contiguous.
  • The recipient lands on a page that first checks whether the link exists and only then asks for the password. An invalid link never reveals whether a share existed.

Technologies

NestJS
The API framework, with modules, middleware and token-based injection.
TypeScript
The API's language.
TypeORM
Entity mapping and the clinical catalog migration.
PostgreSQL
The database for exams, metrics, targets and shared copies.
Swagger
API documentation, served by the application itself.
JWT
Authentication in global middleware, with an exclusion list.
bcrypt
Hashing the user's password and the share password.
pdf.js
Reading the text layer of the exam PDF.
Next.js e React
The web application, on the pages router, consuming the API.
Chart.js
Each marker's history series.
Jest
API tests, covering the assemblers and the PDF extractor.
Docker
The local environment, with PostgreSQL next to the API.
GitHub Actions
A build on every pull request and the branch-origin policy.
  • The tracking screen, with each marker's evolution over time.
  • Exam upload, the entry point of the module that reads the PDF and extracts the values.
  • The sharing flow, where the patient picks which results the doctor gets to see.
  • Diagram of the exam path: the PDF is read, the owner's reference range is applied on write, and the shared slice goes out through a link with a password.

Want to talk about architecture, technical decisions and shipping to production?

Portrait of Thiago Sanches

Contact details

Available for remote work with international teams

Name
Thiago Sanches
Location
Brazil · UTC−3 · remote
Languages
Portuguese native · professional working proficiency in English
Download résumé

Experience

  • 5 years

    on enterprise systems

  • 70%

    less time per new report

  • 50%

    less latency on GraphQL

  • Workers

    asynchronous processing with Redis queues