Startify
Wszystkie artykuły
  • AI
  • Proces
  • Next.js

Jak zbudowałem nową startify.space z pomocą AI — od Figmy i Framera do Next.js na własnym serwerze

Od audytu starej strony, przez podział pracy między Codex i Claude Code, testy i wersje językowe, po staging, domenę i Google Analytics.

Autor: Mateusz Madura

Niezależny Product Designer · LinkedIn (otwiera się w nowej karcie)

18 min czytania

Kiedy pokazałem nową wersję swojej strony, pod postem na LinkedInie (otwiera się w nowej karcie) pojawił się komentarz: „Fajna stronka! A miałbyś ochotę opisać gdzieś ten proces żeby się coś z tego poduczyć? ;)”. Ten komentarz dobrze podsumował problem z większością opowieści o AI coding: pokazujemy efekt, ale rzadko cały proces.

Nowa startify.space nie powstała po wpisaniu jednego promptu. Nie zaczęła się też od pustej kartki. Miałem działającą stronę we Framerze, projekt w Figmie, bibliotekę materiałów, kilka lat projektów do pokazania i bardzo konkretną wizję tego, jak całość ma wyglądać. Brakowało mi natomiast niezależnego, rozwijalnego wdrożenia, porządnego repozytoriumMiejsce, w którym Git przechowuje pliki projektu razem z pełną historią zmian. Zdalna kopia, np. na GitHubie, chroni pracę i ułatwia współpracę., testów, wersji polskiej i angielskiej oraz procesu, w którym AI nie tylko pisze kod, lecz także pomaga go kontrolować.

Przede wszystkim chciałem mieć swobodę dalszej rozbudowy strony. Figma i działająca strona we Framerze były źródłami obecnego rozwiązania, ale nie chciałem, żeby każda kolejna zmiana wymagała najpierw zaprojektowania jej w Figmie, a potem złożenia we Framerze. Chciałem samodzielnie i elastycznie dodawać artykuły, case studies i kolejne funkcje bezpośrednio w repozytorium.

Do pracy wykorzystałem dwa narzędzia: OpenAI Codex oraz Claude Code. Nadałem im różne role, a sobie zostawiłem wszystkie decyzje produktowe i zgodę na publikację. To rozdzielenie okazało się ważniejsze niż wybór konkretnego modelu.

Ten tekst jest opisem całego procesu: od audytu starej strony i pomiarów projektu, przez podział pracy między agentów, implementację, testy i wersje językowe, aż po stagingTestowa kopia strony na prawdziwym serwerze, niewidoczna dla odwiedzających i wyszukiwarek. Pozwala sprawdzić wydanie, zanim trafi pod właściwą domenę., konfigurację serwera, domenę i Google Analytics. Jest też instrukcją, którą można zaadaptować do własnego projektu.

Najpierw ustaliliśmy, kto za co odpowiada

Największym błędem byłoby potraktowanie dwóch agentów AINarzędzie AI, które nie tylko odpowiada na pytania, ale samo wykonuje zadania: czyta pliki projektu, zmienia kod i uruchamia polecenia. W tym projekcie agentami były Codex i Claude Code. jak dwóch developerów, którzy jednocześnie zmieniają te same pliki. To szybka droga do konfliktów, utraty kontekstu i zmian, których nikt nie potrafi później wyjaśnić.

Dlatego podzieliliśmy odpowiedzialność na trzy role:

RolaOdpowiedzialność
Ja — właściciel produktuUstalam cele i priorytety, oceniam wygląd i treść, rozstrzygam niejednoznaczności oraz wyrażam zgodę na push, merge, wdrożenie i zmiany w domenie.
Codex — koordynatorkaAnalizuje stan repozytorium, rozpisuje zadania, pilnuje zakresu, dokumentuje punkt bazowy, przegląda przekazania, prowadzi testy i zgłasza ryzyka.
Claude Code — główny developerImplementuje jasno wydzielone zadania na osobnych gałęziach i oddaje wynik wraz z kompletnym raportem.
  1. Mateusz ustala cel
  2. Codex przygotowuje brief
  3. Claude implementuje
  4. Codex przegląda
  5. Mateusz podejmuje decyzję
Cykl jednego zadania: od celu do decyzji właściciela.

