Strona firmowa · Topolowa Medicenter, Kraków · 2026 · 6 miesięcy

Topolowa Medicenter - statyczny HTML zamiast WordPressa

Pacjent nie ląduje na ogólnym formularzu: przycisk przy konkretnym badaniu otwiera widget rejestracji z już wybranym lekarzem i usługą, więc od kliknięcia do kalendarza jest jeden krok, nie pięć.

  • HTML
  • Tailwind CSS
  • Vanilla JS
  • nginx
  • GitHub Actions
  • ProAssist
Zobacz stronę live ↗
Topolowa Medicenter - statyczny HTML zamiast WordPressa

Wyzwanie

Centrum medyczne działało na WordPressie 5.9 na hostingu współdzielonym, z wygasłym certyfikatem SSL i kosztem odnowienia, który nijak się nie zwracał. Do tego strona nie odpowiadała na to, po co pacjent w ogóle na nią wchodzi: żeby zapisać się na konkretne badanie u konkretnego lekarza i dowiedzieć się, jak się do niego przygotować. Rejestracja online była jednym ogólnym widgetem, w którym trzeba było samemu odnaleźć właściwą usługę wśród kilkudziesięciu.

Nasze rozwiązanie

Zbudowaliśmy stronę od nowa jako statyczny HTML - 34 podstrony, bez bazy danych i bez panelu administracyjnego, który trzeba by aktualizować. Nagłówek, mega-menu i stopka żyją w jednym pliku JavaScript wstrzykiwanym do każdej podstrony, więc zmiana numeru telefonu to jedna linia, nie 34 pliki. Rejestracja dostała siatkę usług z deep-linkami: każdy kafelek otwiera widget ProAssist z preselektowanym lekarzem i badaniem. Deploy leci z gałęzi main przez GitHub Actions na VPS, ze skryptem rollbacku i monitoringiem sprawdzającym co 15 minut, czy strona i certyfikat żyją.

23 ms

Czas do pierwszego bajtu

0,18 s

Pierwsze renderowanie treści

34

Statycznych podstron

Co zbudowaliśmy

  • 01 34 statyczne podstrony, zero bazy danych i panelu do aktualizowania
  • 02 Nagłówek, mega-menu i stopka z jednego pliku JS na wszystkie podstrony
  • 03 Rejestracja z deep-linkami: kafelek usługi otwiera widget z wybranym lekarzem
  • 04 Osobne strony przygotowania do sześciu badań, z PDF-ami do pobrania
  • 05 Cennik, grafik przyjęć i profile lekarzy jako pełnoprawne podstrony
  • 06 301 redirecty ze starych adresów WordPressa, żeby nie stracić pozycji
  • 07 Cache-busting zasobów skrótem commita przy każdym deployu
  • 08 Monitoring co 15 minut: HTTP 200, treść strony i ważność certyfikatu
  • 09 Skrypt rollbacku z backupem bazy i smoke testem przed przełączeniem
  • 10 Skip-link, obsługa klawiatury i aria-expanded w nawigacji
Spis treści +

Punkt wyjścia

Stary WordPress 5.9 stał na hostingu współdzielonym z wygasłym certyfikatem. Odnowienie certyfikatu i przedłużenie hostingu kosztowały tyle, że sensowniej było postawić stronę na nowo niż łatać coś, czego i tak nikt nie aktualizował od lat.

Ale koszt hostingu to był tylko pretekst. Prawdziwy problem był w tym, po co pacjent wchodzi na stronę przychodni. Nie po to, żeby przeczytać o misji i wartościach. Wchodzi z jednym z trzech pytań: ile to kosztuje, kiedy przyjmuje ten lekarz i jak się przygotować do badania. Stara strona odpowiadała na nie po drodze, przy okazji, w akapitach.

Decyzje, które ukształtowały projekt

Statyk zamiast kolejnego WordPressa

Strona przychodni zmienia się kilka razy w roku: cennik, grafik, nowy lekarz w zespole. To nie jest obciążenie, które uzasadnia bazę danych, panel administracyjny i comiesięczne aktualizacje wtyczek. Nowa strona to pliki HTML serwowane przez nginx - nie ma logowania, więc nie ma czego przejąć, i nie ma wersji, która się przeterminuje. To ten sam wybór, który rozkładamy szerzej w tekście o tym, czy wybrać WordPressa czy Next.js - tu odpowiedzią było „żadne z nich”, bo strona firmowa, która zmienia się kilka razy do roku, nie potrzebuje żadnego z nich.

Kompromis jest uczciwy: klientka nie edytuje treści sama. W zamian nie ma też sytuacji, w której nieaktualizowana wtyczka wystawia na zewnątrz stronę z danymi kontaktowymi pacjentów.

Nagłówek i stopka w jednym pliku

assets/js/components.js renderuje nagłówek, pasek z numerami telefonów, mega-menu, panel boczny i stopkę - a każda z 34 podstron ma tylko <div id="site-header">. Trzy numery telefonu, godziny otwarcia i adres siedzą w jednym miejscu.

Alternatywą było skopiowanie nagłówka do 34 plików. Działa do pierwszej zmiany numeru, po której trzy podstrony zostają ze starym.

Rejestracja prowadzi do lekarza, nie do formularza

