Bagtyyar

MyORL — ENT Clinic Platform

Active build

Bilingual healthcare website for a private ENT surgical clinic in Athens — Next.js 16, Strapi 5 CMS, Meilisearch, fully deployed and serving patients.

  • Next.js 16
  • React 19
  • TypeScript
  • Tailwind CSS v4
  • Strapi 5
  • PostgreSQL 18
  • Meilisearch
  • Docker
  • Caddy
  • Vitest
  • Playwright
  • Railway

Outcome

Live in production serving real patients — bilingual Greek/Russian healthcare platform with full CMS handover to clinic staff.

Context

A private ENT (ear, nose, throat) surgical clinic in Athens needed a modern web presence: a bilingual (Greek/Russian) site with a condition encyclopedia, service and price pages, video content, and appointment booking — maintained by non-technical staff after handover. Client details are anonymized; the site is live and publicly reachable.

Engineering Decisions

  • Frontend: Next.js 16 App Router + React 19 + Tailwind CSS v4, bilingual routing (Greek/Russian), server components for fast first paint on clinic Wi-Fi and mobile data.
  • CMS: Strapi 5 + PostgreSQL 18 so clinic staff edit encyclopedia entries, prices, and videos without touching code.
  • Search: Meilisearch for instant, typo-tolerant search across conditions and treatments — patients rarely know exact medical spelling.
  • Migration: Custom extraction tooling (myorl-migrate) to pull content out of the legacy MODX site into structured Strapi content types.
  • Infrastructure: Docker Compose + Caddy locally; production deployed on Railway (frontend, Strapi, Postgres, and Meilisearch as separate services).
  • Testing: Vitest + React Testing Library for components, Playwright for end-to-end flows including booking.

Outcomes

  • Live in production, serving real patients — bilingual content, search, and booking all operational.
  • 314 commits across frontend, CMS, and migration tooling.
  • Full handover: the clinic edits its own content; no developer needed for routine updates.

Visit the live site · Public repository

Milestones

  1. Inception and MODX migration tooling

    OK

    Content audit of the legacy MODX site, custom extraction tooling, and slug parity mapping into structured Strapi content types.

    Completed Apr 2026

  2. Strapi 5 CMS and content model

    OK

    Strapi 5 + PostgreSQL content types for pages, encyclopedia entries, services, prices, and media; unified CmsGateway client and page normalizer on the frontend boundary.

    Completed Apr 2026

  3. Bilingual frontend with Meilisearch

    OK

    Greek/Russian Next.js frontend on Tailwind v4 tokens; full-site typo-tolerant search with bulk corpus seed, Strapi webhook reindexing, and bilingual synonym dictionaries.

    Completed May 2026

  4. Production launch on Railway

    OK

    Docker builds, ISR with per-locale sitemaps, security headers (CSP/HSTS), and production routing fixes; site live and serving patients.

    Completed May 2026

  5. Client remediation and content handover

    OK

    Remediation pass against the client's requirement documents; 23 published Greek pages; day-to-day content editing handed over to clinic staff.

    Completed Jun 2026

  6. Infrastructure rescue and relaunch

    OK

    Relaunched on the Railway project celebrated-abundance at myorl.up.railway.app after the original deployment lapsed; date-dependent appointment-picker tests pinned to a fixed system time.

    Completed Oct 2026

Architecture Decisions

Strapi 5 as headless CMS with a semantic DTO boundary

Strapi 5 owns content; the Next.js frontend consumes it through a single CmsGateway and page normalizer, never leaking CMS shapes into components.

Clinic staff need to edit content without a developer, and the legacy MODX schema could not be exposed directly to the frontend. A semantic DTO boundary (ADR-001) isolates Strapi schema changes from the UI and gave the migration tooling a stable target.

Full-site search via Meilisearch

Meilisearch indexes the bilingual encyclopedia and service pages; Strapi webhooks keep the index in sync on every content change.

Patients rarely know exact medical spelling, and the content is bilingual Greek/Russian. Meilisearch (ADR-011) provides typo-tolerant instant search; a bulk corpus seed, webhook lifecycle with locale-scoped deletes, and curated synonym dictionaries keep results accurate in both languages.

URL-mapping content type for legacy redirects

Legacy MODX URLs resolve through a dedicated Strapi content type instead of hard-coded redirect tables.

The old site had years of indexed URLs that could not break at launch. A URL-mapping content type (ADR-012) lets redirects be audited, edited, and versioned alongside content, and kept MODX slug parity verifiable during the cutover.

Relaunch at myorl.up.railway.app

Site restored on the celebrated-abundance Railway project and verified live after the original deployment lapsed; appointment-picker tests pinned to a fixed system time to remove a date-dependent failure.

Production hardening for launch

CSP and HSTS security headers, per-locale sitemap and static params, ISR on the home route, production routing fixes for slug pages, and mobile search and tab repairs ahead of go-live.

Search corpus seed and Strapi webhook lifecycle

Bulk-seeded the full search corpus into Meilisearch and wired Strapi webhooks so create, update, unpublish, and delete events reindex with locale-scoped deletes; bilingual synonym and stopword dictionaries added with sync tooling.

Ready to build something that lasts?

Let’s talk about your project. I’ll bring the discipline, you bring the vision.

Work With Me