Każde zadanie przechodziło przez ten sam cykl:

  1. Codex przygotowywał brief: cel, wykonawca, bazowy commitZapisany w historii Git stan zmian w plikach, z opisem i autorem. Commit bazowy to punkt wyjścia zadania: z nim porównuje się wynik., dozwolone pliki, rzeczy wyłączone z zadania, kryteria akceptacji i wymagane testy.
  2. Wykonawca sprawdzał aktualny stan repozytorium i potwierdzał, że zaczyna z czystego drzewaStan, w którym lokalna kopia projektu nie ma żadnych zmian niezapisanych w Git. Start z czystego drzewa daje pewność, że do zadania nie trafią przypadkowe poprawki..
  3. Praca trafiała na osobną gałąźOsobna linia zmian w repozytorium Git. Każde zadanie powstawało na własnej gałęzi, więc nie mieszało się z inną pracą, dopóki nie zostało zaakceptowane..
  4. Agent realizował wyłącznie uzgodniony zakres.
  5. Po implementacji uruchamiał testy i wykonywał manualne QA.
  6. Wynik kończył się lokalnym commitem oraz raportem przekazania.
  7. Codex porównywał wynik z briefem i bazą.
  8. Dopiero ja decydowałem: akceptujemy, poprawiamy czy odrzucamy. PushWysłanie lokalnych commitów do zdalnego repozytorium, np. na GitHub. Od tej chwili zmiany widzą inni i może je przejąć automatyzacja., mergePołączenie zmian z jednej gałęzi z inną, zwykle z główną wersją projektu. W tym procesie merge wymagał osobnej zgody właściciela. i wdrożenie zawsze wymagały osobnej zgody.

To zmienia sposób pracy z AI. Zamiast promptu „zrób stronę” mamy małe, sprawdzalne kontrakty.

Szablon briefu, który możesz skopiować

Brief
Cel:
Wykonawca:
Gałąź:
Commit bazowy:

Zakres do wykonania:
Dozwolone pliki lub obszary:
Poza zakresem:

Kryteria akceptacji:
Wymagane testy automatyczne:
Wymagane QA manualne:

Nie podejmuj dodatkowych decyzji produktowych.
Jeżeli źródła są sprzeczne, opisz rozbieżność i zatrzymaj się.
Nie wykonuj pushu, merge’a ani wdrożenia bez osobnej zgody.

Krok 1. Zanim napisaliśmy kod, zrobiliśmy audyt źródeł

Punktem wyjścia nie był jeden idealny projekt. Informacje były rozłożone pomiędzy:

  • działającą stroną startify.space we Framerze,
  • plikiem Figmy z projektem desktopowym,
  • materiałami graficznymi i fontami,
  • moimi uwagami i decyzjami podejmowanymi w trakcie pracy,
  • a później także dokumentacją i historią Git.

Musieliśmy ustalić hierarchię. Figma była bardzo dobrym źródłem geometrii dla widoku 1920 px i oryginalnych assetów. Działająca strona była natomiast lepszym źródłem zachowania, responsywności i interakcji. Jeżeli projekt i wdrożenie się różniły, nie zgadywaliśmy. Różnicę opisywaliśmy i podejmowałem decyzję.

Audyt objął na początku pięć istniejących adresów: stronę główną, menu, Pssst, case study oraz Shots. Rozpisaliśmy osiem sekcji strony głównej, zinwentaryzowaliśmy obrazy, SVG, animacje, fonty i analitykę. Sprawdziliśmy również breakpointySzerokość ekranu, przy której zmienia się układ strony, np. z jednej kolumny na dwie. W tym artykule to m.in. progi 810, 1280 i 1920 px. generowane przez Framera.

Figma zawierała pełny projekt tylko dla szerokości 1920 px. Tablet i mobile musieliśmy odtworzyć na podstawie istniejącego wdrożenia. To ważna lekcja: responsywność nie wynika automatycznie z desktopowego ekranu w Figmie.

Docelowo przyjęliśmy cztery poziomy układu:

  • mobile do 809 px,
  • tablet 810–1279 px,
  • desktop 1280–1919 px,
  • desktop XL od 1920 px.

Próg 1500 px pozostał dodatkowym punktem zmiany bardziej złożonego układu i nawigacji. Nie wymyśliliśmy go „na oko” — wynikał z zachowania strony we Framerze.

Typografia wymagała małego śledztwa

W Figmie pojawiały się nazwy Neue Montreal i PP Neue Montreal. To nie są identyczne kroje. Porównaliśmy metryki plików fontów z tym, co rzeczywiście serwował Framer: szerokości glifów, wysokość kapitalików, x-height, wagę i liczbę znaków.

Wynik był jednoznaczny: strona korzystała z Neue Montreal w wydaniu z 2018 roku, a nie z PP Neue Montreal. Gdybyśmy wybrali krój tylko na podstawie podobnej nazwy, zmieniłoby się łamanie niemal każdej linii.

Następnie zmierzyliśmy rozmiary i interlinie na kilku szerokościach. Nie próbowaliśmy na siłę wyprowadzać wszystkiego z jednego matematycznego wzoru, bo oryginalne wdrożenie nie było idealnie systematyczne. Najpierw odtworzyliśmy stan faktyczny, a dopiero później wprowadzaliśmy świadome odstępstwa.

Mierzyliśmy stronę, ale musieliśmy też mierzyć sam pomiar

