
Programowanie
Portal Miasta i Gminy Stary Sącz
Nowy portal internetowy Miasta i Gminy Stary Sącz: headless CMS, cztery wersje językowe, pełna zgodność z 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 pewnym momencie stwierdziłem, że czas na nową jakość, i sam podjąłem się wykonania: zbudować portal internetowy, który jednocześnie informuje mieszkańca, prowadzi turystę, obsługuje sprawę urzędową i spełnia wymogi prawne dotyczące dostępności cyfrowej.
To była moja własna wizja tego, jak powinien wyglądać portal gminny. Od początku zależało mi na niezależności od wielkich koncernów i usług chmurowych, bez utraty tempa i bez ani złotówki kosztów licencyjnych. Zamiast gotowego systemu pod klucz zaprojektowałem architekturę headless: osobny panel administracyjny do zarządzania treścią i osobny silnik generujący strony dla odwiedzających. Taki podział daje redaktorom w urzędzie prosty, znany interfejs do pracy z treścią, a użytkownikom stronę, która ładuje się błyskawicznie, bo nie dźwiga na sobie ciężaru panelu administracyjnego.

Dla kogo jest ten portal
Zanim usiadłem do pierwszego komponentu, rozpisałem sobie, kto faktycznie z tej strony korzysta, bo urząd gminy obsługuje bardzo różne potrzeby pod jednym adresem: mieszkańca, który chce sprawdzić aktualności i wydarzenia, turystę i inwestora, którzy potrzebują informacji w swoim języku, pracownika urzędu, który ma redagować treść bez pomocy informatyka, osobę z niepełnosprawnością, dla której czytnik ekranu musi po prostu działać, oraz lokalnego przedsiębiorcę, który chce zgłosić atrakcję turystyczną wprost przez formularz.
Ta lista zdecydowała o strukturze treści dużo bardziej niż jakikolwiek szablon graficzny.

Co znalazło się w portalu
Największym wyzwaniem nie było pojedyncze trudne zadanie, tylko skala: portal ma dziś ponad trzydzieści modułów funkcjonalnych i ponad trzydzieści pięć typów treści w panelu CMS, a wszystkie musiały działać spójnie w czterech językach.
Publikacja treści stoi na aktualnościach z filtrami po kategoriach i tagach, kalendarzu wydarzeń z eksportem do Google i Apple Calendar oraz galeriach fotograficznych z lightboxem. Nad wszystkim czuwa wyszukiwarka pełnotekstowa oparta o Meilisearch, która zwraca wyniki w czasie pisania, radzi sobie z polskimi końcówkami fleksyjnymi i przeszukuje jednocześnie artykuły, procedury urzędowe i katalog turystyczny.
Osobną gałąź stanowi eUrząd: wyszukiwarka procedur, karta sprawy z podstawą prawną, wymaganymi dokumentami i opłatami, oraz bezpośrednie linki do ePUAP i gov.pl. Do tego pełna struktura organizacyjna urzędu z referatami i danymi kontaktowymi, a osobno jednostki podległe: organizacyjne, edukacyjne i spółki gminne.
Dla turysty zbudowałem katalog atrakcji z filtrami, mapą i formularzem, przez który lokalny przedsiębiorca może sam zgłosić miejsce do moderacji, oraz questy turystyczne z kodami QR prowadzącymi na krótkie, czytelne adresy /q/kod. Interaktywna mapa gminy, oparta o Leaflet.js i PostGIS, pokazuje sołectwa i obszary jako klikalne regiony, bez żadnej zależności od Google Maps.






