Landing page · Shellcrew - produkt własny · 2026 · 1 dzień na landing, potem rozwijany

Shellcrew - landing z listą oczekujących dla narzędzia, którego jeszcze nie ma

Własne pliki strony głównej to sześć żądań i 39 kB. Zero webfontów, statystyki na własnym serwerze zamiast zewnętrznych trackerów i formularz, który zapisuje maila do własnej bazy, a nie do arkusza.

  • Astro
  • Tailwind
  • TypeScript
  • FastAPI
  • SQLite
  • Cloudflare Turnstile
  • Umami
  • Caddy
  • Docker
  • GitHub Actions
Zobacz stronę live ↗
Shellcrew - landing z listą oczekujących dla narzędzia, którego jeszcze nie ma

Wyzwanie

Produktu jeszcze nie ma. Jest pomysł: odpalać kilku agentów AI naraz na własnych plikach, bez terminala - dla ludzi, którzy nie programują. Zanim powstanie pierwsza wersja, trzeba sprawdzić, czy ktokolwiek tego chce, i mieć gdzie zbierać adresy. Landing sprzedający niebyt ma jeden sposób, żeby polec: obiecać za dużo i stracić zaufanie w dniu premiery.

Nasze rozwiązanie

Jedna podstrona w Astro, która tłumaczy działanie produktu na makietach interfejsu zamiast na obietnicach, i mówi wprost w FAQ, że produktu jeszcze nie ma. Zapisy idą do własnego API (FastAPI + SQLite) na tym samym VPS-ie co reszta - z honeypotem, limitem na IP i mailem do właściciela przy każdym nowym adresie. Bez webfontów, bez zewnętrznych trackerów, bez zewnętrznego narzędzia do newslettera.

6

Żądań do własnych plików

39 kB

Waga własnych plików

0,2 s

Pierwsze renderowanie treści

4

Wpisów na blogu

Co zbudowaliśmy

  • 01 Landing jednostronicowy: hero, jak to działa, załoga agentów, pamięć projektu, tryby pracy, FAQ
  • 02 Makieta aplikacji zbudowana w HTML i CSS - nie zrzut ekranu, bo nie ma czego zrzucać
  • 03 Formularz zapisu z honeypotem, Cloudflare Turnstile, limitem na IP i globalnym limitem na godzinę
  • 04 Własne API zapisów: FastAPI na porcie 8002, SQLite poza katalogiem kodu
  • 05 Powtórny zapis tego samego maila kończy się sukcesem, nie błędem
  • 06 Powiadomienie mailem do właściciela przy każdym nowym adresie
  • 07 Przełączanie ekranów w sekcji „jak to działa" na samym CSS-ie (`:has()`), bez JS
  • 08 Czcionki systemowe - zero pobieranych webfontów
  • 09 Deploy z GitHub Actions na osobnym kluczu CI bez sudo
  • 10 Caddy: HSTS, nagłówki bezpieczeństwa, assety cache'owane na 30 dni
  • 11 Blog, strona o zespole i poradnik porównujący nakładki graficzne na Claude Code
  • 12 llms.txt, RSS, IndexNow i dane strukturalne pod wyszukiwarki i asystentów AI
  • 13 Statystyki na własnym Umami, fail2ban na błędne logowania do panelu
Spis treści +

Punkt wyjścia

Agenci do kodu - Claude Code, Codex - działają dobrze i są zamknięci w terminalu. To nie jest przypadek: zbudowano je dla programistów, którzy w terminalu i tak siedzą. Reszta ludzi, którzy mają realną robotę do zlecenia - poprawić formularz, przepisać stronę produktu, dodać tryb ciemny - odbija się od czarnego okna z migającym kursorem.

Shellcrew to próba zdjęcia tej bariery: kilku agentów naraz, każdy na własnej kopii projektu, wszystko widoczne zwykłym językiem, a terminal zostaje pod spodem i nikt nie musi go otwierać.

Problem w tym, że w dniu, w którym powstawał ten landing, produkt nie istniał. Była decyzja, jak ma działać, i nic więcej. Strona miała zrobić dwie rzeczy naraz: wytłumaczyć pomysł na tyle konkretnie, żeby ktoś zostawił adres, i nie skłamać ani razu - bo pierwsza rzecz, którą te same osoby zobaczą po premierze, to różnica między obietnicą a produktem.

Decyzje, które ukształtowały projekt

Makieta interfejsu zamiast zrzutów ekranu

Nie ma czego zrzucić, więc ekran aplikacji jest zbudowany w HTML i CSS jako część strony: lista zadań, wątek agenta, modal zatwierdzenia zmiany, podgląd na żywo. Kosztowało to więcej pracy niż wklejenie obrazka i ma dwie zalety - skaluje się na telefonie i nie udaje produkcyjnego zrzutu ekranu.

FAQ zaczyna się od „jeszcze nie”

Pierwsze pytanie brzmi „czy Shellcrew już istnieje?”. Odpowiedź: nie, jeszcze nie. Dalej: ile będzie kosztować (własne konto u dostawcy modelu, bez narzutu), czy trzeba umieć programować (nie), gdzie lądują klucze API (w lokalnym sejfie, nie na serwerze). Landing, który to ukrywa, zbiera więcej adresów i traci je wszystkie przy pierwszym mailu.