Framer utrzymywał część elementów w stanie sprzed animacji: z przezroczystością i przesunięciem, np. o 24 px w pionie. Standardowy pomiar pozycji w przeglądarce uwzględnia transformację, więc zwracał wartość inną niż prawdziwa pozycja w układzie.

Pierwsze pomiary hero były przez to błędne. Zamiast ukryć pomyłkę, zapisaliśmy ją w dokumentacji i zmieniliśmy metodę. Przy kolejnych sekcjach wyłączaliśmy na czas pomiaru transformacje, animacje i przejścia albo odejmowaliśmy znane przesunięcie.

To jeden z powodów, dla których AI potrzebuje dokumentacji. Agent może bardzo szybko zmierzyć sto elementów, ale jeżeli metoda jest zła, sto razy szybciej otrzymamy złe dane.

Krok 2. Zbudowaliśmy techniczny fundament

Stronę przepisaliśmy na aplikację w Next.jsFramework do budowania stron i aplikacji w React. Zapewnia m.in. trasy, generowanie stron na serwerze i build gotowy do publikacji. z Reactem i TypeScriptem. Interakcje bazowały na bibliotece Motion, bo podobny mechanizm odpowiadał za ruch w oryginalnej stronie. Style korzystały z Tailwinda oraz własnych arkuszy CSS i tokenów.

Końcowy udokumentowany zestaw obejmował:

  • Next.js 16.3.5,
  • React 19.3,
  • TypeScript 6.0.3,
  • Tailwind CSS 4.3.3,
  • Motion 13.4,
  • PlaywrightNarzędzie do automatycznego testowania stron w prawdziwych przeglądarkach: klika, przewija, wpisuje tekst i sprawdza wynik tak jak użytkownik. do testów przeglądarkowych,
  • axe do automatycznego audytu części reguł dostępności.

Nie zaczynaliśmy od abstrakcyjnego design systemu. Najpierw wydobyliśmy system, który już istniał w projekcie: kolory, typografię, moduły siatki, obramowania, odstępy, przyciski i breakpointy.

Powstała siatka 16 kolumn oraz trzy podstawowe marginesy zewnętrzne: 24 px na mobile, 40 px na tablecie i 80 px na desktopie. Treści i projekty oddzieliliśmy od komponentów. Dane realizacji zasilały zarówno listę na stronie głównej, jak i nawigację poprzedni/następny w case studies.

Struktura projektu miała jasny podział:

Kod
app/          trasy i layouty
components/   komponenty współdzielone, sekcje i bloki case studies
dane/         treści, projekty, opinie, shoty i słowniki
public/       obrazy, SVG, fonty i wideo
docs/         pomiary, decyzje i przekazania
tests/        testy jednostkowe oraz przeglądarkowe

Najpierw commit bazowy, potem szybka praca

Po kilku dniach pierwszej implementacji odkryliśmy poważne ryzyko: cały projekt istniał lokalnie bez jednego commita i bez zdalnego repozytorium. Nie było więc bezpiecznej bazy porównania, informacji o autorstwie zmian ani prostego powrotu do wcześniejszego stanu.

Zatrzymaliśmy rozwój i utworzyliśmy punkt bazowy. Do prywatnego repozytorium GitHub trafił kod, dokumentacja i materiały, w tym wideo, ponieważ największy plik mieścił się w granicach zwykłego Gita. Dopiero od tego momentu mogliśmy bezpiecznie prowadzić osobne gałęzie, przeglądy i przekazania.

Następnie przypięliśmy wersje zależności, naprawiliśmy lintowanieAutomatyczne sprawdzanie kodu pod kątem błędów i niespójności stylu, bez uruchamiania strony. To jedna z pierwszych bramek przed buildem. dla aktualnego Next.js i dodaliśmy CICiągła integracja (Continuous Integration): automat, który przy każdej zmianie w repozytorium sam uruchamia kontrole, np. lint, build i testy, i zgłasza błędy.. Instalacja została oparta na lockfilePlik z dokładnymi wersjami wszystkich pakietów, z których korzysta projekt. Dzięki niemu komputer, agent i serwer instalują dokładnie ten sam zestaw., tak aby lokalna maszyna, agent i serwer CI otrzymywały ten sam zestaw paczek.

Krok 3. Odtwarzaliśmy stronę sekcja po sekcji

Nie prosiliśmy AI o napisanie całej strony jednocześnie. Każda sekcja miała osobny etap pomiaru, implementacji i porównania.

W hero odtworzyliśmy zależność pomiędzy kolumną tekstową, portretem i charakterystycznymi liniami. Portret miał przezroczyste tło, więc nie można go było przekonwertować do JPEG. Ważne było także rozdzielenie obrazu od kadru: to kontener przycinał zdjęcie, a nie object-fit rozciągający sam obraz.

