W skrócie
To, co firma nazywa „stroną internetową”, to zwykle dwie rzeczy: witryna, którą widzą odwiedzający, i miejsce, w którym ktoś siada i ją zmienia. Ten projekt to ta druga część — napisany od zera panel treści, z którego prowadzi się cały zestaw stron klienckich.
To praca komercyjna, więc nazwa klienta i produktu zostaje poza tym opisem. Wszystko poniżej dotyczy tego, co system robi i jak jest zbudowany.
Co zastępuje
Domyślna odpowiedź na „potrzebujemy strony, którą klient sam edytuje” to jeden WordPress na klienta. Działa dokładnie do momentu, w którym masz ich kilkanaście. Wtedy każda strona to osobna instalacja z własnym rdzeniem, motywem i wtyczkami do aktualizowania; każda ma stronę logowania na publicznej domenie klienta; i każda wystawia bazę oraz PHP każdemu, kto ich poszuka. Nikt nie ma czasu pilnować kilkunastu takich instalacji, więc po cichu się starzeją — aż coś się zepsuje albo ktoś się włamie.
Wiem, jak to wygląda z drugiej strony — ratowanie WordPressa zaczyna się zwykle po tym, jak nieaktualizowana wtyczka wpuści kogoś do środka.
Co panel naprawdę daje osobie, która w nim pracuje
Zanim technologia zacznie mieć znaczenie: to miejsce, w którym osoba nietechniczna otwiera podstronę, zmienia ją i publikuje.
- Składasz stronę z bloków Hero, lista funkcji, cennik, FAQ, galeria, panel kontaktowy — przeciągasz je w odpowiednią kolejność i wypełniasz pola. Bez HTML-a i bez shortcode’ów.
- Pilnujesz wszystkich języków Każda podstrona ma jedną wersję na język, a osobny ekran pokazuje, których tłumaczeń brakuje — razem z polami SEO, nie tylko treścią.
- Wgrywasz zdjęcie raz Wersje pod www powstają w tle, więc redaktor wrzucający 4 MB z telefonu nie spowalnia po cichu całej strony.
- Prowadzisz kolekcje, nie tylko podstrony Wpisy blogowe, case studies, usługi, plany cenowe, opinie, słownik pojęć — każda kolekcja ma własne pola, listing i kategorie.
- Masz pod ręką całą hydraulikę Menu, przekierowania, raport 404, sitemapa i hreflang, obrazki do social mediów — to, od czego zależy widoczność, siedzi obok treści.
- Rozdajesz właściwe klucze Trzy role, a autorowi można przydzielić dokładnie te kolekcje, nad którymi pracuje. Osoba od wpisów blogowych nie widzi cennika.

Kreator stron
Podstrona nie jest kawałkiem HTML-a. To uporządkowana lista typowanych bloków, trzymana osobno dla każdego języka, a każdy blok zna swoje pola. Typów bloków jest dziś 32 — hero, treść, funkcje, opinie, cennik, FAQ, galeria, zespół, godziny otwarcia, mapa, kontakt, wideo, zakładki, karuzela i reszta.

Dwie rzeczy z tej listy są ważniejsze niż jej długość:
- Nowy typ bloku to wpis w konfiguracji, nie nowy moduł. Paleta, którą widzi redaktor, opis przy każdym typie i pola w samym bloku pochodzą z jednego pliku konfiguracyjnego. Frontend rejestruje komponent pod tą nazwą i tyle.
- Zdolność wspólną dla wielu bloków deklaruje się raz, a nie kopiuje do każdego. Tło sekcji, wyrównanie, animacja pojawiania i identyfikator kotwicy mają jedną definicję, a blok tylko mówi, które z nich obsługuje — robi tak 26 z 32 typów.
- Każdy blok dostaje trwałe id przy pierwszym zapisie. Dzięki temu można podmienić jeden blok z zewnątrz — zapytaniem do API albo narzędziem AI — nie ruszając reszty podstrony.
Obok edytora stoi konspekt podstrony: jeden wiersz na blok, z fragmentem jego prawdziwej treści, więc długa strona daje się przeglądać zamiast zamieniać w ścianę zwiniętych paneli.

