Strona główna portalu i sekcja Dla mieszkańca w dwóch oknach przeglądarki

Programowanie

Portal miasta i gminy na headless CMS

Portal miasta i gminy, działający od 16 października 2026: headless CMS, cztery wersje językowe, WCAG 2.2 AA i RODO. Zbudowany od podstaw na otwartym oprogramowaniu i utrzymywany wyłącznie na serwerach gminy.

6.09.2026

Pracuję w samorządzie i od dłuższego czasu patrzyłem na nasz stary portal z rosnącym niedosytem. W końcu sam podjąłem się zbudowania nowego: takiego, który informuje mieszkańca, prowadzi turystę, pomaga załatwić sprawę i spełnia wymogi dostępności cyfrowej.

16 października 2026 roku nowy portal przejął główny adres gminy. Od pierwszego commita do startu minęło siedem miesięcy. Stara strona na WordPressie nie zniknęła, tylko przeszła do archiwum.

Od początku zależało mi na niezależności od wielkich koncernów i usług chmurowych, bez złotówki kosztów licencyjnych. Zamiast gotowego systemu pod klucz zaprojektowałem architekturę headless. Osobny panel służy do zarządzania treścią, a osobny silnik generuje strony dla odwiedzających.

Redaktorzy dostają prosty interfejs do pracy z treścią. Mieszkańcy dostają stronę, która ładuje się szybko, bo nie dźwiga ciężaru panelu administracyjnego.

Strona główna portalu i sekcja Dla mieszkańca w dwóch oknach przeglądarki(powiększ)
Strona główna i sekcja Dla mieszkańca, z przełącznikiem języka PL/EN/HU/SK

Dla kogo jest ten portal

Zanim usiadłem do pierwszego komponentu, rozpisałem sobie, kto faktycznie z tej strony korzysta. Gmina obsługuje pod jednym adresem bardzo różne potrzeby:

  • mieszkańca, który sprawdza aktualności, wydarzenia i terminy odbioru odpadów,
  • turystę i inwestora, którzy szukają informacji w swoim języku,
  • pracownika, który redaguje treści bez pomocy informatyka,
  • osobę z niepełnosprawnością, dla której czytnik ekranu musi po prostu działać,
  • lokalnego przedsiębiorcę, który chce sam zgłosić atrakcję turystyczną.

Ta lista zdecydowała o strukturze treści bardziej niż jakikolwiek szablon graficzny.

Co znalazło się w portalu

Największym wyzwaniem nie było jedno trudne zadanie, tylko skala. Portal ma dziś ponad trzydzieści modułów i kilkadziesiąt kolekcji w panelu CMS. Wszystkie muszą działać spójnie w czterech językach.

Sprawy online i wyszukiwarka

Sekcja Dla mieszkańca zaczyna się od pytania: jak załatwić sprawę? Wystarczy wpisać, co chcesz zrobić, a wyszukiwarka wskaże procedurę i właściwy referat.

Karta sprawy zawiera podstawę prawną, wymagane dokumenty, opłaty i formularze do pobrania. Na końcu jest link do ePUAP lub gov.pl, jeśli sprawę da się załatwić online.

Wyszukiwarka całego portalu działa na Meilisearch. Zwraca wyniki w trakcie pisania, rozumie polską odmianę i synonimy. Przeszukuje naraz artykuły, procedury, katalog turystyczny i projekty.

Sekcja Dla mieszkańca z wyszukiwarką spraw i kategoriami procedur(powiększ)
Wyszukiwarka spraw w sekcji Dla mieszkańca

Turystyka i mapy

Dla turysty zbudowałem katalog atrakcji z filtrami i mapą. Lokalny przedsiębiorca może sam zgłosić miejsce przez formularz, a redakcja je moderuje. Questy turystyczne z kodami QR prowadzą na krótkie adresy /q/kod.

Wszystkie mapy działają na Leaflet.js i OpenStreetMap, bez zależności od Google Maps. Mapa gminy pokazuje sołectwa jako klikalne obszary, a dane przestrzenne trzyma PostGIS.

Mapa gminy z pinezkami miejsc turystycznych nad listą atrakcji(powiększ)
Miejsca turystyczne na mapie gminy

Aktualności i wydarzenia

Aktualności mają filtry po kategoriach i tagach, a pod artykułem link do posta na Facebooku. Kalendarz wydarzeń pokazuje nadchodzące terminy i archiwum.