Pierwszy ekran strony głównej: po lewej nagłówek „Niezależny Product Designer” i opis usług, po prawej portret Mateusza Madury na tle poziomych linii
Hero nowej startify.space w szerokości 1920 px: kolumna tekstowa, portret i charakterystyczne linie.

W kolejnych sekcjach odtwarzaliśmy rzeczywistą strukturę: szerokości kolumn, rytm kart, listę kompetencji, testimonials, siatkę projektów, proces, sekcję o mnie, logotypy klientów i stopkę. Dla każdego breakpointu sprawdzaliśmy nie tylko rozmiar fontu, ale także zmianę kierunku układu, kolejność elementów, widoczność opisów i sposób kadrowania grafik.

Nie wszystkie elementy odwzorowaliśmy bez zmian. Przykładowo hero dostał minimalną wysokość ekranu, żeby portret dochodził do dolnej krawędzi także przy nietypowych proporcjach okna. To była decyzja produktowa, a nie przypadkowa „poprawka” agenta. Każde odejście od starej strony było opisane.

Case studies wymagały innego podejścia

Zbudowaliśmy wspólny model bloków dla case studies: otwarcie, cel, rozdziały, galerie, pełnoekranowe grafiki, podsumowanie, kredyty i nawigację do kolejnych projektów. Dzięki temu kolejne realizacje nie były osobnymi, ręcznie sklejanymi stronami, tylko danymi renderowanymi przez wspólny szablon.

Tutaj pojawiła się jedna z ciekawszych pułapek Figmy. Eksport bardzo wysokiej ramki był ograniczany do 4096 px w dłuższym wymiarze. Jednopikselowe linie po takim przeskalowaniu zmieniały się w linie grubości ponad 5 px. Problem występował zarówno w PNG, jak i w SVG.

Rozwiązaniem był eksport do PDF, który zachowywał wektorową geometrię, a następnie kontrolowana rasteryzacja potrzebnych fragmentów. Zamiast ufać wysokościom warstw, analizowaliśmy też rzeczywiste granice widocznych sekcji, bo część ramek w Figmie nachodziła na siebie.

Assety nie były kopiowane bezmyślnie

Tam, gdzie to możliwe, braliśmy oryginały z Figmy i lokalnych materiałów, a nie zoptymalizowane kopie pobrane z CDNSieć serwerów rozmieszczonych po świecie, które szybko dostarczają pliki, np. obrazy. Framer serwował przez CDN zoptymalizowane kopie grafik, dlatego woleliśmy oryginały. Framera. Wyjątkiem były elementy, które istniały wyłącznie we wdrożeniu albo których zachowanie trzeba było odtworzyć z DOMStruktura strony, którą przeglądarka buduje z HTML i której używa do wyświetlania i skryptów. Z DOM odczytywaliśmy rzeczywiste rozmiary i zachowanie elementów działającej strony..

Każdy obraz miał sprawdzone proporcje, naturalny wymiar i zachowanie na kilku szerokościach. Dla filmów w Shots przygotowaliśmy lekkie postery. Same pliki wideo zaczynały się pobierać dopiero w pobliżu widoku i tylko wtedy, gdy użytkownik nie ograniczył animacji. Miniatury można było zatrzymać, a dialog z filmem miał natywne sterowanie.

W efekcie próbka mobilnej strony Shots przy włączonym ograniczeniu ruchu spadła z około 23 MB do około 1,2 MB i nie uruchamiała filmów automatycznie.

Krok 4. Rozszerzyliśmy zakres poza kopię starej strony

Po odtworzeniu fundamentu zaczęliśmy rozwijać stronę. Powstały kolejne case studies, osobna lista realizacji, baza wiedzy, dopracowane interakcje i pełne wersje polska oraz angielska.

Wersje językowe działają pod /pl i /en. Neutralne wejście wybiera język na podstawie zapisanego wyboru lub preferencji przeglądarki, ale jawne adresy językowe nigdy nie przekierowują użytkownika wbrew jego decyzji. Przełącznik prowadzi do odpowiednika tej samej podstrony i zachowuje kotwicę sekcji.

Treści interfejsu trafiły do osobnych słowników, a dane case studies otrzymały pary polska/angielska. Dodaliśmy również:

  • lokalizowane tytuły i opisy,
  • canonicaleZnacznik w kodzie strony, który wskazuje wyszukiwarce jej główny, właściwy adres. Pomaga, gdy ta sama treść jest dostępna pod kilkoma adresami.,
  • hreflangZnacznik, który informuje wyszukiwarkę, że strona ma wersje w innych językach i pod jakimi adresami są. Łączy polski i angielski odpowiednik tej samej podstrony. dla PL, EN i x-default,
  • sitemapę,
  • zlokalizowane strony 404,
  • noindexInformacja dla wyszukiwarek, żeby nie dodawały strony do wyników wyszukiwania. Tu dostały ją m.in. techniczne menu, strony błędu i staging. dla technicznego menu i stron błędu,
  • mapę przekierowań ze starych adresów Framera,
  • obraz Open Graph 1200 × 630 dla podglądów w social mediach.

