Strona glowna portalu Miasta i Gminy Stary Sacz

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.

Strona glowna portalu Miasta i Gminy Stary Sacz
Strona główna portalu, z wyróżnionymi aktualnościami i 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, 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.

Uklad strony glownej: aktualnosci, sekcje tematyczne, slider uslug, widgety
Sekcje tematyczne, slider usług, nadchodzące wydarzenia i widgety pogody oraz jakości powietrza

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.

Lista aktualnosci z filtrami po kategoriach i tagach
Sekcja Dla Turysty z katalogiem atrakcji
Karta miejsca turystycznego z opisem, mapa i danymi kontaktowymi
Sekcja Dla Mieszkanca z procedurami i informacjami urzedowymi
Struktura organizacyjna urzedu i jednostek podleglych
Kalendarz wydarzen gminnych

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.