# ZapiszPrzepis: jak używam AI w projektach

Aplikacja zbudowana i wdrożona od zera z AI — projekt zaliczeniowy 10xDevs 3.0 zdany w pierwszym terminie z wyróżnieniem Best Project. Jak wygląda ten proces.

**Canonical:** https://spoko.space/pl/blog/zapiszprzepis-aplikacja-ai-first/  
**Language:** pl  
**Published:** 2026-08-23  
**Tags:** AI, Next.js, React, TypeScript, Supabase, PWA, Cloudflare  
**Category:** AI

---
**AI jest częścią mojej codziennej pracy od dawna — ale deklaracja niewiele znaczy, więc pokażę projekt.** [ZapiszPrzepis](https://zapiszprzepis.pl) zbudowałem od zera i wdrożyłem na produkcję: aplikacja działa, kod jest publiczny, a jako praca zaliczeniowa kursu **10xDevs 3.0** przeszła w pierwszym terminie i dostała wyróżnienie **Best Project**.

To wciąż wersja testowa: korzysta z niej na co dzień kilka bliskich mi osób, a rejestracja nie jest otwarta.

Ten wpis jest o tym, jak wygląda ten proces w praktyce — bo to jest rzecz, którą wnoszę do każdego projektu klienckiego, a nie tylko do własnych zabawek.

## Co robi aplikacja

Przepisy krążą dziś jako posty, Reelsy i filmy. Odruch jest jeden: zapisać zakładką albo funkcją „Zapisz" w danej platformie. Problem w tym, że **wszystkie te sposoby przechowują odnośnik, a nie treść**.

Po kilku miesiącach spora część zapisanych linków przestaje działać. Autor kasuje Reela, grupa kulinarna znika, blog gaśnie, post idzie w prywatne. Zapisana kolekcja zamienia się w listę błędów 404 — i dowiadujesz się o tym dopiero wtedy, gdy chcesz z niej skorzystać.

ZapiszPrzepis działa odwrotnie — **archive-first**. Z każdego linku robi trwałą kopię: tytuł, składniki, kroki i zdjęcie lądują w bazie użytkownika. Adres źródła zapisuje się razem z nimi, więc do oryginału wracasz jednym kliknięciem — dopóki istnieje. Kiedy zniknie, nie tracisz nic poza tym przyciskiem.

Ta kopia nie jest zrzutem strony. **Tekst układa model OpenAI** — zostawia składniki i kroki, a wycina nawigację, reklamy i długi wstęp, przez który trzeba się przewijać do właściwego przepisu. Angielskie źródła tłumaczy przy okazji na polski.

Projektowałem dla osoby nietechnicznej — takiej, która nie wpisuje ręcznie składników, nie wypełnia formularzy i nie zarządza folderami ani tagami. To ograniczenie okazało się najbardziej użytecznym filtrem w całym projekcie: natychmiast wykluczyło większość „oczywistych" funkcji.

## Jak to działa

Cała ścieżka wejścia to jeden gest. Aplikacja rejestruje się jako **Web Share Target**, czyli pojawia się na systemowej liście „Udostępnij" obok Messengera i WhatsAppa. Użytkownik wysyła do niej link i nie robi nic więcej.

![Ekran główny ZapiszPrzepis na telefonie](../../assets/images/blog/zapiszprzepis-mobile.webp)

Dalej wszystko dzieje się w tle:

Ekstrakcja potrafi trwać kilkanaście sekund i bywa zawodna, więc nie działa w cyklu żądania. Wrzuca zdarzenie do **Inngest**, który zajmuje się kolejkowaniem i ponawianiem. Użytkownik dostaje odpowiedź natychmiast, a przepis dopisuje się chwilę później.

Później doszła jeszcze wyszukiwarka przepisów w internecie z wejściem głosowym — bo samo archiwizowanie rozwiązywało tylko połowę problemu. Druga połowa to znalezienie czegoś, czego jeszcze nie masz.

## Stack i dlaczego akurat taki

<TableLookup
  headers={['Warstwa', 'Wybór i powód']}
  rows={[
    { term: 'Framework', detail: '<strong>Next.js 15</strong> (App Router) — Server Actions, czyli formularze bez budowania osobnego API' },
    { term: 'Baza i auth', detail: '<strong>Supabase</strong> — Postgres z RLS i logowanie magic linkiem, bez haseł' },
    { term: 'Zadania w tle', detail: '<strong>Inngest</strong> — ponawianie i kolejkowanie bez utrzymywania własnej infrastruktury' },
    { term: 'Ekstrakcja', detail: '<strong>Firecrawl + OpenAI</strong> (gpt-4o-mini) — pobranie treści i wyciągnięcie z niej struktury' },
    { term: 'Hosting', detail: '<strong>Cloudflare Workers</strong> (OpenNext) — reszta projektu już tam była' },
    { term: 'Warstwa klienta', detail: '<strong>PWA + Web Share Target</strong> — jedyny sposób na wejście jednym gestem' },
  ]}
/>

Jedna decyzja zdeterminowała pozostałe: **hosting na Cloudflare Workers oznacza brak Node.js API w runtime**. Każda integracja musiała działać przez zwykły `fetch`. To wykluczyło kilka bibliotek, zanim napisałem pierwszą linijkę — i dobrze, bo odkrycie tego w trakcie wdrożenia kosztowałoby jeden z niewielu dostępnych dni.

Wybór między Next.js a lżejszymi generatorami rozbieram dokładniej w [porównaniu frameworków do aplikacji webowych](https://spoko.space/pl/blog/frameworki-aplikacje-webowe-2026/) — tutaj przeważyła potrzeba dynamicznego stanu po stronie serwera.

## Jak wygląda u mnie praca z AI

To jest część, która przenosi się na projekty klienckie jeden do jednego.

### Kontekst projektu jako pamięć długoterminowa

W repozytorium leży katalog z opisem wymagań, roadmapą, planami poszczególnych zmian i rejestrem wyciągniętych wniosków. To nie jest dokumentacja pisana dla ludzi po fakcie — to **materiał wejściowy dla modelu przed każdą zmianą**.

Różnica jest odczuwalna. Model bez kontekstu generuje kod, który wygląda rozsądnie, ale ignoruje decyzje podjęte trzy dni wcześniej. Model z wymaganiami i planem pod ręką proponuje rozwiązania spójne z tym, co już istnieje — i sam zwraca uwagę, gdy prosisz go o coś, co przeczy wcześniejszemu ustaleniu.

Dla Ciebie jako klienta ma to prozaiczny skutek: te dokumenty zostają. Nie kupujesz czarnej skrzynki, tylko projekt, w którym widać, co i dlaczego zostało zdecydowane.

### Plan przed kodem, zawsze

Każda większa zmiana zaczyna się od dokumentu z rozpisanymi fazami, kryteriami akceptacji i listą ryzyk — a nie od polecenia „dodaj wyszukiwarkę". Dopiero zatwierdzony plan idzie do implementacji.

Brzmi jak biurokracja. W praktyce to właśnie ten krok skraca całość, bo eliminuje najdroższą kategorię błędów: zbudowanie czegoś działającego, co rozwiązuje niewłaściwy problem. Wyszukiwarka z lipca to dobry przykład — miała budżet tygodnia, a powstała w trzy dni, bo plan był gotowy, zanim poszła pierwsza linijka.

### Testy tam, gdzie logika jest podstępna

Projekt ma **ponad 70 testów jednostkowych** i zestaw testów E2E w Playwrighcie. Nie są rozłożone równomiernie i to jest celowe — stoją tam, gdzie najłatwiej o cichą pomyłkę: rozpoznawanie typu źródła, redakcja składników, ocena czy pobrana treść w ogóle nadaje się na przepis, parsowanie identyfikatorów filmów.

O tym, jak wpinam AI w testy E2E, pisałem szerzej w [przewodniku po testach E2E z Playwrightem](https://spoko.space/pl/blog/testy-e2e-ai-playwright-przewodnik/).

### Review jako bramka, nie formalność

Kod, przy którym pomagał model, rzadko myli się w sposób oczywisty. Myli się tam, gdzie coś **działa, ale opiera się na błędnym założeniu**: wyrażenie regularne, które wygląda na szczelne. Dopasowanie, które działa dla dzisiejszych danych wejściowych. Uprawnienie nadane „na wszelki wypadek".

To są dokładnie te rzeczy, które przechodzą przez kompilator i przez testy. Dlatego review nie jest u mnie ostatnim punktem listy, tylko miejscem, w którym spędzam nieproporcjonalnie dużo czasu — i im więcej kodu pisze model, tym bardziej to się opłaca.

## Co z tego ma Twój projekt

Konkretnie, bez ogólników:

- **Wymagania spisane przed kodem.** Wiesz, co powstaje i po czym poznamy, że jest gotowe.
- **Szybsze dojście do działającej wersji.** AI skraca pisanie, więc więcej czasu zostaje na to, co realnie decyduje o wyniku.
- **Testy w miejscach, które psują się po cichu.** Nie po to, żeby mieć ładny wskaźnik pokrycia, tylko żeby regresja nie dojechała do produkcji.
- **Kod i dokumentacja u Ciebie.** Repozytorium, decyzje i historia zmian są Twoje — możesz z tym pójść dalej, ze mną albo bez.
- **Jedna osoba odpowiedzialna za całość.** Od architektury, przez wdrożenie, po wsparcie po starcie.

## Podsumowanie

- **AI nie zastępuje myślenia, tylko skraca pisanie.** Cała różnica robi się na etapie, na którym ustalamy, co w ogóle budujemy.
- **Kontekst projektu w repozytorium jest infrastrukturą**, nie dokumentacją — i zostaje u klienta.
- **Review i testy zyskują na znaczeniu, im więcej kodu pisze model**, bo błędy przesuwają się z „nie kompiluje się" w stronę „działa, ale na błędnym założeniu".
- **Ograniczenia platformy warto poznać przed pierwszą linijką**, a nie w trakcie wdrożenia.

ZapiszPrzepis powstał w ramach [10xDevs 3.0](https://10xdevs.pl/), został zaliczony w pierwszym terminie z wyróżnieniem Best Project — [certyfikat do weryfikacji](https://credsverse.com/credentials/d9f99ad8-ed75-4c81-a8ae-2a014d385725) — a kod jest publiczny na [GitHubie](https://github.com/spokospace/zapiszprzepis).