Dostępność jako fundament, nie dodatek
Ustawa o dostępności cyfrowej stron internetowych i aplikacji mobilnych podmiotów publicznych nie zostawia wyboru: portal gminny musi spełniać WCAG 2.2 AA. Zamiast traktować to jako listę poprawek na koniec, zaprojektowałem dostępność jako wymaganie od pierwszego komponentu.
W praktyce oznacza to kontrast tekstu na poziomie minimum 4.5:1 weryfikowany automatycznie, pełną obsługę klawiaturą bez użycia myszy, widoczny fokus na każdym elemencie interaktywnym, minimalny obszar kliknięcia 24 na 24 piksele zgodnie z WCAG 2.2, alternatywne opisy zdjęć, logiczną hierarchię nagłówków i semantyczny HTML5 wsparty ARIA, testowany z czytnikami NVDA i VoiceOver. Do tego przełącznik rozmiaru czcionki, skróty klawiszowe (Alt+1 do treści, Alt+S do wyszukiwarki, Alt+M do menu mobilnego) i dedykowana strona z listą tych skrótów.
Tryb ciemny dopina całość: strona rozpoznaje preferencje systemowe użytkownika i pozwala je nadpisać ręcznie.
Bezpieczeństwo i pełna niezależność od zewnętrznych dostawców
Druga decyzja, która przewijała się przez cały projekt: żadne dane gminy nie opuszczają jej własnej infrastruktury. Zero Google Analytics, zero zewnętrznych chmur, zero uzależnienia od jednego dostawcy oprogramowania.
Panel CMS jest dostępny wyłącznie z sieci urzędu albo przez VPN. Baza danych PostgreSQL siedzi w izolowanej sieci Docker, bez wystawionego na zewnątrz portu. Pliki i media trzyma własny serwer S3 oparty o MinIO, zamiast Dropboksa czy Google Drive. Backup bazy leci automatycznie co noc na osobny serwer, z retencją 30 dni, a Uptime Kuma alarmuje SMS-em i mailem w ciągu 60 sekund od awarii. Statystyki odwiedzin liczy self-hosted Matomo, więc dane ruchu też zostają na miejscu.
Wszystkie formularze publiczne, od zgłoszenia błędu po zgłoszenie atrakcji turystycznej, chroni kilka warstw naraz: honeypot na boty, rate-limiting ograniczający liczbę zgłoszeń z jednego adresu IP, walidacja po stronie serwera i sprawdzanie rzeczywistego typu pliku, nie tylko rozszerzenia. Formularze wykorzystujące weryfikację captcha korzystają z mCaptcha, self-hostowanego rozwiązania proof-of-work, więc żadne dane użytkownika nie trafiają do Google reCAPTCHA.
Stack i koszt licencji: zero złotych
Cały portal stoi na oprogramowaniu open-source, co dla budżetu gminnego oznacza brak opłat licencyjnych teraz i w przyszłości, a dla samego urzędu, że nie jest przywiązany do jednej firmy IT na lata. Panel treści prowadzi Directus, strony generuje Astro 5 w trybie SSR na Node.js, dane geograficzne i tekstowe trzyma PostgreSQL z rozszerzeniem PostGIS, a Redis przyspiesza cache i kolejki. Do tego Meilisearch jako wyszukiwarka, Leaflet.js jako silnik map, TailwindCSS z DaisyUI po stronie interfejsu i Docker Compose spinający całość w kontenery.
Wdrożenia idą przez własny pipeline CI/CD: push do repozytorium uruchamia sprawdzenie typów TypeScript, automatyczny deploy na staging ze smoke testem, a po otagowaniu wersji, automatyczny deploy na produkcję z kolejnym smoke testem i możliwością błyskawicznego rollbacku. Zero przestojów przy aktualizacjach.
Nie budowałem kolejnej wizytówki urzędu. Budowałem narzędzie, z którego mieszkaniec, turysta i urzędnik korzystają codziennie, bez zastanawiania się, że w tle stoi headless CMS, self-hostowana infrastruktura i architektura zgodna z WCAG.
- Aleksander Kowal
Stan projektu
Pierwsza faza jest zrealizowana i działa: strona główna, aktualności, galerie, wydarzenia, interaktywna mapa, wyszukiwarka, eUrząd z procedurami, struktura urzędu i jednostek podległych, katalog turystyczny z questami QR, moduł inwestycji i system zgłaszania błędów. W trakcie realizacji jest eRada, czyli sesje Rady Miejskiej, radni i komisje, oraz moduł konsultacji społecznych. Przed uruchomieniem produkcyjnym czeka jeszcze zewnętrzny audyt WCAG 2.2 AA, szkolenie redaktorów, migracja treści ze starego portalu i testy bezpieczeństwa. Po starcie w kolejce stoją newsletter, aplikacja PWA instalowalna na telefon bez sklepu z aplikacjami i elektroniczne wnioski z podpisem.
