Skip to content
Case study

Medova: Informed Care platform in 15 languages

A travel medicine clinic marketplace with a WHO/CDC public data aggregator, an architecture aligned with GDPR Art. 9 and ISMS ISO 27001. EPKO team responsible for architecture, code, security, and compliance.

ClientMedova / EPKO internal project
IndustryHealthcare / HealthTech
DurationOngoing, in production
Medova & EPKO TECH illustration case study

Regulatory compliance

  • WCAG
  • RODO

01 · Challenge

Challenge

A traveler types "Kenya vaccinations" into Google and lands on the CDC website. They read a list of 12 vaccinations: 3 mandatory, 4 recommended, the rest "depending on the region." They do not know which apply to their route. They do not know where to book a travel medicine doctor. They do not know the cost. They close the tab.

On the other side is a travel medicine clinic in Warsaw with open slots, every vaccine in stock, and a doctor who could answer each of those questions in 5 minutes. But that clinic does not exist in Google for "Kenya vaccinations." Its website is a business card with a phone number and a directions map.

This is the Care Gap: the chasm between credible medical information and a booked appointment. WHO and CDC data is public, clinics exist, patients are searching. What is missing is the layer that connects them.

Medova closes that gap. One place where a traveler learns which public health requirements apply to their destination, and where a partner clinic gains a channel to reach a patient who is already looking. The actual medical qualification and vaccination plan are made by a doctor at the clinic the patient books. Medova does not replace the consultation; it precedes it.

What the brief required

Project led by the EPKO team, responsible for architecture, code, security, and compliance. The scope demanded enterprise-grade treatment from day one:

  • 15 languages from day one, including Arabic (RTL) and Japanese. The travel health market is global, and SEO in one language means giving up 90% of organic reach. No "we'll add it later." From the first commit.
  • Daily synchronization with public WHO and CDC sources. A pipeline queries 6 external sources once a day, normalizes data, and refreshes published requirements per country × disease × vaccine. Data freshness is not a convenience; it is the foundation of trust in the platform.
  • Marketplace with booking, payments, and clinic verification. Full flow: clinic profile, doctor calendar, slot, payment, confirmation. Each clinic passes identity verification before appearing in search results.
  • GDPR and ISMS-aligned architecture from the first commit. Article 9 GDPR data (health information) requires exceptional care. Row-Level Security on every table, audit trail, encryption, retention policies, explicit consent. All designed into the architecture, not bolted on before launch.
  • The MDR/AI Act boundary drawn deliberately. Medova presents public requirements and connects patients with clinics. Diagnosis, medical qualification, and vaccination decisions remain with the doctor at the partner clinic. That boundary is written down, documented, and enforced in copy and UI.
  • Startup budget, enterprise discipline. Infrastructure had to cost like Supabase plus a dedicated server, not like AWS with a consultant. Every architectural decision evaluated against long-term cost.

02 · Solution

Solution

Instead of planning architecture for a quarter, the EPKO team had a working prototype in 6 weeks. Key decision upfront: we are not building "a platform that will someday support 15 languages." We are building a platform that supports 15 languages now. Every day without a Turkish, Indonesian, or Spanish version is organic traffic we will never recover.

Stack: deliberate trade-offs, not hype

Next.js 16 with App Router. SSR for SEO (Google needs to see translated content, not a spinner), and dynamic dashboards for clinics and admins. One framework for both use cases.

Supabase as the backend foundation. PostgreSQL 15 with Auth, Storage, Edge Functions, and Row-Level Security in one package. The alternative was a quarter on authentication and authorization boilerplate, unacceptable for a platform handling Article 9 GDPR data. Trade-off: less flexibility in extreme edge cases. Acceptable for this product stage.

Sanity v5 as CMS for editorial content. Document-level i18n, Portable Text, embedded Studio at /studio. A medical editor prepares content in one place, and the article appears in 15 language versions without developer involvement.

Coolify on Hetzner instead of Vercel/AWS. Dedicated server in Germany (EEA, no US transfers at the hosting layer), Docker standalone, zero vendor lock-in. Cloudflare for CDN and DDoS, with DPF status for GDPR compliance. Cost: a fraction of the cloud alternative at comparable availability.

Multilingual routing: one of the harder problems

URL /pl/wiedza/choroby must lead to the same component as /en/knowledge/diseases. Files on disk live under English paths, and URL translations live in the database so adding a new language does not require redeploy.

We solved this with a proxy in the routing layer. Not Next.js middleware, not redirects, not 15 copies of the same files. The proxy intercepts the request, recognizes the locale, translates the path to its English equivalent, and forwards it to the correct component. Transparent to the user.

Security: 935 RLS policies as a zero-trust foundation

Each of 160 tables has Row-Level Security policies. Who can read, write, modify, delete, at the row level. A patient sees only their own data. A clinic sees only its patients. A moderator sees reports. An admin sees everything. Even if someone bypassed the frontend and hit the API directly, the database would refuse.

935 policies is the result of a systematic process, not a side effect. Every new table triggers an immediate question: who has access and why. We have our own audit tooling that blocks merges when a table appears without RLS.

Public source integration pipeline

6 Edge Functions in the Deno runtime query public sources daily:

  • WHO: Global Health Observatory, Disease Outbreak News
  • CDC: Travel Notices, Vaccination Requirements
  • Climate data, travel costs, travel advisories

Data flows into PostgreSQL, where 16 pg_cron jobs normalize it and refresh public views. In the UI, a patient sees the requirements published by WHO and CDC for the selected country, with the source and last-updated timestamp clearly marked. Full medical qualification of the patient happens at the clinic where they book the appointment.