Centrum korzysta z zewnętrznego systemu rejestracji ProAssist. Domyślnie osadza się go jako jeden widget, w którym pacjent sam szuka swojej usługi na liście kilkudziesięciu pozycji.

Zamiast tego strona ma siatkę kafelków - konsultacja gastroenterologiczna u konkretnego lekarza, USG jelit, test oddechowy, kapilaroskopia - a każdy kafelek trzyma w data-widget-path ścieżkę do widgetu z już wybranym lekarzem i badaniem. Kliknięcie otwiera modal od razu na kalendarzu terminów. Te same deep-linki prowadzą z podstron badań, więc ktoś czytający o gastroskopii zapisuje się na gastroskopię bez wracania do zakładki „Rejestracja”.

Koszt tej decyzji: identyfikatory usług pochodzą z panelu ProAssist i po zmianie cennika trzeba je odświeżyć. Jest to opisane w komentarzu przy siatce, bo to jedyne miejsce w projekcie, które wymaga ręcznej synchronizacji z systemem zewnętrznym.

Przygotowanie do badania jako osobne strony

Pacjent przed kolonoskopią nie szuka przychodni - on już ją wybrał i teraz szuka instrukcji: co jeść, kiedy przestać, co wziąć ze sobą. Dostało to sześć własnych podstron plus PDF-y do wydrukowania, zamiast jednej zbiorczej strony z rozwijanymi sekcjami. Każde przygotowanie ma własny adres, który da się wysłać SMS-em przy potwierdzaniu wizyty.

Zejście ze starego adresu bez utraty pozycji

Stary WordPress miał adresy typu /personel/, nowa strona to pliki .html. nginx/tmedicenter-redirects.conf trzyma komplet 301, więc żaden link z Google ani z wizytówki nie kończy się na 404 - dokładnie ten punkt z checklisty SEO technicznego strony firmowej, który przy migracji najłatwiej pominąć.

Deploy, który da się cofnąć

Push do main uruchamia GitHub Actions: workflow podmienia ?v= w każdym HTML-u na skrót commita i wysyła pliki rsyncem na VPS. Cache-busting po SHA oznacza, że pacjent nigdy nie dostanie nowego HTML-a ze starym CSS-em z pamięci przeglądarki.

Do tego dwie rzeczy, których statyczna strona zwykle nie ma: scripts/rollback-to-static.sh robi backup bazy i plików przed przełączeniem vhosta i kończy smoke testem, a scripts/check-tmedicenter.sh chodzi z crona co 15 minut i sprawdza, czy strona zwraca 200 z sensowną treścią i czy certyfikat nie wygasa w ciągu 21 dni. Alert idzie mailem i tylko przy zmianie stanu, żeby nie zamienił się w tło.

Co z tego wyszło

Pomiar strony głównej z 13 września 2026, headless Chrome 1366x900, bez cache: 23 ms do pierwszego bajtu, 0,18 s do pierwszego renderowania treści - najszybsze FCP z naszych trzech ostatnich realizacji. Dalej jest gorzej: 1,38 s do zdarzenia load i 52 żądania - trzy dokumenty, siedem arkuszy stylów, dwadzieścia jeden obrazów, siedem plików JavaScript i czternaście fontów, razem 1323 kB transferu.

Nie udajemy, że to dobre liczby. Czternaście plików fontów na jedno wejście i sekunda trzysta osiemdziesiąt do load to rezerwa, nie sukces - i wiemy dokładnie, skąd się bierze: nagłówek i mega-menu renderowane z jednego pliku JS ładują komplet czcionek i grafik od razu, niezależnie od tego, którą podstronę ktoś otworzył. To dokładnie przypadek z checklisty Core Web Vitals - subsetting fontów i późniejsze ładowanie obrazów spoza pierwszego ekranu.

Czego nie wiemy: jak wyglądał stary WordPress pod tym samym pomiarem - certyfikat wygasł, zanim ktokolwiek go zmierzył, więc nie ma punktu odniesienia i nie szacujemy go na wyrost. To jeden pomiar syntetyczny z jednej maszyny, nie dane z ruchu realnych pacjentów.

Technicznie

Statyczny HTML, Tailwind CSS z CDN plus własny arkusz na to, czego klasy narzędziowe nie ogarniają. Dwa pliki JavaScriptu bez frameworka: components.js na wspólne części layoutu, navigation.js na hamburger, rozwijane menu i obsługę klawiatury. nginx na VPS OVH, deploy z main przez GitHub Actions, monitoring i rollback w repozytorium - nie w głowie ani w notatkach na serwerze.

Zrzuty ekranu

Strona główna - hero z dwoma CTA i pasek boczny z numerami oraz rejestracją, widoczny na każdej podstronie.
Rejestracja po usługach - każdy kafelek to deep-link otwierający widget z preselektowanym lekarzem i badaniem.
Cennik konsultacji i badań w tabeli - pacjent widzi kwotę przed rejestracją.
Personel: profile lekarzy jako pełnoprawne podstrony, nie ukryte w widgetcie.
Widok mobilny z przyklejonym paskiem „Zadzwoń" - najkrótsza droga do wizyty, gdy ktoś czyta stronę w poczekalni.

Podobny problem do rozwiązania?

Napisz krótko, o co chodzi — wycena wraca w 24 godziny.

Zapytaj o wycenę