Nowe typy treści bez pisania kodu
Druga połowa silnika treści to kolekcje. Strona, która potrzebuje „case studies”, „godzin otwarcia dla każdego oddziału” albo „planów cenowych, ale w trzech osobnych zestawach”, nie dostaje pisanego pod siebie modułu. Kolekcję definiuje się w panelu — wybierasz typ elementu, włączasz pola, ustawiasz ikonę — i pojawia się w menu z własnym ekranem edycji, własnymi kategoriami i własnym endpointem API.
Każdy klient ma przy tym włączone tylko te kolekcje, z których faktycznie korzysta. Reszta jest wyłączona i nie zaśmieca mu menu.

Tłumaczenia, których stan widać
Wielojęzyczność zwykle sypie się po cichu: ktoś dodaje angielską podstronę, nikt nie dodaje polskiej, a lukę wyłapuje po miesiącach przypadkowy odwiedzający. Panel zamiast tego cały czas liczy — ile podstron jest przetłumaczonych w danym języku, których brakuje i czy wypełniono także tytuł i opis SEO, nie tylko samą treść.

Najciekawsza część: AI jako pełnoprawny klient CMS-a
Wszystko, co panel potrafi odczytać, CMS wystawia dwa razy — jako REST API i jako serwer MCP, za tym samym uwierzytelnieniem. MCP to protokół, którym asystenci AI rozmawiają z zewnętrznymi systemami, więc ta druga warstwa oznacza, że narzędzie AI pracuje bezpośrednio na treści, zamiast dostawać ją wklejoną z ręki.
Narzędzi jest tam dziś 82: wypisz i przeczytaj podstrony, przeszukaj treść, pobierz schemat bloków, utwórz podstronę, podmień pojedynczy blok po jego id, ustaw metadane, ogarnij kategorie, menu i przekierowania, wgraj media, uruchom przebudowę. Klient może podpiąć Claude’a do własnego panelu swoim własnym loginem — OAuth z PKCE, a nie token wklejony do pliku konfiguracyjnego — i poprosić o szkic podstrony, uzupełnienie brakujących opisów albo przetłumaczenie sekcji, a zmiany lądują w CMS-ie, nie w oknie czatu.
Dwoje drzwi do tej samej treści
Panel to jedno wejście. Terminal to drugie. MCP jest protokołem, a nie funkcją jednej aplikacji, więc te same narzędzia, które odpowiadają oknu czatu, odpowiadają też Claude Code — programista zostaje tam, gdzie już jest, i pisze do CMS-a z linii poleceń: tworzy podstronę, wypełnia jej bloki, ustawia metadane, uruchamia przebudowę.
To nie jest ścieżka na pokaz. Teksty na stronach postawionych na tym systemie weszły z terminala, a nie przez klikanie w panelu. Napisanie dwunastu podstron to inna robota, kiedy zamiast otwierać dwanaście formularzy podaje się brief i strukturę.
Oboje drzwi prowadzą do tej samej treści, tej samej walidacji i tych samych uprawnień. Osoba, która raz na kwartał poprawia stronę „O nas”, dostaje panel, który niczego od niej nie wymaga; programista stawiający całą stronę dostaje linię poleceń. Żadne z nich nie musi udawać drugiego.
Ciekawym problemem inżynierskim nie były same narzędzia, tylko zabezpieczenia:
- Poświadczenie nigdy nie jest szersze niż jego właściciel Każde chronione narzędzie sprawdza dwie rzeczy: czy osoba ma uprawnienie i czy poświadczenie ma pasujące pozwolenie. Poświadczenie tylko do odczytu nie uruchomi wdrożenia ani nie wyda cudzego limitu API.
- Zawsze w granicach jednego klienta To właściciel poświadczenia decyduje, czyją treść ono widzi. Nie ma parametru z id klienta, który dałoby się podmienić, więc nie ma czego pomylić między najemcami.
- Limity, które faktycznie ograniczają Narzędzia wydające prawdziwe pieniądze — wdrożenia, tagi wydań, limity zewnętrznych API — mają ostrzejszy przydział niż narzędzia do odczytu.
- Spisany kontrakt do przeczytania Format bloków ma własną specyfikację, a typy na froncie są generowane ze schematu backendu. Narzędzie AI edytujące podstronę pracuje na tym samym dokumencie co programista.

