Files
wtr/AGENTS.md
zv 91acdb39b8
Some checks failed
CI / Lint, test, typecheck and build (push) Has been cancelled
feat: add weather unit preferences
2026-07-04 20:16:11 +02:00

13 KiB

AGENTS.md

Projekt

wtr. to mobilna PWA pogodowa z pełnym trybem dla Polski i globalną prognozą modelową. Dla Polski pokazuje bieżącą analizę IMGW Hybrid, pomiary synoptyczne, dane hydrologiczne i ostrzeżenia z publicznych API IMGW oraz prognozę modelową łączącą IMGW ALARO z Open-Meteo. Poza Polską pokazuje modelowe bieżące warunki i prognozę Open-Meteo bez oficjalnych ostrzeżeń IMGW. Open-Meteo Geocoding służy do globalnego wyszukiwania miejscowości, a Nominatim / OpenStreetMap do opcjonalnego reverse geocodingu po zgodzie GPS użytkownika.

Stack: Next.js App Router, React, TypeScript, Tailwind CSS, TanStack Query, Zustand, Framer Motion, Recharts, Lucide React, web-push i SQLite przez better-sqlite3. PWA korzysta z manifestu oraz własnego service workera.

Najważniejsze katalogi:

  • app/ - routing, layout, globalne style i route handlery proxy.
  • components/ - komponenty pogody, prognozy, hydro, ostrzeżeń, layoutu, UI i stanów ekranu.
  • hooks/ - hooki TanStack Query.
  • lib/ - fetchery, normalizacja danych, tłumaczenia, helpery, Web Push i store Zustand.
  • types/ - typy danych IMGW, prognozy, lokalizacji oraz powiadomień.
  • public/ - manifest, service worker i ikony PWA.

Komendy

Wymagany jest Node.js 20.9 lub nowszy.

npm install
npm run dev
npm run lint
npm run format
npm run format:check
npm run test
npm run test:watch
npm run typecheck
npm run build
npm run start
npm run notifications:worker

Testy jednostkowe uruchamia npm run test przez Vitest, a npm run test:watch działa w trybie obserwowania zmian. npm run format i npm run format:check używają Prettiera. npm run typecheck uruchamia tsc --noEmit, a npm run build uruchamia produkcyjny build Next.js. npm run notifications:worker uruchamia osobny proces Node do cyklicznego wywoływania endpointów Web Push na self-hostingu; wczytuje .env i .env.local, ale nadal wymaga równolegle działającego npm run start albo poprawnego WTR_APP_URL. Nie opisuj ani nie uruchamiaj nieistniejących komend jako standardowego workflow.