Strona wydarzenia ma mapę dojazdu, przycisk zakupu biletów i eksport do kalendarza Google lub Apple. Po zakończeniu albo odwołaniu wydarzenia przycisk biletów sam znika.

Lista wydarzeń z kalendarzem miesiąca obok strony festiwalu jazzowego z mapą i przyciskiem Kup bilet(powiększ)
Kalendarz wydarzeń i strona festiwalu z mapą dojazdu

Nasza gmina w danych

Zamiast tabel przepisanych z raportów, część stron pokazuje dane wprost. Gmina w liczbach ma wykresy liczby mieszkańców oraz urodzeń i zgonów. Miasta partnerskie mają własną mapę z datami podpisania umów.

Mieszkańcy dostali też interaktywny harmonogram odbioru odpadów. Zamiast szukać swojego rejonu w kilkunastu plikach PDF, od razu widzą terminy dla swojej ulicy.

Wykresy liczby mieszkańców oraz urodzeń i zgonów obok mapy Europy z miastami partnerskimi(powiększ)
Gmina w liczbach i mapa miast partnerskich

Fundusze europejskie i projekty

Ze starej strony przeniosłem 128 projektów finansowanych z funduszy zewnętrznych. Są pogrupowane według programów, od KPO po Interreg. Karta projektu pokazuje cele, wartość, kwotę dofinansowania, zdjęcia i dokumenty.

Strona Fundusze europejskie i zewnętrzne z projektami pogrupowanymi według programów(powiększ)
Projekty pogrupowane według programów finansowania

Dostępność jako fundament, nie dodatek

Ustawa o dostępności cyfrowej nie zostawia wyboru: portal gminny musi spełniać WCAG 2.2 AA. Dlatego dostępność była wymaganiem od pierwszego komponentu, a nie listą poprawek na koniec. W praktyce oznacza to:

  • kontrast tekstu co najmniej 4,5:1, sprawdzany automatycznie,
  • pełną obsługę klawiaturą i widoczny fokus na każdym elemencie,
  • obszar kliknięcia co najmniej 24 na 24 piksele,
  • semantyczny HTML5 z ARIA, testowany z czytnikami NVDA i VoiceOver,
  • trzy rozmiary tekstu, tryb wysokiego kontrastu i motyw ciemny,
  • czytanie na głos w języku strony, także po angielsku, węgiersku i słowacku,
  • skróty klawiszowe: Alt+1 do treści, Alt+S do wyszukiwarki, Alt+M do menu.

Dostępność zależy też od tego, co wpisują redaktorzy. Dlatego przygotowałem dla nich poradnik dostępnych treści, opublikowany na samym portalu.

Pasek narzędzi portalu: czytanie na głos, rozmiar tekstu, kontrast, motyw i wybór języka, pod nim odtwarzacz artykułu i skróty Alt+1, Alt+S, Alt+M(powiększ)
Pasek dostępności, odtwarzacz artykułu i skróty klawiszowe

Panel dla redakcji

Portal jest tak dobry, jak treści, które w nim są. Dlatego sporo pracy poszło w panel Directusa, choć odwiedzający nigdy go nie zobaczą. Redaktorzy dostali:

  • polski interfejs z opisem przy każdym polu i podpowiedzią, co wpisać,
  • widoki dopasowane do pracy: moje wpisy, szkice, kalendarz wydarzeń, drzewo stron z przeciąganiem,
  • automatyczne opisy SEO generowane przy zapisie,
  • czyszczenie formatowania wklejonego z Worda, zanim trafi na stronę,
  • powiadomienia e-mail o błędach zgłoszonych przez mieszkańców,
  • rejestr adresów kończących się błędem 404, z możliwością dodania przekierowania.
Trzy okna panelu CMS: logowanie, lista inwestycji i edycja artykułu z podpowiedziami przy polach(powiększ)
Panel Directusa przygotowany dla redaktorów

Bezpieczeństwo i niezależność od dostawców

Druga zasada, która przewijała się przez cały projekt: dane gminy nie opuszczają jej własnej infrastruktury. Bez Google Analytics, bez zewnętrznych chmur i bez uzależnienia od jednej firmy.

Baza PostgreSQL działa w izolowanej sieci Docker, bez portu wystawionego na zewnątrz. Porty kontenerów zamyka zapora, a z sieci lokalnej widać tylko reverse proxy. Pliki trzyma własny serwer S3 na MinIO.

