Jeden wspólny planer dla paczki znajomych. Logujesz się raz (e-mail + kod), potem widzisz oś czasu wypadów i dodajesz nowe. Dla każdego wypadu proponujecie terminy, każdy zaznacza kiedy może, a organizator (twórca wypadu) „ustala" zwycięski termin — wtedy wypad ląduje na osi czasu jako nadchodzący. Wynik aktualizuje się na żywo. Logowanie pilnuje, że każdy działa tylko jako on sam (nikt nie zagłosuje za kogoś).
- Next.js 16 (App Router, TypeScript) + React 19 — frontend i hosting (Vercel).
- Supabase — baza PostgreSQL, aktualizacje na żywo (Realtime) oraz logowanie (Auth, e-mail + kod OTP, trwała sesja).
- PWA — manifest pozwala dodać stronę do ekranu głównego telefonu.
Wszystko mieści się w darmowych planach Vercela i Supabase przy skali „grupka znajomych".
- Załóż projekt Supabase na https://supabase.com (darmowy plan).
- Utwórz tabele: w panelu Supabase otwórz SQL Editor, wklej zawartość
supabase/schema.sqli kliknij Run. Skrypt jest idempotentny — po aktualizacji schematu uruchamiasz go po prostu ponownie. Schemat włącza logowanie i zacieśnione reguły RLS (zob. „Logowanie" niżej). - Skopiuj klucze: Project Settings → API → potrzebujesz
Project URLoraz kluczaanon public. - Skonfiguruj zmienne środowiskowe:
i uzupełnij:
cp .env.example .env.local
NEXT_PUBLIC_SUPABASE_URL=https://twoj-projekt.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=twoj-klucz-anon - Zainstaluj i uruchom:
Aplikacja działa na http://localhost:3000.
npm install npm run dev
Bez kroków 1–4 strona się otworzy, ale pokaże baner z prośbą o konfigurację.
- Wrzuć repo na GitHub.
- Na https://vercel.com wybierz Import Project i wskaż repozytorium.
- W ustawieniach projektu Vercel dodaj te same dwie zmienne środowiskowe
(
NEXT_PUBLIC_SUPABASE_URL,NEXT_PUBLIC_SUPABASE_ANON_KEY). - Deploy. Dostajesz darmowy adres
nazwa.vercel.app, który wysyłasz znajomym.
npm run dev— serwer deweloperski.npm run build— build produkcyjny.npm start— uruchomienie buildu produkcyjnego.
- Logowanie na wejściu. Podajesz e-mail, dostajesz 6-cyfrowy kod, a przy pierwszym razie ustawiasz nazwę (widoczną przy Twoich głosach). Sesja jest trwała — na danym urządzeniu logujesz się praktycznie raz.
- Strona główna = dashboard: wspólna oś czasu wypadów (Do ustalenia / Nadchodzące / Minione) i przycisk „Nowy wypad".
- Każdy wypad (
/event/<id>) ma swój link. Uczestnik dodaje terminy i przy każdym zaznacza: Mogę / Może / Nie. - Organizator (twórca wypadu) „ustala" zwycięski termin — wypad dostaje konkretną datę i przechodzi na osi czasu do „Nadchodzące", a po dacie do „Minione".
- Dzięki Supabase Realtime głosy, nowe wypady i ustalenia pojawiają się u wszystkich natychmiast.
- Reguły bazy pilnują, że każdy edytuje tylko swoje (głos, ustalanie terminu) — nikt nie podszyje się pod kogoś innego.
Logowanie to e-mail + jednorazowy kod (Supabase Auth). Konfiguracja w panelu:
- Authentication → Providers → Email — włączone (domyślnie jest).
- Authentication → Email Templates → Magic Link — dodaj do treści kod, np.:
Twój kod logowania: {{ .Token }}(domyślny szablon pokazuje tylko link, a my logujemy się kodem wpisywanym w aplikacji). - Uruchom (lub uruchom ponownie)
supabase/schema.sql— włącza reguły RLS „tylko zalogowani; każdy edytuje swoje".
Wbudowana wysyłka maili Supabase jest limitowana (kilka/godz.) — dla paczki znajomych wystarcza; docelowo można podpiąć własny SMTP. Sesja trzymana jest w przeglądarce i odświeżana automatycznie, więc logujesz się rzadko.
Darmowy plan Supabase pauzuje projekt po ~7 dniach bezczynności. Żeby tego
uniknąć, vercel.json definiuje Vercel Cron, który raz dziennie odpytuje
endpoint /api/keepalive — ten robi lekkie
zapytanie do bazy i utrzymuje ją aktywną. Działa automatycznie po wdrożeniu na
Vercela (widoczne w Settings → Cron Jobs). Cron na planie Hobby uruchamia się
raz na dobę — to wystarcza wobec 7-dniowego okna pauzy.
Można też sprawdzić ręcznie: wejście na https://<twoja-domena>/api/keepalive
zwraca {"ok":true,...}.
Fallback: gdyby cron z jakiegoś powodu nie działał, ten sam efekt da darmowy zewnętrzny pinger (np. https://cron-job.org) ustawiony na codzienne odpytywanie
/api/keepalive.
W src/app/layout.tsx podpięte są @vercel/analytics i @vercel/speed-insights.
Żeby zaczęły zbierać dane, włącz je jeszcze w panelu Vercela:
- Projekt → zakładka Analytics → Enable.
- Projekt → zakładka Speed Insights → Enable.
Dane pojawią się po pierwszych wejściach (z niewielkim opóźnieniem).
- Wspólna baza / cutover. Włączenie nowego
schema.sql(logowanie + RLS) sprawia, że stara wersja bez logowania przestaje działać na tej samej bazie. Uruchamiaj nowy schemat razem z wdrożeniem nowego kodu na produkcję. - Każdy zweryfikowany ma dostęp. Nie ma listy zaproszonych — kto się zaloguje, ten korzysta (ale tylko jako on sam). Jeśli zajdzie potrzeba trzymania obcych z daleka, dochodzi allowlista e-maili.
- Migawki nazw. Nazwę wyświetlaną zapisujemy przy głosie/wypadzie w chwili akcji; zmiana nazwy nie aktualizuje wstecz starych wpisów.
npm auditzgłasza jedną podatność moderate w pakieciepostcss(zależność pośrednia, używana tylko przy budowaniu CSS — nie dotyczy runtime). Podpowiadany „fix" downgrade'uje Next do prehistorycznej wersji, więc go nie stosujemy.
- Powiadomienia push (Web Push / VAPID, darmowe). Działają na Androidzie; na iPhonie tylko od iOS 16.4+ i pod warunkiem dodania strony do ekranu głównego.
- Logowanie przez Google (jedno kliknięcie) obok kodu e-mail; allowlista e-maili.
- Komentarze przy wypadzie.
- Ikony PNG (192/512) i
apple-touch-icondla pełnego wsparcia instalacji PWA.