Stare adresy prowadziły do angielskich odpowiedników, bo taką treść prezentowała poprzednia strona. Przed publikacją sprawdziliśmy mapę istniejących URL-i, zamiast zakładać, że nikt już do nich nie linkuje.

Krok 5. Testy stały się częścią implementacji

W AI coding bardzo łatwo zachwycić się tempem generowania zmian. Problem pojawia się wtedy, gdy każdy kolejny prompt naprawia jedną rzecz i psuje dwie inne. Dlatego z czasem zbudowaliśmy kilka warstw kontroli.

Podstawowa bramka obejmowała:

Bash
npm run lint
npm run typecheck
npm test
npm run build

Do tego doszły testy Playwright w Chromium i WebKit. Sprawdzały nawigację, menu, wersje językowe, przekierowania, zachowanie formularzy i przycisków, dialog Shots, obsługę klawiatury, preferencję ograniczonego ruchu, brak poziomego scrolla i stan obrazów.

Utworzyliśmy wzorce wizualne dla kluczowych widoków na szerokościach granicznych, m.in. 390, 809, 810, 1279, 1280, 1499, 1500, 1700 i 1920 px. Dzięki temu testowaliśmy nie tylko „telefon, tablet, desktop”, ale również piksel przed i po zmianie breakpointu.

Przed publikacją powstał osobny audyt obejmujący publiczne trasy w dwóch wersjach językowych, obrazy, błędy JavaScript, statusy HTTP, metadane, poziome przewijanie i automatyczne reguły axe. Testy nie zastępowały oceny człowieka, ale zamieniały wiele powtarzalnych kontroli w stałą bramkę.

Pierwszy audyt wykrył m.in. zbyt niski kontrast części szarych tekstów, ciężkie filmy i problemy ze sterowaniem autoplay. Poprawiliśmy kolory, sposób ładowania multimediów i zachowanie przy prefers-reduced-motion, a potem ponowiliśmy pełny zestaw kontroli.

W jednym z etapów związanych z analityką build wygenerował 30 stron, 15 testów jednostkowych przeszło pomyślnie, a 156 testów przeglądarkowych w Chromium i WebKit zakończyło się wynikiem pozytywnym. Nie oznacza to „idealnej strony” ani pełnej zgodności WCAGMiędzynarodowe wytyczne dostępności treści internetowych. Opisują m.in. kontrast, obsługę klawiaturą i teksty dla czytników ekranu.. Oznacza, że mieliśmy powtarzalny dowód dla konkretnie opisanych zachowań.

Krok 6. Najpierw staging, dopiero potem domena

Docelowy hosting działał w cyber_Folks. Aplikacja nie była statycznym eksportem. Uruchamialiśmy Next.js jako aplikację Node 22 zarządzaną przez Phusion PassengerOprogramowanie na serwerze hostingu, które uruchamia aplikację Node.js, pilnuje jej procesu i przekazuje do niej ruch z przeglądarek..

Zaczęliśmy od odizolowanego stagingu na technicznej domenie. Katalog aplikacji leżał poza public_html, a dostęp był chroniony Basic AuthNajprostsza ochrona strony hasłem, wbudowana w przeglądarki: przed wejściem pojawia się okno logowania. Tu zamykała staging przed przypadkowymi odwiedzającymi.. Staging otrzymał dodatkowy nagłówek X-Robots-Tag: noindex, nofollow, noarchive, żeby przypadkowo nie wejść do indeksu.

Przygotowaliśmy dwa osobne launcheryMały plik startowy, który uruchamia aplikację na serwerze i wskazuje, którą wersję strony ma serwować. Osobne launchery pozwalały inaczej skonfigurować staging i produkcję.:

  • stagingowy, który zawsze dodawał ochronę przed indeksowaniem,
  • produkcyjny, bez globalnego noindex.

Launcher jawnie konfigurował Passenger z wyłączoną automatyczną instalacją serwera HTTP i nasłuchiwał przez mechanizm Passenger. To drobny detal, ale bez niego framework mógł przejąć niewłaściwy serwer tworzony w procesie.