Konwencje kodu

  • Używaj TypeScript konsekwentnie i importów absolutnych @/....
  • Komponenty i typy nazywaj PascalCase, funkcje oraz hooki camelCase; hooki zaczynają się od use.
  • Trzymaj routing w app/, komponenty funkcjonalne w odpowiednim podkatalogu components/, zapytania Query w hooks/, fetchery i normalizację w lib/, a typy danych w types/.
  • Dodawaj "use client" tylko tam, gdzie komponent lub moduł korzysta z hooków, stanu przeglądarki albo interakcji.
  • Dane zewnętrzne pobieraj przez route handlery Next.js. Nie omijaj allowlisty w app/api/imgw/[...path]/route.ts.
  • Traktuj IMGW jako źródło bieżących pomiarów, hydro i ostrzeżeń tylko dla Polski. Poza Polską używaj Open-Meteo jako modelowego źródła bieżących warunków i prognozy. Nie generuj fikcyjnych danych, nie przedstawiaj prognozy jako pomiaru IMGW i nie przedstawiaj modelowych sygnałów jako oficjalnych alertów.
  • Lokalizacja ma region PL albo GLOBAL. Preferuj capabilities i metadane źródła z types/weather-region.ts zamiast rozsiewania lokalnych warunków po kraju w UI.
  • Dashboard hero korzysta z publicznego endpointu Hybrid oficjalnego portalu IMGW przez app/api/imgw-current/route.ts, z fallbackiem do godzinowego synop. Hybrid ma krótki cache i dostarcza m.in. opad 10-minutowy; nie przedstawiaj go jako akumulowanej sumy opadu stacji.
  • Hybrid wybieraj z pierwszego pełnego rekordu analizy zwracanego przez endpoint dla lokalizacji, preferując Type_Ten_Minutes, a potem Type_Hour. Wymagaj realnych wartości liczbowych; nie traktuj null jako pełnego pola i nie opieraj wyboru na zegarze przeglądarki. Jeśli pełny Type_Ten_Minutes jest o ponad 2 godziny starszy od pełnego Type_Hour z tej samej odpowiedzi, użyj świeższego Type_Hour, żeby nie nadpisywać aktualnego fallbacku starym rekordem Hybrid. Jeśli IMGW zwraca wyłącznie lokalny opad MERGE bez pełnych parametrów, zachowuj go jako częściową analizę lokalną, a pozostałe parametry uzupełniaj jawnym fallbackiem synop.
  • W UI rozdzielaj lokalną analizę Hybrid dla współrzędnych miejscowości od kontekstowej informacji o najbliższej stacji pomiarowej. Fallback synop oznaczaj jawnie; dla stacji oddalonej o co najmniej 30 km zachowuj ostrzeżenie o możliwej różnicy warunków lokalnych.
  • Route handler prognozy pobiera pełne 7 dni Open-Meteo, a dla PL dodatkowo godzinowe IMGW ALARO. W godzinach pokrytych przez ALARO parametry IMGW mają pierwszeństwo, Open-Meteo dostarcza prawdopodobieństwo opadu i dalszy horyzont, a awaria ALARO pozostawia działający fallback Open-Meteo. Dla GLOBAL nie odpytuj ALARO i używaj Open-Meteo z lokalną strefą czasu. Dashboard pokazuje regułowy brief dnia, najbliższe 24 przyszłe godziny oraz wykresy pełnego bieżącego dnia, a widok szczegółowy dnia korzysta z pełnego zestawu godzin dla wybranej daty.
  • synop.suma_opadu jest akumulowaną sumą opadu. Nie używaj jej jako sygnału, że pada w tej chwili, ani do sterowania animacją deszczu.
  • Ostrzeżenia hydro zawierają jawne województwa, a ostrzeżenia meteo kody powiatów TERYT. Normalizuj oba warianty przez lib/provinces.ts i lib/warning-regions.ts; nie filtruj ostrzeżeń wyłącznie po opisach tekstowych.
  • HTTP 404 z IMGW dla ostrzeżeń z JSON {"status":false,"message":"No products were found"} oznacza brak produktów i ma być normalizowany do pustej listy, nie do błędu UI ani błędu workera.
  • Listy ostrzeżeń zachowują priorytet lokalnego obszaru, a wewnątrz każdej grupy pokazują ostrzeżenia meteorologiczne przed hydrologicznymi. Jeśli lokalizacja ma rozpoznany powiat TERYT, ostrzeżenia meteo filtruj po tym powiecie; w przeciwnym razie stosuj fallback wojewódzki. W obrębie rodzaju zachowuj kolejność publikacji od najnowszych.
  • Dashboard pokazuje kompaktowo wyłącznie aktywne i nadchodzące ostrzeżenia meteo dla wybranego obszaru. Filtruj je po validTo względem czasu przeglądarki i automatycznie usuwaj wygasłe komunikaty bez przeładowania strony.
  • Brief dnia i brief na jutro generuj deterministycznie w lib/weather-brief.ts z prognozy modelowej i, dla PL, ostrzeżeń IMGW. Nie traktuj ich jako odpowiedzi modelu AI i nie wymagaj klucza OpenAI API. Brief na jutro korzysta z pełnego jutrzejszego dnia prognozy i może informować o burzach na podstawie kodów modelu także bez oficjalnego ostrzeżenia IMGW.
  • Preferencje jednostek temperatury, wiatru, opadu, ciśnienia i dystansu są ustawieniami prezentacyjnymi. Dane źródłowe oraz progi logiki pogody pozostają liczone w °C, m/s, mm, hPa i km, a wybrane jednostki zapisuj w subskrypcji Web Push, żeby briefy serwerowe używały tego samego formatu co UI.
  • Powiadomienia Web Push o ostrzeżeniach meteo, porannym briefie i wieczornym briefie na jutro konfiguruj przez /settings, public/sw.js, route handlery app/api/notifications/*, w tym testowy /api/notifications/test, oraz self-hostowany worker scripts/notification-worker.mjs. Endpointy harmonogramu nie uruchamiają się same bez workera albo zewnętrznego crona. Briefy są deduplikowane po lokalnej dacie subskrypcji i wysyłane po godzinie skonfigurowanej względem zapisanej strefy czasowej lokalizacji. Wymagają kluczy VAPID w zmiennych środowiskowych. iOS/iPadOS wymaga PWA z ekranu początkowego, ale Android i desktop nie powinny być blokowane wymogiem standalone. lib/push-store.ts zapisuje subskrypcje i historię wysyłek w SQLite wskazanym przez WTR_DATABASE_PATH, domyślnie ./data/wtr.sqlite.
  • GPS wymaga świadomej zgody użytkownika i HTTPS. Zaokrąglaj współrzędne przed użyciem i utrzymuj widoczną atrybucję OpenStreetMap dla reverse geocodingu Nominatim.
  • Normalizuj zewnętrzne odpowiedzi i obsługuj null, puste pola oraz błędne wartości. Brak danych pokazuj jawnie zamiast uzupełniać estymacją.
  • Dla pobierania danych używaj TanStack Query z sensownym queryKey, cache i retry. W UI zachowuj loading, error, retry oraz empty states.
  • Teksty interfejsu dodawaj równolegle po polsku i angielsku w lib/i18n.tsx. Nazw stacji i treści IMGW nie tłumacz automatycznie.
  • Trwałe preferencje użytkownika zapisuj przez istniejący store Zustand w lib/store.ts lub istniejące klucze localStorage.
  • Zachowuj mobile-first UI, dostępność klawiatury, aria-label, focus states oraz spokojny styl glassmorphism.
  • Pełnoekranowe warstwy interaktywne zamykaj przyciskiem i klawiszem Escape, blokuj przewijanie tła oraz przywracaj fokus po zamknięciu.
  • Nie edytuj ręcznie next-env.d.ts; plik jest generowany przez Next.js.

Obsługa błędów:

  • Route handlery zwracają kontrolowane odpowiedzi JSON z kodem HTTP.
  • Fetchery w lib/ rzucają Error, a komponenty prezentują czytelny stan błędu i retry.
  • Projekt nie ma warstwy logowania aplikacyjnego. Nie dodawaj przypadkowych console.log.

Zmiany frontendowe

To jest istniejąca aplikacja produktowa. Nie przebudowuj frontendu od zera, jeśli celem jest poprawa wyglądu. Zachowuj routing, przepływ danych, strukturę komponentów i logikę biznesową. Restyle powinien najpierw przechodzić przez globalne style, theme, tokeny, layout oraz komponenty współdzielone, a dopiero później przez pojedyncze widoki.

Docelowy kierunek wizualny:

  • spokojny, praktyczny i produktowy;
  • nowoczesny, ale bez efektów modnych na siłę;
  • neutralna baza kolorystyczna i jeden konsekwentny kolor akcentu;
  • czytelna hierarchia, przewidywalne odstępy i spójne karty;
  • wygląd nudny w dobrym sensie: dopracowany, czytelny, bez dekoracyjnego szumu.

Unikaj:

  • neonowych kolorów, fioletowo-cyjanowych gradientów i świecących cieni;
  • losowych dekoracyjnych blobów, nadmiaru blurów i efektów bez funkcji;
  • przesadnie dużych zaokrągleń oraz niespójnych radiusów między sekcjami;
  • generycznych sekcji typu SaaS landing page;
  • arbitralnych kolorów bg-[#...], text-[#...], border-[#...] w komponentach;
  • lokalnych wyjątków stylistycznych, które powodują inny wygląd /, /warnings, /hydro i modali.

Przy zmianach UI:

  • nie dodawaj nowych zależności bez wyraźnego powodu;
  • nie zmieniaj UX ani przepływu interakcji, chyba że problem jest oczywisty i opiszesz go przed zmianą;
  • preferuj tokeny Tailwind/theme, klasy użytkowe z app/globals.css, Card, Button i komponenty współdzielone;
  • ogranicz zakres do najmniejszego zestawu plików potrzebnych do poprawy spójności;
  • po zmianie sprawdź, czy nie pojawiły się hardcodowane kolory, nowe gradienty, neonowe akcenty, niespójne karty ani zmiany logiki biznesowej;
  • sprawdź responsywność co najmniej mentalnie dla mobile, tablet i desktop, a przy większych zmianach uruchom aplikację lokalnie.

Instrukcje dla agenta

  • Przed zmianą przeczytaj pliki w obszarze funkcji i sprawdź git status.
  • Utrzymuj mały zakres zmian. Nie refaktoruj niezwiązanych modułów i nie cofaj cudzych zmian.
  • Nie dodawaj mocków jako źródła danych pogodowych. Przy zmianie źródeł API zaktualizuj route handler, typy, normalizację, UI i README.
  • Przy zmianach PWA sprawdź spójność public/manifest.json, public/sw.js i rejestracji service workera.
  • Dobieraj lokalną weryfikację proporcjonalnie do ryzyka zmiany. CI w Gitea Actions jest ostateczną bramką jakości po pushu.
  • Zmiany w README, docs, tekstach i komentarzach: nie uruchamiaj npm run lint, npm run typecheck ani npm run build; wystarczy git diff i ewentualnie git diff --check.
  • Małe zmiany wizualne, np. klasy Tailwind, border, radius, spacing, kolory albo copy w JSX: nie uruchamiaj rutynowo npm run build. Uruchom npm run lint tylko, gdy zmiana mogła naruszyć składnię albo reguły lintingu, a npm run typecheck tylko przy zmianach typów, propsów lub logiki.
  • Zmiany w komponentach z logiką, hookach, typach, parserach i danych pogodowych: uruchom npm run typecheck; dodaj npm run lint, jeśli zmiana dotyka kodu TS/TSX, oraz npm run test, jeśli zmiana dotyka logiki objętej testami.
  • Zmiany wysokiego ryzyka, np. Next routing, config, dependencies, package-lock, PWA/service worker, API/server code, build config i obsługa env: uruchom pełny zestaw npm run lint, npm run format:check, npm run typecheck, npm run test i npm run build.
  • Przed większym pushem albo większym refaktorem możesz uruchomić pełną weryfikację.
  • Sprawdź git status przed zakończeniem. Używaj git diff --check wtedy, gdy zmiana mogła wprowadzić problemy whitespace. Nie commituj wygenerowanego churnu w next-env.d.ts.
  • Commituj zakończone zmiany w formacie Conventional Commits, np. fix: correct warning filtering, ale nie używaj eskalacji dla git commit bez realnej potrzeby.
  • Nie pushuj automatycznie, chyba że użytkownik wyraźnie o to poprosi. Jeśli push wymaga autoryzacji, zatrzymaj się i poproś użytkownika o wykonanie git push origin main.
  • Ważne decyzje o źródłach danych, ograniczeniach API, uruchamianiu i wdrożeniu dokumentuj krótko w README.md.

Utrzymywanie pliku

Aktualizuj AGENTS.md w tej samej zmianie, gdy zmieniają się: struktura projektu, komendy, konwencje, zależności, sposób uruchamiania, testowania lub istotne decyzje architektoniczne.

Jeśli ten plik jest nieaktualny, niepełny albo sprzeczny z kodem, popraw go zamiast ślepo go przestrzegać. Zachowuj go krótkim i praktycznym: bez historii czatu, dziennika zmian i ogólnych porad niezwiązanych z repozytorium.