On top sits an internal Python pipeline whose purpose is source data quality. XGBoost analyses completeness and stability of feeds. Isolation Forest detects anomalies (e.g. sudden gaps in WHO feeds, values diverging from historical trends). Alerts go to the Medova editorial team, which decides on updates to public views. This is an operational tool for the content team, not a recommendation system for the patient.

Compliance and data protection: enterprise from day one

Medova processes Article 9 GDPR data (special category, health information). That demands a regime most startups defer to "later." We treat it as a boundary condition:

  • Records of Processing Activities (Article 30 GDPR) with a map of every patient data flow between systems.
  • Data Protection Impact Assessment (DPIA, Article 35 GDPR) prepared for high-risk operations. Updated whenever architecture changes materially.
  • 72-hour breach notification procedure to the supervisory authority, with incident playbooks and contact lists.
  • Per-data-type retention policy with automatic anonymization once defined periods expire.
  • MDR/AI Act boundary written into the architecture: Medova presents public requirements; it does not issue patient-specific recommendations. Every UI surface where health requirements appear carries a clear disclaimer about the platform's role.

Engineering process: three gates, no blind spots

Every push to production must be safe. We built a three-gate pipeline where the heavy checks happen locally:

Gate 1, local: pre-commit checks secrets, formatting, and lint. Pre-push runs the full suite: strict lint, typecheck, 7,929 tests, production build, and bundle size check. If anything fails, the push does not go through.

Gate 2, GitHub Actions: safety net. Lint and typecheck on every PR (catches cases where someone bypasses local hooks). On merge to main, automatic migration push to the production database.

Gate 3, Coolify: detects a new commit on main, builds a Docker image, deploys the container with zero-downtime. Rollback is one click.

The whole process is supported by AI pair-programming tooling (Claude Code, Cursor) as part of a modern engineering workflow. AI accelerates the implementation of repeatable patterns and assists with refactoring. Architectural decisions, database schema, security policies, and code review remain with the engineers. It is a tool, not a replacement.

03 · Results

Results

Platform in production. A working marketplace with booking, payments, a clinic panel, and an admin panel, handling organic traffic in 15 languages. The numbers tell the story better than any description.

Code scale

1,778 TypeScript files in strict mode. Every type explicit, every null checked, every unused import a compilation error. 904 SQL migrations mean every database change is versioned, reproducible, and auditable. Zero manual changes in production.

  • 541 React components
  • 105 API endpoints, 13 Edge Functions in the Deno runtime
  • 665+ commits
  • 15 languages with full routing and translated URLs

Quality and security

7,929 tests are not the result of writing tests for the sake of tests. Each test exists because it protects a specific scenario. From data quality calculations, through clinic registration flows, to edge cases in RTL translations. Plus mutation testing (Stryker), which verifies that tests actually catch bugs, not just inflate coverage.

935 RLS policies across 160 tables. A level of security that in a traditional approach would require a dedicated security engineer at half capacity. In Medova it is built into the database architecture and maintained by tooling.

  • 6 system roles: patient, clinic, moderator, admin, analytics_viewer, sales
  • ISMS aligned with ISO 27001, phases 1 to 4 complete, certification readiness ~90%
  • 93 security controls, 10 documented risks, 4 incident playbooks
  • GDPR documentation: Records of Processing Activities (Art. 30), DPIA (Art. 35), 72h breach notification procedure

Infrastructure

All infrastructure within the EEA (Hetzner DE) plus Cloudflare at the CDN layer (DPF-compliant). Monthly cost lower than one hour of a senior developer. Comparable traffic on Vercel Pro means a bill 10 to 20 times higher.

  • Hosting: Coolify on Hetzner dedicated, cost in the tens of euros per month
  • CDN: Cloudflare (DPF), DDoS protection, edge caching, SSL
  • CI/CD: local hooks plus GitHub Actions, heavy tests run locally
  • Monitoring: SigNoz (OpenTelemetry), full observability without a Datadog licence

What it means for the business

  • Marketplace in production: full flow from clinic search through booking to Stripe payment
  • B2B API in beta: documentation, keys, rate limiting, ready for integration partners (travel agencies, insurers)
  • Founder's Program launched: first 50 clinics at zero commission
  • 4 pricing tiers: from free profile to Enterprise with a dedicated account manager

What we take away from this project

Trade-offs say more about a technology partner than a list of successes. A client looks for someone who can talk about both.

Supabase: excellent for MVP and a fast start on auth, storage, and RLS. But 935 RLS policies are deliberate architectural debt. We could simplify at the cost of security. We did not.

15 languages from day 1: a harder decision than "we'll add it later." Routing, tests, content, SEO, everything 15 times more complex. In return, a search engine advantage you cannot retrofit.

Mutation testing (Stryker): alongside unit tests. Catches false-positive coverage where tests pass but do not test what they should. Extra CI cost, but worth it.

The MDR/AI Act boundary from day one: healthtech platforms that do not draw this line deliberately tend to cross it accidentally after a year of growth. We wrote it into the architecture, the copy, and the code review process.

1,778TypeScript files541 React components, strict mode
7,929Tests499 test files + mutation testing
935RLS policies160 tables, 6 roles, zero-trust
15LanguagesIncluding Arabic (RTL) and Japanese
904SQL migrationsInfrastructure-as-code, zero manual changes
93Security controlsISMS ISO 27001, phases 1-4 complete

Technologies

Next.js 16React 19TypeScriptSupabasePostgreSQL 15Sanity v5StripeTailwind CSSCloudflareDockerCoolifyHetznerPythonXGBoostOpenTelemetryDenoUpstash RedisSigNoz

Planning a HealthTech product, marketplace, or multilingual platform? Let's talk about how we can help.

Get in touch