Od zmiany do strony na produkcji
- Krok 1
Ktoś wprowadza zmianę
Redaktor przestawia bloki i poprawia teksty w panelu — albo narzędzie AI podmienia jeden blok przez MCP. Te same dane, ta sama walidacja.
- Krok 2
Zapis jako treść o strukturze
Bloki idą do bazy jako typowany JSON, osobno dla każdego języka, każdy z trwałym id. Nic nie jest zapisywane jako gotowy HTML, więc tę samą treść można później wyrenderować inaczej.
- Krok 3
Publikacja kolejkuje build
Panel wprost mówi, że produkcja jest starsza niż treść, a jeden przycisk uruchamia przebudowę.
- Krok 4
Strona pyta API o swoje podstrony
Statyczny build loguje się własnym poświadczeniem i pobiera gotowe podstrony — z blokami i rozwiązanymi referencjami — w jednym przebiegu.
- Krok 5
Nowy build wchodzi na produkcję
Redaktorzy widzą kolejno: w kolejce → budowanie → wydane, a poprzednie wydanie zostaje, żeby dało się na nie wrócić.
Przebudowa trwa od 10 do 20 sekund. Ta liczba sprawia, że „to opublikujmy” jest zdaniem, które można powiedzieć klientowi od ręki, a nie tematem do ustalenia na później — a panel trzyma historię, więc powrót na dowolne wcześniejsze wydanie to jeden przycisk.

Odwiedzający dostaje na końcu stronę statyczną: HTML, CSS i obrazki z CDN-u. Żadnego zapytania do bazy, żadnego procesu PHP, nic, do czego można się zalogować. Treść mieszka w panelu, publiczna strona jest jej migawką.
Ponieważ kontraktem między jednym a drugim jest zwykły JSON po HTTP, front też nie jest zabetonowany. Dziś renderuje go Astro; strona w Next.js, Nuxcie czy SvelteKicie korzystałaby z dokładnie tych samych endpointów, a backend nie musiałby się zmienić.
Uruchomienie nowej strony
Dodanie klienta to jeden formularz. Wszystko po nim dzieje się w tle, jako łańcuch kroków, z których każdy da się powtórzyć osobno: repozytorium, aplikacja na serwerze, podpięcie wdrożeń z gita, certyfikat. Panel pokazuje, na którym kroku jest, zamiast jednego „udało się / nie udało”, a nieudany przebieg można wznowić bez dublowania tego, co już powstało.
Moja rola
Jestem głównym autorem systemu: wielofirmowego modelu treści, silników bloków i kolekcji, panelu w Filamencie, warstw REST i MCP, łańcucha uruchamiania klientów, procesu obróbki obrazów i pakietu Astro, z którego budowane są strony klientów. W pierwszych dziesięciu tygodniach weszło około 1900 commitów, w większości moich, przy niewielkim zespole i code review na każdym pull requeście.
Efekt
- Jeden backend, wiele stron Aktualizacja bezpieczeństwa, nowy typ bloku albo nowa funkcja panelu trafiają od razu na wszystkie strony, zamiast być powtarzane instalacja po instalacji.
- Na publicznej domenie nie ma czego atakować Żadnego CMS-a, bazy ani formularza logowania na stronie klienta — tylko statyczny build.
- AI w procesie, a nie obok niego Treść może szkicować, poprawiać i publikować asystent AI pracujący bezpośrednio na CMS-ie, na tych samych uprawnieniach co człowiek.
Technologie
Laravel
Framework, na którym stoi cały backend — model treści, kolejka, API, uruchamianie klientów i wdrożenia.
Filament
Warstwa panelu. Kreator stron to jego komponent Builder, sterowany w całości konfiguracją.
MariaDB
Treść, tłumaczenia, metadane mediów i ustawienia każdego klienta, z każdym zapytaniem ograniczonym do jednego najemcy.
Astro + TypeScript
Statyczne frontendy. Typy bloków są generowane ze schematu backendu, więc obie strony nie mogą się rozjechać.
REST API
Warstwa odczytu używana przy budowaniu stron, opisana w OpenAPI i uwierzytelniana osobno dla każdego klienta.
MCP
82 narzędzia odwzorowujące API dla asystentów AI, z pozwoleniami per poświadczenie i limitami na tych kosztownych.