Jak wyglądało wydanie na serwer

  1. Przygotowywaliśmy paczkę wyłącznie ze śledzonych źródeł i launchera. Bez .env, .git, node_modules, cache, logów i konfiguracji lokalnych.
  2. Paczka trafiała do nowego katalogu wydania, a przed rozpakowaniem sprawdzaliśmy sumę SHA-256 i listę plików.
  3. Zachowywaliśmy kopię dotychczasowego launchera, .htaccess i mapowania aplikacji, aby rollbackPowrót do poprzedniej, działającej wersji po nieudanym wydaniu. Tu wystarczało przywrócić poprzedni launcher, bez ponownego budowania strony. nie zależał od ponownego budowania.
  4. Zależności instalowaliśmy na serwerze z lockfile. Nie kopiowaliśmy node_modules z macOS na Linux.
  5. Build wykonywaliśmy na hostingu. W praktyce sprawdził się build przez WebpackNarzędzia, które podczas buildu łączą i optymalizują kod strony w wersję gotową do publikacji. W Next.js domyślny jest Turbopack, ale na hostingu sprawdził się Webpack.; domyślny Turbopack natrafiał na ograniczenia środowiska.
  6. Dopiero po udanym buildzie wydanie było podłączane do Passenger i restartowane.
  7. Przed zmianą domeny sprawdzaliśmy PL, EN, case studies, media, przekierowania, 404, nagłówki oraz dostęp do zasobów Next.js.

Na hostingu pojawiło się jeszcze jedno ograniczenie: kompilacja potrafiła zakończyć się błędem tworzenia puli wątków (EAGAIN). Ograniczyliśmy więc liczbę wątków i puli roboczych dla procesu budowania. To nie była „optymalizacja kodu”, tylko dostosowanie procesu do limitów współdzielonego hostingu.

Domena, HTTPS i droga powrotu

Przed przełączeniem produkcji chcieliśmy potwierdzić aplikację na docelowym hoście bez publicznej zmiany DNSSystem, który zamienia nazwę domeny, np. startify.space, na adres serwera. Zmiana rekordów DNS decyduje, który serwer odpowiada pod danym adresem.. Do tego służy test HTTPS wymuszający konkretny adres IP przy zachowaniu prawidłowej nazwy domeny i certyfikatu.

Pierwsza próba publikacji została cofnięta, ponieważ narzędzie na hostingu nie potrafiło poprawnie zweryfikować łańcucha TLSProtokół, który szyfruje połączenie; to on stoi za literą „S” w HTTPS. Łańcuch certyfikatów TLS potwierdza, że serwer naprawdę należy do danej domeny.. Nie obeszliśmy problemu flagą wyłączającą weryfikację. Sprawdziliśmy jawny plik certyfikatów CA i zachowaliśmy zasadę: jeżeli HTTPS nie przechodzi prawidłowej walidacji, nie przełączamy ruchu.

Plan zmiany DNS był celowo wąski: zmienić tylko rekord kierujący ruch WWW, pozostawiając bez zmian serwery nazw, pocztę, rekordy TXT i subdomenę developerską. Stara strona we Framerze i poprzednie rekordy pozostawały drogą powrotu. Nie podmienialiśmy całego public_html, bo znajdowały się tam również inne elementy infrastruktury.

Po przełączeniu www.startify.space jest rekordem CNAMERekord DNS, który mówi, że jedna nazwa domeny jest aliasem innej. Tu www.startify.space wskazuje na startify.space. wskazującym na startify.space, a oba adresy prowadzą do tego samego serwera i odpowiadają po HTTPS. Znacznik canonical na obu wariantach hosta wskazuje https://www.startify.space, a stare adresy Framera zostały objęte trwałymi przekierowaniami.

Krok 7. Google Analytics dopiero po zgodzie

Na starej stronie działał już strumień GA4Google Analytics 4, obecna wersja Google Analytics. Strumień GA4 to źródło danych o ruchu z jednej strony; tu wykorzystaliśmy istniejący strumień Startify.. Zamiast tworzyć nową usługę, wykorzystaliśmy istniejący strumień Startify i jego identyfikator pomiaru. Zachowaliśmy pomiar zaawansowany, a odsłony pozostawiliśmy mechanizmowi Google, bez ręcznego dublowania page_view przy każdej zmianie w React.

Analityka nie ładuje się automatycznie. Domyślny stan to brak zgody. Dopóki użytkownik nie zaakceptuje kategorii Analytics:

  • skrypt GA nie jest dodawany,
  • nie ma preconnect do Google,
  • przeglądarka nie wysyła pingów analitycznych.

Panel zgody jest dwujęzyczny i oferuje odmowę, dostosowanie oraz akceptację. Wybór jest zapisywany lokalnie na 180 dni. Błąd odczytu, brak dostępu do storage albo wygaśnięcie wyboru oznacza brak zgody, a nie zgodę domyślną.

Użytkownik może później wrócić do ustawień w stopce. Wycofanie zgody usuwa cookies _ga i _ga_*, wyłącza analitykę i przeładowuje dokument, aby usunąć aktywne listenery zewnętrznego skryptu. Stan synchronizuje się pomiędzy kartami.

Dodatkowo ograniczyliśmy wysyłanie danych do startify.space i www.startify.space. Localhost oraz staging nie wysyłają danych nawet po kliknięciu zgody. Google Signals i personalizacja reklam pozostały wyłączone, a zgody reklamowe ustawione jako odrzucone.