Kopia bazy powstaje automatycznie co noc, z retencją 30 dni. Uptime Kuma pilnuje dostępności, a statystyki odwiedzin liczy Matomo na serwerze gminy.

Formularze publiczne chroni kilka warstw naraz: honeypot, limit zgłoszeń z jednego adresu IP, walidacja po stronie serwera i sprawdzanie rzeczywistego typu pliku. Captcha to mCaptcha, samodzielnie hostowany mechanizm proof-of-work, więc nic nie trafia do Google reCAPTCHA.

Stack i koszt licencji: zero złotych

Cały portal stoi na otwartym oprogramowaniu. Dla budżetu gminy oznacza to brak opłat licencyjnych, a dla gminy brak przywiązania do jednej firmy IT na lata.

  • Directus 11 jako panel treści i API,
  • Astro 7 w trybie SSR na Node.js generuje strony,
  • PostgreSQL 16 z PostGIS trzyma dane, także przestrzenne,
  • Redis 7 przyspiesza cache,
  • Meilisearch odpowiada za wyszukiwanie,
  • Leaflet.js rysuje mapy,
  • TailwindCSS i DaisyUI budują interfejs,
  • Docker Compose spina całość w kontenery.
Schemat architektury: redakcja pracuje w Directusie, dane trzymają PostgreSQL, Redis i MinIO, Astro serwuje strony odwiedzającym, wyszukuje Meilisearch(powiększ)
Architektura: panel treści i strona działają osobno

Wdrożenia idą przez własny pipeline CI/CD w OneDev. Push do repozytorium uruchamia sprawdzenie typów TypeScript i wdrożenie na serwer testowy ze smoke testem. Dopiero otagowana wersja trafia na produkcję, a kolejny smoke test sprawdza, czy strona działa.

Przeprowadzka ze starej strony

Nowy portal nie zaczynał od zera. Skryptem przeniosłem ze starego WordPressa ponad dwa tysiące artykułów, galerie i projekty. Po drodze treści przeszły porządki: zniknęły śmieci z Worda, puste akapity i martwe linki.

Najwięcej uwagi wymagały adresy. Stare linki z Google, Facebooka i stron partnerów nie mogły prowadzić donikąd. Portal zna więc mapę przekierowań 301 ze starych adresów, a to, czego nie przeniesiono, otwiera się w archiwum WordPressa pod osobną domeną.

Po starcie każdy adres zakończony błędem 404 trafia do rejestru w panelu. Redakcja może od razu wskazać, dokąd ma prowadzić.

Nie budowałem kolejnej wizytówki. Budowałem narzędzie, z którego mieszkaniec, turysta i pracownik korzystają codziennie, bez zastanawiania się, że w tle stoi headless CMS, własna infrastruktura i architektura zgodna z WCAG.

- Aleksander Kowal

Pierwszy tydzień po starcie

Pierwszy tydzień po przełączeniu domeny przyniósł 1773 wizyty. 62 procent ruchu przyszło z Google, a 44 procent z telefonów. To potwierdziło, że widok mobilny nie może być dodatkiem.

Statystyki pokazały też, czego mieszkańcy szukają. Wpisywali hasła takie jak KPO, fotowoltaika czy nazwy sołectw, a wyszukiwarka nie znała jeszcze projektów. Kilka dni później projekty były w indeksie, a wyszukiwarka dostała synonimy i skróty do najczęstszych fraz.

Infografika: 2397 artykułów, 147 stron, 62 karty spraw, 128 projektów, 829 zdjęć w 83 galeriach, 51 miejsc turystycznych, 4 wersje językowe, 1773 wizyty w pierwszym tygodniu(powiększ)
Portal w liczbach po starcie

Co dalej

Portal działa, ale nie jest skończony. W kolejce czekają:

  • eRada, czyli radni, komisje i kluby, jako uzupełnienie gotowej już strony sesji z transmisjami i archiwum nagrań,
  • moduł konsultacji społecznych z dokumentami i terminami,
  • newsletter na własnym serwerze,
  • aplikacja PWA, którą można zainstalować na telefonie bez sklepu z aplikacjami,
  • elektroniczne wnioski z podpisem.

Kliknij albo przewiń, żeby przybliżyć. Przeciągnij, żeby przesunąć.Stuknij dwa razy albo rozsuń palce, żeby przybliżyć.