Własne API zapisów zamiast zewnętrznego newslettera

Zapis leci POST-em na /api/signup do FastAPI na tym samym VPS-ie. Adresy siedzą w SQLite poza katalogiem kodu, więc deploy przez rsync ich nie dotyka. Honeypot firma_www odsiewa boty, limit dziesięciu zapisów na IP na godzinę - resztę. Powtórzony adres kończy się komunikatem o sukcesie, a nie błędem „już jesteś na liście”: to informacja dla cudzej ciekawości, nie dla zapisującego.

Zero webfontów

Cała typografia stoi na krojach systemowych - SF Pro na Macu, Segoe UI na Windowsie, SF Mono w miejscach, gdzie tekst ma wyglądać na terminal. Landing przy ciemnej palecie i jednym akcencie (mięta #55d6c6) nic na tym nie traci, a zyskuje dwa żądania mniej i brak skoku tekstu przy wczytywaniu.

Przełączanie ekranów bez JavaScriptu

Sekcja „jak to działa” to akordeon z czterema krokami i makietą laptopa z telefonem obok. Zmiana kroku przełącza ekran w makiecie - na selektorze :has() w CSS-ie, bez ani jednej linii skryptu. To samo zachowanie w JS oznaczałoby hydratację komponentu tylko po to, żeby zmienić klasę.

Osobny klucz CI, bez sudo

VPS jest współdzielony z innymi projektami. Deploy z GitHub Actions wchodzi na konto deploy, które nie ma sudo, dedykowanym kluczem - innym niż klucz administracyjny. Wyciek sekretu z Actions kosztuje jeden katalog, nie całą maszynę. Odcięcie to skasowanie jednej linii z authorized_keys.

Po starcie: z landingu w stronę produktu

Landing powstał w jeden dzień, ale nie został w tej formie. W kolejnych tygodniach doszły rzeczy, których lista oczekujących potrzebuje, gdy zaczyna ją ktoś odwiedzać.

Treść pod wyszukiwarki i asystentów AI. Blog z czterema wpisami (m.in. koszt pracy z Claude Code policzony na realnych liczbach i porównanie dziewięciu nakładek graficznych w jednej tabeli), strona o zespole i osobna strona o nakładkach graficznych na Claude Code z sekcją FAQ. Do tego llms.txt, kanał RSS, daty modyfikacji w mapie witryny, powiadomienia IndexNow i graf schema.org z opisem produktu.

Ochrona formularza. Do honeypota i limitu na IP doszły Cloudflare Turnstile i globalny limit zapisów na godzinę. Jeśli wysyłka powiadomień mailowych padnie, alarm przychodzi przez GitHuba, zamiast żeby zapisy ginęły po cichu.

Utwardzenie serwera po audycie. Dostęp do statystyk Umami jest zamknięty, poczta idzie przez STARTTLS z certyfikatem, deploy nie korzysta z konta roota, a fail2ban blokuje adresy po serii błędnych logowań do panelu administracyjnego.

Film promocyjny złożony w kodzie w Remotion, w tym samym repozytorium co strona.

Co z tego wyszło

Strona główna pobiera sześć własnych plików: dokument, trzy arkusze stylów, jeden skrypt i skrypt statystyk. Razem 39 kB po kompresji. Pierwsze renderowanie treści w 0,2 s. Najcięższym elementem jest dziś widżet Turnstile ładowany z Cloudflare, który dokłada kilkanaście żądań. To świadoma cena za formularz, którego nie zasypują boty.

Od pustego repozytorium do działającej domeny z odbierającym zapisy API minął jeden dzień. To właściwa cena landingu pod listę oczekujących: jeśli kosztuje tydzień, jest droższy niż wart, bo jego jedynym zadaniem jest sprawdzić, czy budowanie reszty ma sens. Blog i strony pod wyszukiwarki doszły dopiero wtedy, gdy było wiadomo, że projekt idzie dalej.

Technicznie

Astro 7 z Tailwindem, całe copy w jednym pliku src/data/content.ts - zmiana tekstu nie wymaga otwierania żadnego .astro. Backend to FastAPI w kontenerze na porcie 8002, baza SQLite w /data poza katalogiem synchronizowanym przy deployu. Caddy stoi przed obydwoma: /api/* idzie do kontenera, reszta to pliki statyczne z nagłówkami bezpieczeństwa i trzydziestodniowym cache’em na assety.

CI robi dwie rzeczy przed wypuszczeniem zmiany: uruchamia self-check API i buduje frontend. Deploy API kończy się smoke testem na /health wykonanym już w kontenerze - jeśli kontener wstał, ale aplikacja w nim nie, workflow się wywala, zamiast zameldować sukces.

Jeśli planujesz landing pod kampanię albo aplikację webową z własnym backendem - to jest ten sam zestaw decyzji, tylko w mniejszej skali.

Zrzuty ekranu

Hero: jedno zdanie, jedno pole e-mail i makieta aplikacji zamiast listy funkcji.
Hero: jedno zdanie, jedno pole e-mail i makieta aplikacji zamiast listy funkcji. (telefon)

Hero: jedno zdanie, jedno pole e-mail i makieta aplikacji zamiast listy funkcji.