Testy analityki korzystały z atrapy Google. Sprawdzały obie wersje językowe, brak połączeń przed zgodą, akceptację, odmowę, odświeżenie, wycofanie, czyszczenie cookies, wygasłą zgodę, zablokowany storage, synchronizację pomiędzy kartami i wykluczenie localhosta.

Co w tym procesie faktycznie zrobiło AI

AI nie zaprojektowało za mnie marki i nie zdecydowało, co powinienem pokazywać klientom. Nie dostało też prawa do samodzielnego publikowania zmian.

Codex i Claude pomagały w czterech rodzajach pracy:

  1. Analiza — inwentaryzacja stron, pomiary DOM, porównywanie Figmy z wdrożeniem, analiza fontów, assetów i historii zmian.
  2. Implementacja — komponenty, style, modele danych, wersje językowe, testy, launchery serwera i analityka.
  3. Kontrola — lint, typy, build, testy przeglądarkowe, wizualne i dostępnościowe, sprawdzanie zakresu zadania oraz raportowanie rozbieżności.
  4. Pamięć projektu — dokumentowanie decyzji, błędów, punktów bazowych, ryzyk i sposobów odtworzenia pracy.

Największa przewaga nie polegała na tym, że kod powstawał szybciej. Ważniejsze było to, że mogliśmy przeanalizować więcej wariantów, zapisać więcej wiedzy i automatyzować kontrole, które przy jednoosobowym projekcie łatwo pominąć.

Jednocześnie każdy moment, w którym AI otrzymywało zbyt szeroki zakres, zwiększał ryzyko. Dlatego im szybciej narzędzie potrafi pracować, tym ważniejsze stają się granice, historia zmian i testy.

Jak powtórzyć ten proces we własnym projekcie

Poniższa kolejność jest ważniejsza niż konkretny framework.

  1. Określ role i uprawnienia

    Zapisz, kto podejmuje decyzje produktowe, kto koordynuje, kto implementuje i kto może publikować. Jeżeli pracujesz z kilkoma agentami, nie pozwalaj im bez koordynacji zmieniać tych samych plików.

    Rezultat: krótki plik zasad w repozytorium.

  2. Zbuduj mapę źródeł prawdy

    Wypisz wszystkie źródła: produkcję, Figmę, treści, assety, analitykę, domenę i decyzje właściciela. Dla każdego określ, czemu ufamy: wyglądowi, zachowaniu, treści czy historii.

    Rezultat: audyt tras, sekcji, fontów, breakpointów, assetów, integracji i otwartych decyzji.

  3. Zabezpiecz stan przed rozwojem

    Utwórz repozytorium, pierwszy commit i zdalną kopię. Nie rozpoczynaj pracy kilku agentów na zbiorze nieśledzonych plików.

    Rezultat: jednoznaczny commit bazowy i czyste drzewo.

  4. Wydobądź system z projektu

    Zanim zbudujesz pełne widoki, zapisz tokeny kolorów, typografię, siatkę, marginesy, breakpointy, przyciski, linie i zasady kadrowania mediów.

    Rezultat: mały zestaw wspólnych prymitywów zamiast setek lokalnych poprawek.

  5. Implementuj pionowymi fragmentami

    Wybierz jedną sekcję lub trasę. Zmierz, zaimplementuj, porównaj na kilku szerokościach i dopiero wtedy przejdź dalej. Zapisuj pułapki pomiarowe.

    Rezultat: każdy etap można zaakceptować albo cofnąć niezależnie.

  6. Oddziel treść od komponentów

    Projekty, teksty, tagi i galerie trzymaj w modelu danych. Ten sam komponent powinien umieć wyrenderować kolejne case studies bez kopiowania całej strony.

    Rezultat: prostsze wersje językowe i mniej niespójności.

  7. Dodaj testy zanim zaczniesz „szlifować”

    Minimum to lint, typy i build. Dla ważnych interakcji dodaj testy przeglądarkowe. Dla layoutu sprawdzaj szerokości po obu stronach breakpointu, nie tylko popularne urządzenia.

    Rezultat: kolejny prompt nie cofa niepostrzeżenie wcześniejszej decyzji.

  8. Potraktuj SEO, dostępność i multimedia jako część produktu

    Sprawdź metadane, canonicale, języki, przekierowania, 404, kontrast, klawiaturę, ograniczenie ruchu, rozmiar obrazów i moment ładowania filmów.

    Rezultat: strona jest czymś więcej niż ładnym screenshotem.

  9. Zbuduj staging z rollbackiem

    Wydania umieszczaj w nowych katalogach. Zachowuj launcher i konfigurację poprzedniej wersji. Chroń staging hasłem i noindex. Buduj zależności w docelowym systemie operacyjnym.

    Rezultat: awaria builda nie wyłącza działającej strony.

  10. Oddziel publikację od zmiany DNS

    Najpierw uruchom i sprawdź aplikację na docelowym serwerze. Potem zweryfikuj HTTPS dla prawdziwej domeny bez publicznego przełączenia. Dopiero na końcu zmień minimalny zakres rekordów DNS.

    Rezultat: domena nie jest narzędziem do testowania niesprawdzonego wydania.

  11. Analitykę uruchamiaj świadomie

    Sprawdź, czy korzystasz z istniejącego strumienia, jakie zdarzenia są automatyczne i czy nie dublujesz odsłon. Nie ładuj zewnętrznego skryptu przed zgodą, jeżeli Twój model prywatności jej wymaga. Wyklucz staging i localhost.

    Rezultat: czyste dane i mniej przypadkowych naruszeń prywatności.

Prompty, które są lepsze niż „zrób mi stronę”

Prompt do audytu

Prompt
Przeanalizuj istniejącą stronę i projekt, ale nie pisz jeszcze kodu.
Przygotuj listę tras, sekcji, komponentów, fontów, kolorów,
breakpointów, assetów, interakcji, integracji i otwartych decyzji.

Dla każdego ustalenia podaj źródło: produkcja, Figma, materiał lokalny
albo decyzja właściciela. Jeżeli źródła się różnią, nie wybieraj
samodzielnie. Opisz rozbieżność i jej wpływ.

Prompt do implementacji sekcji

Prompt
Zaimplementuj wyłącznie sekcję [nazwa] na bazie commita [SHA].
Dozwolone pliki: [lista]. Poza zakresem: treść, inne sekcje, hosting.

Odtwórz układ dla szerokości [lista] oraz zachowanie na granicach
breakpointów. Nie zgaduj brakujących wartości. Każdą świadomą różnicę
względem wzorca opisz.

Na końcu uruchom [lista testów] i oddaj raport: zmienione pliki,
wyniki kontroli, QA manualne, ryzyka i stan drzewa roboczego.

Prompt do przeglądu

Prompt
Porównaj wynik z briefem i commitem bazowym. Szukaj regresji, zmian poza
zakresem, niepotwierdzonych założeń, problemów responsywnych, dostępności,
SEO i wydajności. Nie poprawiaj kodu. Najpierw przedstaw ustalenia według
ważności wraz z konkretnym dowodem i proponowanym sposobem weryfikacji.

Najważniejsze lekcje

AI coding nie usuwa potrzeby zarządzania projektem. Przeciwnie: kiedy implementacja przyspiesza, coraz ważniejsze staje się precyzyjne określenie zakresu i odpowiedzialności.

Działająca strona jest osobnym źródłem wiedzy. Figma pokazuje intencję, ale nie zawsze zawiera wszystkie breakpointy, stany, animacje i kompromisy wdrożenia.

Pomiar też może być błędny. Animacje, ukryte warianty i ograniczenia eksportu potrafią wygenerować bardzo wiarygodne, ale fałszywe dane.

Dokumentacja to pamięć zespołu agentów. Czat pomaga pracować, ale dopiero commit, plik z decyzjami i raport przekazania pozwalają bezpiecznie kontynuować projekt.

Testy nie są etapem po kodowaniu. Są sposobem prowadzenia kolejnych zmian bez ciągłego wracania do punktu wyjścia.

Wdrożenie jest częścią produktu. Serwer, certyfikat, DNS, przekierowania, staging, rollback i analityka mają taki sam wpływ na efekt jak komponenty Reacta.

Czy zrobiłbym to jeszcze raz w ten sam sposób?

Tak, ale z jedną zmianą: repozytorium, punkt bazowy, zasady ról i podstawowe testy utworzyłbym pierwszego dnia, przed pierwszą dużą porcją implementacji.

Sam pomysł połączenia dwóch agentów sprawdził się bardzo dobrze, ponieważ nie próbowali robić tego samego. Jeden pomagał prowadzić proces i kontrolować rezultat, drugi realizował jasno wydzielone zadania, a ja pozostawałem osobą odpowiedzialną za produkt.

Nowa startify.space jest więc nie tyle „stroną zrobioną przez AI”, ile stroną zbudowaną w nowym modelu współpracy. AI pisało kod, analizowało, testowało i dokumentowało. Ja nadawałem kierunek, oceniałem i podejmowałem decyzje.

I chyba właśnie to jest najciekawsza odpowiedź na pytanie z komentarza, od którego zaczął się ten tekst.

Pojęcia z tego artykułu, wyjaśnione prostym językiem

Mateusz MaduraNiezależny Product Designer

Porozmawiajmy dalej na LinkedInie

Publikuję tam krótsze obserwacje o projektowaniu, AI i budowaniu produktów.

Odwiedź mój profil (otwiera się w nowej karcie)

Udostępnij artykuł

Powiązane artykuły