Fix FAQFull: Use isDraft boolean for draft filtering, fix Kontakt ID override

This commit is contained in:
MichalC
2026-09-16 12:31:19 +02:00
parent 437e1e4823
commit 9043301da6
140 changed files with 23337 additions and 724 deletions
+156
View File
@@ -0,0 +1,156 @@
# Przegląd, strategia i workflow — poprawa strony j_kedzierski
**Klient:** Dipl.-Ing. Janusz Kędzierski, Finanz- & Lohnbuchhaltung — Beratungsstelle
b.b.h. Lohnsteuerhilfeverein e.V. (§4 Nr. 11 StBerG)
**Cel biznesowy:** wizytówka + pozyskiwanie klientów (Polacy pracujący w Niemczech,
rozliczenie po polsku) — nie e-commerce, nie SaaS. Konwersja = kontakt na WhatsApp.
**Stack:** Payload CMS 3 + Next.js 16.3.3 + React 19 + Tailwind 4 + Framer Motion +
`@intecion/ipal-kit`. Repo: `j_kedzierski` (folder `kedzierski_website` na Macu).
Ten plik spina wszystkie pozostałe. Przeczytaj go pierwszy — reszta plików zakłada,
że decyzje z sekcji 2 i 4 są już podjęte.
---
## 1. Co faktycznie jest w zipie (audyt, nie domysły)
Rozpakowałem `j_kedzierski.zip` i przeczytałem `scripts/content-snapshot.json`
(pełny zrzut wszystkich 10 stron PL+DE + globali) zamiast zakładać stan projektu.
Stan faktyczny:
### 1.1 Co jest zrobione dobrze (Antigravity, faza „kod i logika")
- Payload 3 + Next 16 + ipal-kit poprawnie zszyte: i18n PL/DE, `proxy.ts` (nie
middleware), kolekcje `Pages`/`Media`/`Users`, globale `Header`/`Footer`/`Company`
+ `site-settings` z pluginu.
- **17 bloków** już zbudowanych i podłączonych do `RenderBlocks`: Hero, TrustBar,
UniqueValue, Stats, ServicesList, Process, Affiliation, Testimonials, FAQTeaser,
FinalCTA, PageHeader, ServicesDetailed, Eligibility, ContactInfo, Bio, Team,
TextSection.
- Hero ma już realną robotę: Framer Motion stagger na tekst, 3D-parallax na
zdjęcie (`useParallax3D`, pointer-tracked rotateX/rotateY), floating stat card.
To nie jest szkielet — to działający, dopracowany komponent.
- Motyw jasny/ciemny (`next-themes`, `data-theme`) działa, przełącznik jest.
- **Design tokeny już wybrane i wdrożone** w `globals.css` (Tailwind 4 `@theme`):
ciepłe tło papieru `#F7F5F1`, atrament `#1C1B1A`, akcent pieczęć-czerwień
`#A13D2C` (hover `#8A3324`), karta biała, border `#E2DDD3`, radius przycisku 6px
(nie „pill"). Ciemny motyw: tło `#17140F`, akcent `#D4634A`. Fonty: **Fraunces**
(nagłówki, serif) + **Public Sans** (body).
- Treść tekstowa homepage, usług, procesu i „o nas" jest już napisana — dobrej
jakości, konkretna, PL i DE, nie jest to placeholder AI-lorem.
### 1.2 Realne braki (to jest do zrobienia, nie do zgadywania)
| Obszar | Stan faktyczny w zipie |
|---|---|
| Zdjęcia | Każdy blok ma `"image": 1` — czyli wskazuje na media ID 1, ale w paczce **nie ma żadnego pliku graficznego**. Zero zdjęć, zero logo, zero favicon. |
| Dane firmy | `address: "DO POTWIERDZENIA PRZEZ KLIENTA"`, `phone: "+49 123 456 789"`, `email: "[email protected]"`, `whatsappNumber: "49123456789"` — wszystko placeholder. |
| Strony prawne | Impressum, Polityka prywatności, Polityka cookies, Stowarzyszenie: treść = `"Treść w przygotowaniu"` / `"Inhalt in Vorbereitung"`. Puste. |
| FAQ (strona) | Też `TextSection` placeholder — mimo że homepage ma już `faqTeaser` z 8 pytaniami. Brak pełnej listy/kategoryzacji. |
| System Pages | `privacyPolicy`, `cookiePolicy`, `termsOfService` w `site-settings` = `null`. Role nieprzypisane → `getSystemPagePath` nie zadziała, linki w stopce/bannerze cookies będą martwe. |
| Baner cookies | Brak w kodzie `ConsentProvider`/`CookieBanner` w przejrzanych plikach — do potwierdzenia przy realizacji, patrz [11](./11-integracje-seo-wydajnosc.md). |
| Wygląd (Impeccable) | **Nie uruchomiony ani razu.** `styles.css` w `(frontend)` to nadal domyślny boilerplate Payloada (czarne tło, `font-family: system-ui`) — nieużywany, ale zostawiony w repo (do usunięcia, patrz [10](./10-architektura-cms.md)). Realny design system żyje w `globals.css`, ale nikt jeszcze nie przepuścił żadnej strony przez `/impeccable polish`/`audit`/`document`. |
| Formularz kontaktowy | Nie istnieje — jest tylko `contactInfo` (statyczne dane: adres/telefon/email/godziny). Cała konwersja opiera się o link do WhatsApp w `finalCta`/`hero`. |
**Wniosek:** to NIE jest projekt od zera. Faza „Antigravity" (funkcjonalność,
edytowalność, treść) jest w ~80% zrobiona i solidna. Brakuje: (a) prawdziwych
danych i zdjęć klienta, (b) treści na stronach prawnych/FAQ/stowarzyszenie,
(c) całej fazy „Impeccable" — wizualnego dopracowania, animacji scrollowania,
efektów — którą ten plan rozpisuje sekcja po sekcji.
---
## 2. Rozstrzygnięcie: bbh-lohnsteuerhilfe.de jako wzorzec — czego dokładnie
Sprawdziłem aktualną `bbh-lohnsteuerhilfe.de` (live). To generyczna strona na
Astro, wizualnie przeciętna: header z dużym menu, slider-hero ze zdjęciem
stockowym, sekcja usług jako tekst z listą, blok wideo, teaser porad podatkowych
(„Steuerspar-Tipps"), jeden cytat-pull-quote, newsletter, stopka z adresem i
linkami Impressum/Datenschutz/Satzung/Beitragsordnung, plakietki zaufania
(„Verschlüsselte Verbindung", „Server in Deutschland").
**Decyzja (przyjmuję jako założenie — popraw mnie, jeśli chodziło o coś innego):**
biorę z bbh **strukturę i sygnały zaufania branży**, nie warstwę wizualną.
Wizualnie bbh wygląda dokładnie jak to, czego już raz się pozbyliśmy w tym
projekcie („AI slop"/generic — patrz historia ustaleń w `.agents/context`) —
kopiowanie 1:1 jego stylu byłoby krokiem wstecz względem tokenów, które już są
w `globals.css` i które są dobrym, nietuzinkowym kierunkiem dla biura
podatkowego (ciepły papier + pieczęć = metafora „dokumentu urzędowego", a nie
kolejny SaaS). Zamiast przepisywać paletę bbh, **przenoszę z niego wzorce, które
faktycznie konwertują w tej branży**:
| Z bbh bierzemy (treść/UX) | Z bbh NIE bierzemy (wizualnie) |
|---|---|
| „Znajdź doradcę" / silny, jeden CTA nad zgięciem | Generyczny header z rozwijanym mega-menu |
| Sekcja „co to jest Lohnsteuerhilfe" (edukacja + wideo) | Stockowe zdjęcie slidera na cały ekran |
| Teaser porad podatkowych jako sygnał eksperckości | Płaska siatka kart bez hierarchii |
| Pull-quote klienta jako emocjonalny dowód społeczny | Domyślna typografia (system sans, brak charakteru) |
| Plakietki zaufania w stopce (szyfrowanie, serwery w UE) | Newsletter jako główny CTA (u nas to WhatsApp) |
| Linki Satzung/Beitragsordnung jako PDF w stopce | Brak spójnego motion/scroll storytellingu |
| Adres, telefon, godziny zawsze widoczne | — |
Kierunek wizualny: **ciepły „dokument urzędowy", nie SaaS** — już potwierdzony
w kodzie (papier/pieczęć/Fraunces). Ten plan go **dociąga do poziomu „petarda"**:
teksturę papieru, subtelne linie jak w formularzu podatkowym, akcenty pieczęci/
stempla, mikro-interakcje przy scrollowaniu, sekcję wideo i realne social proof —
wszystko przepuszczone przez Impeccable, żeby nie zjechać w stronę żadnego z
61 wzorców AI-slop (pełna lista w [01](./01-design-system-impeccable.md)).
Jeśli w istocie chodziło o dosłowne przejęcie wyglądu bbh (kolory, font, układ) —
to jest jedyne założenie w tym planie, które warto zweryfikować przed startem
budowy; reszta dokumentu nie zależy od tej decyzji.
---
## 3. Kolejność plików w tym planie
| Plik | Zawartość |
|---|---|
| `00-przeglad-strategia-i-workflow.md` | Ten plik. Audyt, decyzja stylu, workflow. |
| `01-design-system-impeccable.md` | PRODUCT.md, DESIGN.md, paleta/typografia/motion, kolejność komend Impeccable, checklista anty-slop. |
| `02-strona-glowna.md` | Home — sekcja po sekcji: treść, zdjęcia, animacje, tło, scroll. |
| `03-uslugi.md` | Usługi / Leistungen. |
| `04-jak-sie-umowic.md` | Jak się umówić / Terminvereinbarung. |
| `05-o-nas.md` | O nas / Über uns. |
| `06-faq.md` | FAQ — pełna strona (obecnie placeholder). |
| `07-stowarzyszenie.md` | Stowarzyszenie / Verein — pełna treść (obecnie placeholder). |
| `08-kontakt.md` | Kontakt. |
| `09-strony-prawne.md` | Impressum, Datenschutz, Cookie-Richtlinie — treść robocza + granica odpowiedzialności. |
| `10-architektura-cms.md` | Zmiany w kolekcjach/blokach/globalach, media, System Pages, sitemapa URL. |
| `11-integracje-seo-wydajnosc.md` | WhatsApp, formularz, SEO/schema.org, analytics za zgodą, bezpieczeństwo, wydajność. |
| `12-checklist-odbioru.md` | Skrócona, spriorytetyzowana checklista odbioru pod ten konkretny projekt. |
---
## 4. Workflow realizacji (Antigravity + Impeccable, w tej kolejności)
Zgodnie z `architektura-tresci.md`: **Antigravity najpierw (funkcjonalność),
Impeccable potem (wygląd)**. Tu funkcjonalność w ~80% już jest, więc kolejność:
1. **Dane wejściowe od klienta** (blokujące wszystko inne — patrz [10](./10-architektura-cms.md)
§1): realny adres, telefon, e-mail, numer WhatsApp, logo/zdjęcie Janusza,
ew. zdjęcia biura. Bez tego część sekcji zostaje na placeholderach.
2. **Antigravity — uzupełnienia funkcjonalne**: nowe pola/bloki wymagane przez
ten plan (FAQ accordion, treść Stowarzyszenie, System Pages role, WhatsApp
floating button, ew. formularz kontaktowy) — patrz [10](./10-architektura-cms.md) i
[11](./11-integracje-seo-wydajnosc.md). Zero stylowania ad hoc na tym etapie
(zgodnie z A6.8 w `antigravity-zasady-agent.md`).
3. **Impeccable `/impeccable init`** → wygeneruj `PRODUCT.md` (gotowa treść w
[01](./01-design-system-impeccable.md) §1 — do wklejenia/potwierdzenia).
4. **Impeccable `/impeccable document`** → wygeneruj `DESIGN.md` z istniejących
tokenów w `globals.css` (Impeccable powinien je wykryć automatycznie —
zweryfikuj wynik względem tabeli w [01](./01-design-system-impeccable.md) §2).
5. Dla każdej podstrony, w kolejności home → usługi → jak się umówić → o nas →
FAQ → stowarzyszenie → kontakt → prawne:
`/impeccable polish` z konkretnym promptem sekcja-po-sekcji z odpowiedniego
pliku (`02`–`09`) → `npx impeccable detect` na zbudowanej stronie → popraw
findings → `/impeccable audit` jako ostateczna kontrola jakości.
6. **`/impeccable animate`** na sekcjach, które w planie mają oznaczone efekty
scrollowania (hero, proces, statystyki, sekcja zaufania) — pojedynczo, nie
hurtowo, żeby nie przesadzić z ruchem (patrz zasada „Motion" w [01](./01-design-system-impeccable.md) §4).
7. Po wszystkich stronach: jeden przelot `/impeccable critique` na całości,
potem checklista z [12](./12-checklist-odbioru.md).
**Zasada obowiązująca cały czas:** żadna treść, obraz ani link nie ląduje na
sztywno w JSX — wszystko przez panel Payload (pole `localized`, `upload→media`,
`relationship→pages`), zgodnie z `architektura-tresci.md` i twardymi zakazami
w `antigravity-zasady-agent.md` (A1–A4). Ten plan opisuje TREŚĆ i WYGLĄD, które
mają trafić do pól CMS — nie jest to specyfikacja tekstu zaszytego w komponencie.
+185
View File
@@ -0,0 +1,185 @@
# Design system — PRODUCT.md, DESIGN.md, Impeccable
Ten plik to wejście do `/impeccable init` i `/impeccable document`. Zawiera
gotową treść obu plików kontekstowych, potwierdzone tokeny, system motion
„dokument urzędowy" (spójny w całej witrynie) oraz checklistę anty-slop
zawężoną do wzorców, na które ten konkretny projekt jest najbardziej narażony.
---
## 1. `PRODUCT.md` — wklej/wygeneruj i zatwierdź
```md
## Register
tax-advisory / professional services / trust-first landing site
## Platform
web (Next.js 16 SSR, Payload CMS 3 panel), responsywne od 360px do 4K,
PL i DE jako pełnoprawne wersje językowe (nie tylko tłumaczenie stringów UI)
## Users
Polacy pracujący w Niemczech (budowa, opieka, przemysł, sektor usługowy),
25-55 lat, rozliczają PIT/Einkommensteuererklärung raz w roku, często pierwszy
raz korzystają z doradcy podatkowego. Czytają po polsku, część zna niemiecki
na tyle, by porównać ofertę z niemiecką konkurencją (stąd wersja DE). Wchodzą
głównie z telefonu, często z linku od znajomego lub z Facebooka/grupy
polonijnej. Nieufni wobec formularzy z danymi osobowymi — WhatsApp jest dla
nich niższym progiem wejścia niż mail czy telefon.
## Product Purpose
Przekonać odwiedzającego w mniej niż 30 sekundach, że (a) to prawdziwa,
uprawniona firma (nie oszustwo), (b) obsługa jest w 100% po polsku,
(c) proces jest prosty i zdalny — i doprowadzić go do jednego działania:
napisania na WhatsApp. Strona to wizytówka + generator leadów, nie sklep,
nie panel klienta, nie blog (na start).
## Tone
Rzeczowy, spokojny, kompetentny — jak dobry doradca, nie jak reklama. Bez
zachwytów marketingowych („rewolucyjne", „najlepsze na rynku"). Konkret:
liczby, terminy ustawowe, realne dokumenty (Lohnsteuerbescheinigung, IdNr).
Zaufanie buduje precyzja, nie entuzjazm.
## Accessibility & Inclusion
WCAG 2.2 AA jako cel bazowy (patrz `wymagania-projektowe-strony.md` §4).
Duża część odbiorców to osoby starsze/niekorzystające na co dzień z
rozbudowanych interfejsów — tekst czytelny bez zoomu (min. 16px body),
kontrast pilnowany osobno dla ciepłego tła papieru (nie zakładaj, że jasne tło
= automatycznie OK), pełna obsługa klawiaturą, `prefers-reduced-motion`
respektowany na WSZYSTKICH animacjach z sekcji 4.
```
---
## 2. `DESIGN.md` — potwierdzenie tokenów już w `globals.css`
Impeccable powinien je wykryć sam przez `/impeccable document`. Poniższa
tabela to punkt odniesienia do weryfikacji wygenerowanego pliku — jeśli
wygenerowany `DESIGN.md` odbiega od tego, popraw go ręcznie przed dalszą pracą
(inaczej detektor „design system" będzie zgłaszał fałszywe alarmy).
### Kolor
| Token | Jasny motyw | Ciemny motyw | Użycie |
|---|---|---|---|
| `--bg-color` | `#F7F5F1` (ciepły papier) | `#17140F` | tło strony |
| `--fg-color` | `#1C1B1A` (atrament) | `#F5F1E8` | tekst podstawowy |
| `--card-color` | `#FFFFFF` | `#1F1B14` | karty, panele |
| `--border-color` | `#E2DDD3` | `#332C21` | linie, obramowania |
| `--accent-color` | `#A13D2C` (pieczęć) | `#D4634A` | CTA, linki, akcenty |
| `--accent-hover-color` | `#8A3324` | `#E17B62` | hover na akcencie |
Zasada: **maksymalnie jeden akcent** (pieczęć-czerwień). Żadnych dodatkowych
kolorów „na szybko" (niebieski link, zielony success) bez dopisania do
`DESIGN.md` — to jeden z 4 checków „Your design system" w Impeccable.
### Typografia
| Token | Wartość | Użycie |
|---|---|---|
| `--font-heading` | Fraunces (serif, wariant *opsz* wysoki dla nagłówków display) | H1–H3, cytaty |
| `--font-sans` | Public Sans | body, UI, nawigacja, przyciski |
| Skala | 16px body / 1.6 line-height minimum | patrz `wymagania-projektowe-strony.md` §4 — nie schodzić poniżej |
**Twardy zakaz z katalogu Impeccable:** brak kursywy jako domyślnego stylu
nagłówka display („italic serif display headline" — reguła #1 na liście
anty-slop, patrz sekcja 5). Fraunces ma piękną kursywę i pokusa jest duża —
używać jej WYŁĄCZNIE jako pojedynczego akcentu na jednym słowie w hero (np.
„**po polsku**" pochylone w podtytule), nigdy jako stylu całego H1.
### Kształt i głębia
| Token | Wartość |
|---|---|
| `--radius-button` | 6px (umiarkowane zaokrąglenie — NIE „pill", NIE 20px+ blob) |
| Karty | radius 8–10px, cień delikatny (`box-shadow` 1 warstwa, nie „hairline + wide shadow" — patrz sekcja 5) |
| Obramowania | 1px `--border-color`, nigdy grube kolorowe paski z boku karty |
### Motyw wizualny „dokument urzędowy" (charakter, nie tylko tokeny)
To jest to, co ma odróżnić tę stronę od typowego SaaS-landingu i uzasadnić
prompt „efekty pasujące do biura podatkowego" bez wpadania w kicz:
- **Tekstura papieru**: bardzo subtelny noise/grain na tle sekcji jasnych
(opacity ~2-3%, `mix-blend-mode: multiply` lub SVG `feTurbulence` jako
tło) — sugeruje fakturę papieru, nie plastik. Jeden globalny efekt, nie
per-sekcja.
- **Linie jak w formularzu**: cienkie poziome linie `--border-color` jako
separator sekcji zamiast pełnych kolorowych bloków tła — metafora liniatury
dokumentu podatkowego.
- **Akcent „pieczęci"**: okrągły/owalny kształt w kolorze akcentu, używany
OSZCZĘDNIE — np. jako tło pod floating-stat w hero (już jest w kodzie:
`floatingStat`), jako marker przy cytatach klientów, jako obwódka wokół
liczby „20+" w sekcji Stats. Nie na każdym elemencie.
- **Typografia numeryczna**: liczby (20+, 100%, §4 Nr. 11) w Fraunces, duże,
z lekkim tabular-nums — czytają się jak wpis w rejestrze, nie jak KPI
dashboardu.
- **Zdjęcia**: kolor, nie stockowy błysk korporacyjny — patrz `02-strona-glowna.md`
§Hero i `05-o-nas.md` co do konkretnego kierunku (ciepłe światło, realne
biuro/dokumenty, nie białe tło + uśmiech do kamery w garniturze).
---
## 3. Tryby stron (Impeccable dobiera automatycznie, ale potwierdź)
| Strona | Tryb | Uzasadnienie |
|---|---|---|
| Home, Usługi, Jak się umówić, Kontakt | **Persuade** | mają przekonać i doprowadzić do WhatsApp |
| O nas, Stowarzyszenie | **Persuade** (miękki) | budują zaufanie, ale bez twardego CTA co drugi ekran |
| FAQ, strony prawne | **Read** | czytelność i skanowalność ważniejsze niż perswazja — długie teksty, listy, akapity |
| Panel Payload (admin) | **Operate** | poza zakresem tego planu (panel dostarcza plugin), ale nie dotykać wizualnie |
---
## 4. System motion (spójny, jedna specyfikacja dla całej strony)
Zamiast wymyślać animacje per sekcja od zera w każdym pliku `02`–`09`, każdy z
tych plików odwołuje się do jednego z poniższych wzorców. To gwarantuje
spójność i chroni przed „motion slop" (reguły #48–53 w katalogu).
| Nazwa wzorca | Efekt | Kiedy używać | Kiedy NIE używać |
|---|---|---|---|
| `reveal-up` | Fade-in + translateY(16–24px), stagger dzieci co ~0.08–0.14s, ease `[0.22,1,0.36,1]` (już użyty w Hero — reużyj tę samą krzywą wszędzie) | wejście każdej sekcji przy scrollu (raz, `whileInView`, `viewport={{ once: true }}`) | nie powtarzać animacji przy każdym ponownym scrollu — meczy |
| `parallax-tilt` | Pointer-tracked rotateX/rotateY, już zaimplementowany jako `useParallax3D` w Hero | WYŁĄCZNIE hero — nie kopiować na każdą sekcję ze zdjęciem, bo traci efekt wyjątkowości | karty usług, avatary, ikony |
| `count-up` | Liczby w Stats (20+, 100%) liczą się od 0 do wartości docelowej przy wejściu w viewport, ~800ms, bez odbicia (`ease-out`, NIE elastic/bounce — reguła #52) | blok Stats na home | gdziekolwiek indziej |
| `line-draw` | Cienka linia (`--border-color` lub akcent) „rysuje się" (`stroke-dashoffset`) przy wejściu w viewport, jako separator lub podkreślenie nagłówka sekcji | separator między sekcjami zamiast twardej krawędzi | pod każdym nagłówkiem H2 z osobna — max 2-3 razy na stronę |
| `stamp-in` | Element „pieczęci" (floating stat, badge zaufania) pojawia się ze skalą 0.9→1 + rotate -3°→0°, ease-out, BEZ overshoot | floating stat w hero, badge „§4 Nr. 11 StBerG" | przyciski, pola formularza |
| `sticky-progress` | Cienka linia postępu czytania na górze strony (jak zakładka w dokumencie), tylko na stronach `Read` (FAQ, prawne) | FAQ, Impressum, Datenschutz | strony `Persuade` |
**Twarde zasady motion (z katalogu anty-slop, sekcja 5):**
- Zero pulsującej kropki statusu, zero migającego kursora, zero auto-scrolling
marquee (loga/teksty), zero bounce/elastic easing na dialogach czy kartach.
- Zero „zoom on hover" na każdym zdjęciu z automatu — hover-zoom TYLKO tam,
gdzie zdjęcie jest linkiem do czegoś (np. karta usługi), nigdy na zdjęciu Janusza
w hero czy o-nas.
- Wszystkie animacje transform/opacity (nie animować `width`/`height`/`margin` —
powoduje layout shift, reguła #51).
- `prefers-reduced-motion: reduce` → wszystkie warianty wyżej wyłączone,
treść widoczna od razu (bez „utknięcia w opacity: 0" — reguła #56).
---
## 5. Checklista anty-slop — zawężona do realnego ryzyka tego projektu
Pełny katalog Impeccable ma 61 reguł w 9 kategoriach. Poniżej te, na które ten
konkretny brief (serif display font, dużo kart usług, dużo liczb, ciepła
paleta) jest szczególnie narażony — sprawdzić RĘCZNIE po każdym `/impeccable polish`,
niezależnie od automatycznego detektora:
| # | Ryzyko w tym projekcie | Dlaczego tu grozi | Test |
|---|---|---|---|
| Italic serif display headline | Fraunces zachęca do kursywy na całym H1 | H1 w hero i page-headerach ma być prosty, prosto stojący; kursywa max na 1 słowie |
| Cream/beige palette jako „domyślny wybór z automatu" | Nasze tło JEST ciepłe/kremowe | OK tylko dlatego, że jest to świadomy wybór spójny z metaforą „dokument" — ale reszta palety (akcent, kontrasty) musi być równie przemyślana, nie „zostawione domyślne" |
| Icon tile stacked above heading | ServicesList/ServicesDetailed mają ikony (fileText, calculator, shieldCheck...) | Ikona OBOK nagłówka albo bez zaokrąglonego „tile" w tle — nie kwadrat z zaokrąglonymi rogami nad każdym tytułem usługi |
| Identical card grids | 6-7 usług w ServicesDetailed, wszystkie tym samym wzorcem karty | Zróżnicować: pierwsza/najważniejsza usługa większa lub wyróżniona, reszta w siatce — nie 7× ta sama karta |
| Hero metric layout (duża liczba + mały label + statsy obok) | Blok Stats na home to dokładnie ten wzorzec (20+ / 100% / §4 Nr. 11) | Dopuszczalne TYLKO jeśli liczby mają realny kontekst (opis pod spodem już jest w danych) — nie ucinać opisów, nie zostawiać gołych liczb |
| Tiny numbered section labels (01/02/03) | Process ma 3 kroki | Numerować krokami z pełnym słowem („Krok 1"), nie małą cyfrą-ozdobnikiem obok nagłówka sekcji |
| Border accent / side-tab na kartach | Karty testimoniali, FAQ | Bez grubego kolorowego paska z boku — jeśli trzeba wyróżnić, użyć tła karty albo cienkiej górnej linii `line-draw`, nie side-tab |
| Nested cards | ContactInfo + PageHeader + karty usług mogą się złożyć w kartę-w-karcie | Maks. 1 poziom „karty" na sekcję |
| Generic marketing claims | Pokusa dopisania „najlepsza obsługa", „rewolucyjne rozliczenie" | Zero słów-wypełniaczy — patrz `PRODUCT.md` Tone. Każde zdanie ma nieść konkret (liczbę, termin, nazwę dokumentu) |
| Em-dash overuse | Ryzyko przy douzupełnianiu treści (FAQ, prawne) | Kropka między myślami, nie długi myślnik co zdanie |
| Gradient text / radial glow | Pokusa „unowocześnienia" hero przez glow za nagłówkiem | Zero gradientów na tekście, zero halo/spotlight za sekcją — kontrast i typografia robią robotę, nie poświata |
Procedura: po każdym `/impeccable polish` uruchom `npx impeccable detect` na
zbudowanej stronie, przejrzyj findings, DOPIERO wtedy przejdź przez tabelę
wyżej ręcznie (detektor łapie źródło/DOM, powyższe wymaga oceny projektowej —
kategoria „Design review" w Impeccable).
+291
View File
@@ -0,0 +1,291 @@
# Strona główna — `/pl/` i `/de/` (page id 1, slug `home`/`home`)
Sekcja po sekcji, w kolejności renderu. Wzorce animacji (`reveal-up`,
`parallax-tilt`, `count-up`, `line-draw`, `stamp-in`) odsyłają do
[01-design-system-impeccable.md](./01-design-system-impeccable.md) §4 — nie
powtarzam tu ich definicji, tylko gdzie je zastosować.
Istniejące pola/treść z `content-snapshot.json` są dobre jakościowo — poniżej
zaznaczam **[ZACHOWAĆ]** gdzie treść zostaje, **[DOPRACOWAĆ]** gdzie proponuję
zmianę, **[NOWE]** gdzie brakuje elementu.
---
## 0. Element globalny: floating WhatsApp button
Nie jest osobnym blokiem strony — to element w layout (`(frontend)/[locale]/layout.tsx`),
widoczny na WSZYSTKICH podstronach, nie tylko home. Opisuję tu, bo determinuje
przestrzeń na hero.
- **Treść**: ikona WhatsApp + `whatsappNumber` z globala Company (już istnieje
w schemacie), link `https://wa.me/{whatsappNumber}`.
- **Layout**: sticky, prawy-dolny róg, 56×56px na desktopie / 52×52px mobile,
zawsze nad treścią (z-index ponad ThemeSwitcher).
- **Animacja**: `stamp-in` przy pierwszym renderze (raz), potem statyczny —
ŻADNEGO pulsowania w pętli (reguła anty-slop „pulsing status dot").
Delikatny scale 1→1.05 TYLKO na hover, bez bounce.
- **Widoczność**: ukryty, gdy użytkownik jest w obrębie sekcji FinalCTA (tam
i tak jest duży przycisk WhatsApp — dublowanie dwóch identycznych CTA na
ekranie naraz to szum, nie pomoc) — pokazuje się ponownie po przescrollowaniu dalej.
- **a11y**: `aria-label="Napisz do nas na WhatsApp"` / `"Auf WhatsApp schreiben"`,
widoczny fokus, osiągalny Tabem.
---
## 1. Hero (`blockType: hero`)
**[ZACHOWAĆ treść, DOPRACOWAĆ wygląd]** — treść PL/DE jest mocna („Odbierz
zwrot podatku z Niemiec / Rozliczymy Cię po polsku"), nic nie zmieniam
w kopii poza jednym punktem niżej.
| Pole (CMS) | Treść |
|---|---|
| `title` | Odbierz zwrot podatku z Niemiec *(bez zmian)* |
| `titleAccent` | Rozliczymy Cię po polsku — **tu, i tylko tu, dopuszczalna kursywa Fraunces na słowie „po polsku"** (patrz zakaz italic-display w [01](./01-design-system-impeccable.md) §5) |
| `subtitle` | *(bez zmian)* |
| `primaryCta` | Napisz na WhatsApp *(bez zmian, prowadzi do `wa.me`)* |
| `secondaryCta` | Zobacz jak to działa → **[DOPRACOWAĆ]** `url` obecnie `#jak-to-dziala`, ale na stronie nie ma sekcji o tym `id` (proces jest w bloku `process` bez ustawionego `id="jak-to-dziala"`) — dodać `id` do sekcji Process (pkt 6 niżej) albo zmienić link na realny anchor. Martwy link kotwicowy to błąd funkcjonalny, nie tylko wizualny. |
| `floatingStat` | 20+ / Lat doświadczenia *(bez zmian)* |
| `image` / `imageSecondary` | patrz niżej |
**Zdjęcia (obecnie puste — krytyczny brak):**
- `image` (główne, duże): Janusz Kędzierski w naturalnym otoczeniu pracy —
NIE studio z białym tłem, NIE stockowe zdjęcie „uśmiechnięty biznesmen".
Kierunek: biurko z dokumentami/laptopem, ciepłe światło dzienne, kadr 4:5
lub 3:4 (pionowy, żeby zmieścić parallax-tilt bez przycinania twarzy).
- `imageSecondary` (mała, nakładająca się karta w rogu głównego zdjęcia — tak
sugeruje istniejący layout z dwoma obrazami): detal — dłoń podpisująca
dokument, kalkulator + Lohnsteuerbescheinigung, albo logo/pieczątka firmy.
Wzmacnia metaforę „dokument", nie duplikuje twarzy z głównego zdjęcia.
- Jeśli zdjęcia klienta nie będą gotowe na start: NIE wstawiać stockowego
zdjęcia przypadkowej osoby (to prawdziwa firma, fałszywa twarz = ryzyko
zaufania i prawne). Lepszy tymczasowy wariant: zdjęcie dokumentów/biurka
bez osoby, dopóki zdjęcie Janusza nie będzie gotowe.
**Layout:** dwie kolumny na desktopie (tekst lewo, zdjęcie prawo — układ już
zaimplementowany), pełna szerokość na mobile z tekstem NAD zdjęciem (czytelność
przed obrazem na małym ekranie).
**Animacja:** `reveal-up` na blok tekstowy (już jest — stagger 0.14s, zachować),
`parallax-tilt` WYŁĄCZNIE na `image` główne (już jest, `useParallax3D` —
zachować, nie dodawać do `imageSecondary`, żeby nie kręciło się dwoma
warstwami naraz), `stamp-in` na `floatingStat`.
**Tło:** tekstura papieru (grain, patrz [01](./01-design-system-impeccable.md) §2)
na całej sekcji hero, bardzo subtelna. Bez gradientowego halo za nagłówkiem.
---
## 2. TrustBar (`blockType: trustBar`)
**[ZACHOWAĆ treść]** — 4 punkty (b.b.h., 100% po polsku, wsparcie w US,
wieloletnie doświadczenie) to dobry pasek zaufania od razu pod hero.
**Layout:** pozioma belka, 4 pozycje w rzędzie na desktopie (2×2 na tablet,
pionowa lista na mobile), ikona + tekst, separator to cienka pionowa linia
`--border-color` między pozycjami (nie karty z cieniem — to pasek, nie grid kart).
**Tło:** kontrastowe względem hero — `--card-color` (biała belka na papierowym
tle) LUB odwrotnie cienka linia `line-draw` nad i pod paskiem zamiast pełnego tła.
**Animacja:** `reveal-up` ze stagger 0.08s na 4 pozycje, trigger przy wejściu
w viewport (pasek jest tuż pod hero, więc to będzie prawie natychmiastowe przy
scrollu — subtelne, nie efekciarskie).
---
## 3. UniqueValue (`blockType: uniqueValue`)
**[ZACHOWAĆ treść]** „Rozliczenia bez bariery językowej" — jasny, jeden
argument różnicujący.
**Zdjęcie (`image`, puste):** kadr pokazujący RELACJĘ, nie dokument — np.
rozmowa (telefon/WhatsApp w ręku) albo dłonie przy wspólnym przeglądaniu
dokumentów. To sekcja o barierze językowej, więc obraz powinien sugerować
KOMUNIKACJĘ, nie biurokrację (ta metafora jest już w hero).
**Layout:** dwie kolumny, zdjęcie i tekst na przemian względem hero (jeśli
hero ma tekst-lewo/zdjęcie-prawo, tu odwrotnie — zdjęcie-lewo/tekst-prawo) —
prosty rytm wizualny przy scrollu, bez potrzeby dodatkowych efektów.
**Features (`features[]`):** 2 pozycje („Bez barier językowych",
„Indywidualne podejście") — renderować jako checkmarki, nie jako osobne karty
(to są 2 punkty, karta na 2 punkty to nested-card/overkill).
**Animacja:** `reveal-up`, zdjęcie i tekst wchodzą z lekkim przesunięciem
w przeciwnych kierunkach (zdjęcie z boku, tekst z dołu) — wystarczy, żeby
nie było identyczne z sekcją 5 (Stats) czy 6 (ServicesList).
---
## 4. Stats (`blockType: stats`)
**[ZACHOWAĆ treść, DOPRACOWAĆ animację]** 20+ lat / 100% po polsku / §4 Nr. 11.
To dokładnie wzorzec „hero metric layout" z katalogu anty-slop — dopuszczalny
TU, bo każda liczba ma realny opis pod spodem (`description`), ale wymaga
świadomego wykonania:
**Layout:** 3 kolumny równej wagi (nie jedna duża + dwie małe — to nie jest
hierarchia ważności, to 3 równorzędne dowody), separator cienką pionową linią.
**Animacja:** `count-up` na wartościach numerycznych (20+, 100%) — UWAGA:
„§4 Nr. 11" to nie jest liczba do zliczania, tylko oznaczenie paragrafu —
zostaje statyczne, bez count-up (fałszywe zastosowanie count-up na tekście
byłoby zauważalnym błędem). `line-draw` pod całą sekcją jako domknięcie.
**Tło:** pełna szerokość, `--card-color` lub delikatnie inny odcień papieru
niż otoczenie, żeby sekcja miała optyczną „ramkę" bez rysowania karty wokół
każdej liczby osobno.
---
## 5. ServicesList (`blockType: servicesList`)
**[ZACHOWAĆ treść]** 3 usługi (Deklaracje, Kontrola decyzji, Ulgi i dopłaty) —
to skrócona wersja pełnej listy z `/uslugi` (7 usług, patrz [03-uslugi.md](./03-uslugi.md)).
**Layout:** 3 karty w rzędzie (1 kolumna mobile), każda z `linkText` → link do
`/uslugi#<kotwica-usługi>` (obecnie `linkText: "Zobacz więcej"` bez `linkUrl`
w polu — **[DOPRACOWAĆ]** dodać pole `linkUrl` do configu bloku jeśli go nie
ma, bo aktualnie te trzy „Zobacz więcej" nie mają dokąd prowadzić poza całą
stroną `/uslugi`).
**Animacja:** `reveal-up` stagger 0.1s na 3 karty. Bez ikon w kwadratowych
„tile" nad tytułem (reguła anty-slop) — jeśli ikona, to mała, obok tytułu.
**Tło:** neutralne, bez zmiany względem otoczenia — ta sekcja ma być spokojna,
kontrast wizualny rezerwujemy dla Stats i Affiliation.
---
## 6. Process (`blockType: process`, drugi na stronie — pierwszy jest na
`/jak-sie-umowic`)
**[ZACHOWAĆ treść, DOPRACOWAĆ funkcjonalnie]** 3 kroki (WhatsApp → dokumenty →
zwrot).
- **[DOPRACOWAĆ]** dodać `id="jak-to-dziala"` do sekcji (naprawia martwy
`secondaryCta.url` z hero, patrz §1).
- `ctaUrl` już poprawnie wskazuje `/pl/jak-sie-umowic` — zachować.
- `image` (puste): zdjęcie/ilustracja procesu — NIE trzy identyczne ikony w
kółkach z numerem 1/2/3 (to dokładnie wzorzec „tiny numbered section
labels"/„icon tile" połączony). Zamiast tego: jedno zdjęcie kontekstowe
(np. dokumenty na biurku) obok listy kroków, kroki numerowane pełnym słowem
„Krok 1", „Krok 2", „Krok 3" w Fraunces, nie małą cyfrą-ozdobnikiem.
**Layout:** lista kroków pionowo po lewej z cienką pionową linią `line-draw`
łączącą numery kroków (metafora „ścieżki"), zdjęcie po prawej, sticky przy
scrollu do wysokości listy kroków (zdjęcie zostaje w miejscu, kroki
przewijają się obok — efekt „prowadzenia za rękę").
**Animacja:** `line-draw` rysuje się w dół w miarę scrollowania przez sekcję
(scroll-linked, nie viewport-trigger-once — to jedyne miejsce na stronie
głównej, gdzie animacja jest powiązana z postępem scrolla, nie jednorazowym
wejściem w viewport — używać oszczędnie, dokładnie tu ma sens narracyjny).
---
## 7. Affiliation (`blockType: affiliation`)
**[ZACHOWAĆ treść, UZUPEŁNIĆ media]** „Zaufanie i bezpieczeństwo" — kluczowa
sekcja prawna/zaufania (b.b.h., §4 Nr. 11 StBerG).
**`logo` (puste):** logo b.b.h. Lohnsteuerhilfeverein e.V. — klient wspomniał,
że je ma (patrz [10-architektura-cms.md](./10-architektura-cms.md) §1, dane
wejściowe). Bez logo ta sekcja jest gołym tekstem i traci najmocniejszy
dowód wiarygodności, jaki strona może pokazać.
**`trustPoints` (obecnie puste `[]`):** **[NOWE — wypełnić]** propozycja treści:
- „Licencjonowana pomoc podatkowa (§4 Nr. 11 StBerG), nie samozwańcze doradztwo"
- „Członkostwo w b.b.h. Lohnsteuerhilfeverein e.V. — stowarzyszeniu działającym w całych Niemczech"
- „Pełna odpowiedzialność zawodowa i ubezpieczenie w ramach stowarzyszenia"
DE odpowiednio: „Zugelassene Lohnsteuerhilfe (§4 Nr. 11 StBerG)...", itd.
**Layout:** logo b.b.h. widoczne, blok tekstu obok (nie pod spodem —
wiarygodność ma być na pierwszy rzut oka, nie po przeczytaniu akapitu),
`trustPoints` jako krótka lista z checkmarkiem, `linkText`/`linkUrl` prowadzi
do `/o-nas` (obecnie) — do rozważenia przekierowanie zamiast do `/stowarzyszenie`,
skoro ta strona istnieje właśnie po to, żeby rozwinąć temat b.b.h. (patrz
[07-stowarzyszenie.md](./07-stowarzyszenie.md)).
**Tło:** to jest kandydat na jedyne miejsce na stronie z delikatnie innym tłem
niż papier — np. bardzo blady odcień akcentu (2-3% `--accent-color` jako tło)
albo obramowanie w kolorze pieczęci, żeby sekcja „prawna" wizualnie
odróżniała się jako punkt zaufania, nie kolejny akapit.
**Animacja:** `stamp-in` na logo (wchodzi jak przybita pieczęć), `reveal-up`
na resztę.
---
## 8. Testimonials (`blockType: testimonials`)
**[ZACHOWAĆ treść]** 3 opinie (Piotr/Monachium, Anna/Berlin, Krzysztof/Dortmund)
— konkretne, z imieniem i miastem, dobra jakość dowodu społecznego.
**Layout:** NIE karuzela z auto-scrollującym marquee (zakaz w katalogu
anty-slop). Zamiast tego: 3 karty statyczne obok siebie na desktopie (stack
pionowy na mobile), każda z dużym znakiem cudzysłowu w Fraunces jako element
graficzny (spójne z motywem „dokumentu"/pieczęci), bez zdjęć profilowych
(nie ma ich w danych — nie wymyślać awatarów).
**Animacja:** `reveal-up` stagger 0.12s. Bez zoom-on-hover na kartach.
**Tło:** neutralne, spokojne — to sekcja do czytania, nie do „wow".
---
## 9. FAQTeaser (`blockType: faqTeaser`)
**[ZACHOWAĆ treść — 8 pytań]** ale to dużo jak na „teaser". Na stronie
głównej pokazywać TYLKO pierwsze 4-5 pytań (najczęstsze/najkrótsze odpowiedzi),
z wyraźnym CTA „Zobacz wszystkie pytania →" prowadzącym do pełnej strony
`/faq` (patrz [06-faq.md](./06-faq.md)) — **[DOPRACOWAĆ]** obecny blok nie ma
pola na link do pełnego FAQ ani limitu liczby pytań; dodać `ctaUrl`/`ctaText`
do configu, analogicznie do bloku `process`.
**Layout:** accordion (pytanie klika się, odpowiedź rozwija) — jedno otwarte
naraz, żeby lista nie „skakała" w dół przy każdym kliknięciu. Ikona plus/minus
lub chevron obracający się o 180°, transform nie layout-affecting (zgodnie
z zasadą motion w [01](./01-design-system-impeccable.md) §4).
**Animacja:** rozwijanie odpowiedzi: `height: auto` przez `AnimatePresence`/
`useMeasure` (Framer Motion), 200-250ms, bez bounce.
---
## 10. FinalCTA (`blockType: finalCta`)
**[ZACHOWAĆ treść]** „Gotowy na wyższy zwrot podatku? / Rozpocznij na WhatsApp".
**Layout:** pełna szerokość, wyraźnie oddzielona od reszty strony (to ostatni
akord przed stopką) — duży przycisk WhatsApp, wyśrodkowany, otoczony
spokojnym tłem.
**Tło:** jedyne miejsce, gdzie dopuszczalny mocniejszy akcent koloru — np.
pełne tło w `--accent-color` (ciemna pieczęć-czerwień) z jasnym tekstem, jako
wizualny „stempel domykający" stronę. To jest świadome odejście od
neutralnego papieru — ma sygnalizować „koniec dokumentu, czas na podpis/akcję".
**Animacja:** `stamp-in` na cały blok (skala + lekki obrót, jak przybicie
pieczątki na końcu formularza) — to najbardziej „efektowne" miejsce na
stronie, uzasadnione tym, że to jedyny call-to-action, który się tu pojawia.
---
## 11. Nowa sekcja do rozważenia: wideo „Co to jest Lohnsteuerhilfe"
Inspiracja z bbh (mają dedykowaną sekcję wideo). **[NOWE — faza 2, nie
blokuje startu]** — wymaga nagrania materiału (Janusz tłumaczy po polsku, czym
jest doradztwo podatkowe i dlaczego warto skorzystać z uprawnionego
Lohnsteuerhilfeverein zamiast np. samodzielnego rozliczenia). Realna wartość:
(a) SEO (wideo + transkrypcja), (b) zaufanie (twarz + głos silniej buduje
relację niż tekst), (c) wyjaśnienie niszowego tematu (Lohnsteuerhilfeverein to
pojęcie nieznane większości odwiedzających).
Jeśli/gdy powstanie: nowy blok `VideoSection` (pole `video` jako `upload` do
R2/storage lub `videoUrl` do YouTube/Vimeo embed, `poster` jako `upload→media`,
`title`, `description`) — umieszczony między sekcją 6 (Process) a 7
(Affiliation). Nie blokuje uruchomienia strony bez tej sekcji.
+92
View File
@@ -0,0 +1,92 @@
# Usługi / Leistungen — `/pl/uslugi` i `/de/leistungen` (page id 2)
Bloki: `pageHeader` → `servicesDetailed` → `eligibility` → `finalCta`.
Wzorce animacji: patrz [01-design-system-impeccable.md](./01-design-system-impeccable.md) §4.
---
## 1. PageHeader (`blockType: pageHeader`)
**[ZACHOWAĆ treść]** „Kompleksowe rozliczenia podatkowe dla Polaków w Niemczech".
**Layout:** prosty nagłówek strony — H1 + subtitle, wycentrowany lub do lewej
(spójnie z resztą page-headerów w serwisie), bez zdjęcia tła (to strona typu
„Read/Persuade mieszany" — treść ma się liczyć, nie hero-wizual po raz drugi).
**Tło:** cienka linia `line-draw` pod nagłówkiem jako separator do sekcji usług
— to page-header, nie hero, więc bez tekstury/parallax, subtelniej niż na home.
**Animacja:** `reveal-up`, pojedyncze wejście, bez stagger (dwa elementy: H1 + subtitle).
---
## 2. ServicesDetailed (`blockType: servicesDetailed`)
**[ZACHOWAĆ treść — 7 usług]** Deklaracja podatkowa, wstępne obliczenie
zwrotu, kontrola decyzji, odwołania, całoroczne doradztwo, klasa podatkowa,
ulgi/Kindergeld. Treść konkretna i kompletna — nie zmieniam.
**Ryzyko anty-slop:** 7 identycznych kart z ikoną = klasyczny wzorzec
„identical card grids" + „icon tile stacked above heading" z katalogu. Musi
zostać rozbite:
**Layout — dwupoziomowa hierarchia zamiast jednej siatki:**
- **Usługa #1 „Sporządzenie deklaracji podatkowej"** wyróżniona jako pozycja
główna, szersza karta (2 kolumny szerokości na desktopie), z ikoną OBOK
tytułu (nie nad, nie w kwadratowym tile) i pełnym opisem widocznym od razu —
to jest usługa, po którą przychodzi 90% odwiedzających.
- Pozostałe 6 usług w siatce 2×3 (desktop) / 1 kolumna (mobile), karty
jednolite ale mniejsze niż wyróżniona, z ikoną małą, inline z tytułem.
- Każda karta ma cienki górny akcent (`line-draw` przy wejściu w viewport),
NIE grubą kolorową krawędź z boku (zakaz side-tab).
**Ikony:** już zmapowane w danych (`fileText`, `calculator`, `shieldCheck`,
`scale`, `helpCircle`, `users`, `coins` — prawdopodobnie lucide-react, zgodnie
z resztą projektu). Renderować w kolorze `--accent-color`, rozmiar
proporcjonalny do tekstu (nie oversized — reguła „massive icons").
**Animacja:** `reveal-up` stagger 0.08s po kolei, karta wyróżniona wchodzi
jako pierwsza i lekko większa amplituda (24px zamiast 16px), żeby podkreślić
hierarchię ruchem, nie tylko rozmiarem.
---
## 3. Eligibility (`blockType: eligibility`)
**[ZACHOWAĆ treść]** „Dla kogo — zakres uprawnień wg §4 Nr. 11 StBerG" —
merytorycznie kompletna (kto może skorzystać / limity dochodów dodatkowych
18 000€/36 000€ / kto jest wykluczony). To jedna z najważniejszych sekcji na
całej stronie prawnie — Beratungsbefugnis jest podstawą działania firmy.
**Layout — kluczowe: to NIE jest sekcja marketingowa, to jest informacja
prawna, więc traktować wizualnie jak fragment dokumentu, nie jak feature-grid:**
- Dwie kolumny obok siebie: **„Kto może skorzystać"** (lista z ✓, kolor
neutralny/zielonkawy stonowany, nie jaskrawy) vs **„Kogo NIE obejmują nasze
uprawnienia"** (lista z ✕, kolor stonowany, nie agresywny czerwony — to nie
jest błąd/ostrzeżenie, to fakt prawny).
- `limitationsText` (limity 18 000€/36 000€) jako osobny, wyraźnie
wydzielony akapit między dwiema kolumnami a `legalNotice` — to najbardziej
„techniczny" fragment i ludzie go pomijają, jeśli nie ma wizualnego zaczepu
(np. cienka ramka, mała ikona dokumentu/paragrafu z boku).
- `legalNotice` (podstawa prawna) na samym dole, mniejszym tekstem, jako
formalne domknięcie — jak stopka dokumentu prawnego, nie call-to-action.
**Tło:** delikatnie wydzielone od reszty strony (np. `--card-color` na całą
sekcję, cienka ramka `--border-color` dookoła) — sygnalizuje „to jest
oficjalna informacja, nie marketing".
**Animacja:** BEZ efektownego wejścia — `reveal-up` bardzo subtelny (8px, nie
24px) albo brak animacji w ogóle. To sekcja do przeczytania w spokoju, ruch
tu odwracałby uwagę od treści prawnej.
**Uwaga treściowa (nie wizualna, ale ważna):** limity 18 000€/36 000€ i
podstawa `§4 Nr. 11 StBerG` to dane prawne, które mogą się zmieniać rok do
roku — do weryfikacji z klientem przed publikacją, że kwoty są aktualne na
2026 (nie kopiować bez sprawdzenia, to nie jest zakres tego planu wizualnego).
---
## 4. FinalCTA
**[ZACHOWAĆ treść]** identyczny wzorzec jak w [02-strona-glowna.md](./02-strona-glowna.md)
§10 — spójność między stronami jest tu ważniejsza niż wariacja.
+79
View File
@@ -0,0 +1,79 @@
# Jak się umówić / Terminvereinbarung — `/pl/jak-sie-umowic` i
`/de/terminvereinbarung` (page id 3)
Bloki: `pageHeader` → `process` → `contactInfo` → `finalCta`. To strona o
najniższym progu wątpliwości — ktoś, kto tu trafia, jest już prawie
zdecydowany. Cel wizualny: nie stawiać żadnej przeszkody, potwierdzić że
„to naprawdę jest proste".
---
## 1. PageHeader
**[ZACHOWAĆ treść]** „Jak się umówić" / „Prosty, przejrzysty i w 100% zdalny
proces". Layout jak w [03-uslugi.md](./03-uslugi.md) §1 — spójny wzorzec
page-header w całym serwisie.
---
## 2. Process (`blockType: process`, pełna wersja — 3 kroki)
**[ZACHOWAĆ treść]** WhatsApp → dokumenty → gotowe rozliczenie do podpisu.
To jest ROZWINIĘTA wersja tych samych 3 kroków co na home (tam skrócone jako
teaser) — musi wyglądać podobnie, ale bardziej szczegółowo, nie jak inny
komponent.
**Layout:** pionowa oś czasu (timeline) na całą szerokość kolumny treści —
numer kroku w kółku po lewej połączony pionową linią `line-draw` z kolejnym
krokiem, tytuł + pełny opis po prawej. To już opisany wzorzec z home §6, tu
pełniejszy (dłuższe opisy — np. wymienione konkretne dokumenty:
Lohnsteuerbescheinigung, IdNr/PESEL).
**Zdjęcie (`image`, puste):** jedno zdjęcie kontekstowe obok osi czasu —
propozycja: dłonie trzymające telefon z otwartym WhatsAppem + dokumenty na
stole obok. Łączy wizualnie 3 kroki (komunikacja + dokumenty) w jednym kadrze,
zamiast szukać osobnego zdjęcia do każdego z 3 kroków (co prowadziłoby do
zbyt rozdrobnionej, „stockowej" sekcji).
**Animacja:** `line-draw` scroll-linked (linia oś czasu rysuje się w miarę
przewijania — dokładnie ten sam wzorzec co na home, świadomie powtórzony, bo
to ta sama treść w rozwiniętej formie — powtórzenie tu buduje rozpoznawalność,
nie jest duplikacją bez sensu).
---
## 3. ContactInfo (`blockType: contactInfo`)
**[WYMAGA DANYCH OD KLIENTA]** obecnie `address: "DO POTWIERDZENIA PRZEZ
KLIENTA"`, telefon i e-mail placeholder — patrz [10-architektura-cms.md](./10-architektura-cms.md) §1.
Nie da się tego sensownie zaprojektować bez realnych danych — poniżej sam
wygląd, niezależny od treści.
**Layout:** karta w formie „wizytówki" — adres, telefon (klikalny `tel:`),
e-mail (klikalny `mailto:`), godziny — 2×2 grid ikon+tekstu na desktopie,
pionowa lista na mobile. Traktować jak fragment papeterii firmowej: cienka
ramka, może z delikatnym narożnikiem „zagięcia rogu" (subtelny `box-shadow`
sugerujący kartkę, nie dosłowny origami-efekt).
**Animacja:** `reveal-up`, brak dodatkowych efektów — to czysta informacja
użytkowa, ktoś tu szuka faktu (numeru telefonu), nie doświadczenia.
---
## 4. FinalCTA
**[ZACHOWAĆ treść]** „Chcesz szybko odzyskać podatek?" — spójny wzorzec, patrz
[02-strona-glowna.md](./02-strona-glowna.md) §10.
---
## Uwaga UX: ta strona i WhatsApp floating button
Na tej konkretnej stronie floating WhatsApp button (patrz
[02-strona-glowna.md](./02-strona-glowna.md) §0) jest szczególnie istotny —
to strona, na którą ktoś trafia PO decyzji „chcę się umówić", więc przycisk
musi być widoczny od pierwszego ekranu, nie dopiero po scrollu do FinalCTA.
Nie ukrywać go tu w obrębie sekcji Process/ContactInfo (tylko w obrębie samego
FinalCTA, zgodnie z regułą ogólną) — to jedyne odstępstwo od reguły „ukryj przy
FinalCTA" wspomnianej w pliku 02, bo tu jest tylko jeden FinalCTA na dole, a
reszta strony powinna mieć stały dostęp do CTA.
+81
View File
@@ -0,0 +1,81 @@
# O nas / Über uns — `/pl/o-nas` i `/de/uber-uns` (page id 4)
Bloki: `pageHeader` → `bio` → `team` → `finalCta`.
**Otwarta kwestia do potwierdzenia z klientem przed budową tej strony:** dane
w `content-snapshot.json` pokazują `team.members` z JEDNĄ osobą (Janusz
Kędzierski, „Właściciel / Beratungsstellenleiter"). Jeśli faktycznie firma to
tylko Janusz — poniższy plan pasuje bez zmian. Jeśli firma zatrudnia więcej
osób/doradców — sekcja `team` (§3) wymaga realnych danych (imiona, role,
zdjęcia) zanim zostanie zbudowana; nie wypełniać jej wymyślonymi osobami.
Traktuję to jak `address: "DO POTWIERDZENIA PRZEZ KLIENTA"` — jako otwarty
punkt, nie zakładam żadnej liczby.
---
## 1. PageHeader
**[ZACHOWAĆ treść]** „O nas / Ponad 20 lat rzetelnego wsparcia..." — spójny
wzorzec page-header.
---
## 2. Bio (`blockType: bio`)
**[ZACHOWAĆ treść]** dwa akapity + `credentials` (4 punkty: 20 lat praktyki,
Beratungsstellenleiter w b.b.h., obsługa PL/DE, maksymalizacja zwrotu).
**Zdjęcie (`image`, obecnie wskazuje media ID 1 = puste):** to NAJWAŻNIEJSZE
zdjęcie na całej stronie po hero — to jest twarz firmy. Kierunek:
- Portret Janusza, kadr pionowy, naturalne otoczenie pracy (nie białe tło
studyjne — to osłabia „ciepłe, ludzkie" pozycjonowanie, które reszta strony
buduje przez papier/dokument-motyw).
- Spojrzenie w kamerę lub lekko w bok, spokojny wyraz — nie sztuczny
korporacyjny uśmiech.
- Jeśli dostępne dodatkowe zdjęcia biura/otoczenia pracy — dobre jako tło lub
drugi mniejszy kadr obok (podobnie jak `imageSecondary` w hero).
**Layout:** zdjęcie po jednej stronie (sugeruję lewo, żeby odróżnić od hero,
gdzie zdjęcie jest po prawej — daje to stronie własny rytm, nie kopię hero),
tekst + `credentials` po drugiej. `credentials` jako pionowa lista z małym
checkmarkiem lub myślnikiem w kolorze akcentu — nie 4 osobne karty (to tylko
4 krótkie linie, karta na jedną linię tekstu to nested-card/overkill).
**Animacja:** `parallax-tilt` na zdjęciu — TU jest drugie i ostatnie miejsce
na stronie, gdzie ten efekt się powtarza po hero (dozwolone świadome
powtórzenie na stronie „O nas", bo to również portret osoby — spójność
motywu „ożywionego dokumentu/zdjęcia" bez rozmnażania efektu na każdą sekcję
serwisu, patrz zakaz w [01](./01-design-system-impeccable.md) §4).
---
## 3. Team (`blockType: team`)
Patrz nota na górze pliku. Jeśli zostaje 1 osoba (Janusz):
**[DOPRACOWAĆ — rozważyć usunięcie/scalenie z Bio]** blok `team` z jedną
osobą, która jest tą samą osobą co w `bio` bezpośrednio nad nim, tworzy
wizualną redundancję — to samo zdjęcie/opis dwa razy pod rząd. Dwie opcje:
- **(A) Zostawić `team` jako osobny blok** tylko jeśli w przyszłości dojdą
kolejne osoby — wtedy warto mieć gotową strukturę i nie przebudowywać
strony później. W takim wypadku na razie renderować jako pojedynczą,
spokojną kartę „wizytówkową" (nie grid na 1 element — grid sugeruje że
czegoś brakuje).
- **(B) Pominąć render bloku `team`, gdy `members.length === 1`** i tekstowo
wzmocnić `bio` o rolę/kontakt zamiast duplikować — prostsze, unika
redundancji, ale wymaga zmiany w komponencie (`Team/Component.tsx`),
patrz [10-architektura-cms.md](./10-architektura-cms.md) §3.
Rekomendacja: (B), chyba że klient potwierdzi, że dojdą kolejne osoby w
krótkim terminie — wtedy (A).
Jeśli firma jednak zatrudnia większy zespół (do potwierdzenia — patrz nota na
górze): renderować jako siatkę kart (foto + imię + rola + krótki opis), 3 w
rzędzie desktop / 1 mobile, `bookingUrl` z każdej karty prowadzi do `/kontakt`
(już jest w danych).
---
## 4. FinalCTA
**[ZACHOWAĆ treść]** „Gotowy na rozliczenie podatku?" — spójny wzorzec.
+82
View File
@@ -0,0 +1,82 @@
# FAQ — `/pl/faq` i `/de/faq` (page id 5)
**Stan obecny: pusta.** Layout to `TextSection` z treścią `"Treść w
przygotowaniu"` — mimo że strona główna ma już `faqTeaser` z 8 gotowymi
pytaniami. To najszybszy do naprawienia brak w całym serwisie: treść już
istnieje, trzeba ją tylko przenieść na dedykowaną stronę i rozbudować.
---
## 1. Zmiana blokowa (wymagana, nie tylko treściowa)
`TextSection` (pojedynczy blok tekstowy) nie nadaje się do renderowania
listy pytań-odpowiedzi z akordeonem i danymi strukturalnymi. Potrzebny jest
blok dedykowany — patrz [10-architektura-cms.md](./10-architektura-cms.md)
§2 po specyfikację pola. W skrócie: reużyć strukturę `faqTeaser` (ma już
pole `questions[{question, answer}]`), ale jako pełną, niekróconą wersję
z opcjonalnym grupowaniem w kategorie.
---
## 2. Treść — reorganizacja istniejących 8 pytań w kategorie
Obecne pytania z `faqTeaser` na home są dobre i się nie duplikują treściowo —
przenieść 1:1, tylko pogrupować pod nagłówkami kategorii dla skanowalności
(strona `Read`, nie `Persuade` — priorytet to łatwość znalezienia odpowiedzi):
**Kategoria „Proces i dokumenty"**
- Czy muszę przyjeżdżać osobiście do biura?
- Jakie dokumenty są potrzebne do rozliczenia?
- Do kiedy muszę złożyć deklarację podatkową w Niemczech?
**Kategoria „Zwrot podatku i koszty"**
- Jak długo czeka się na zwrot podatku z urzędu skarbowego?
- Ile kosztuje rozliczenie podatku z Niemiec?
**Kategoria „Świadczenia dodatkowe"**
- Czy załatwiacie również zasiłek Kindergeld? *(w danych występuje 2×, prawie
identyczne pytanie — połączyć w jedno przy migracji na tę stronę, nie
duplikować)*
**[NOWE — sugerowane pytania do uzupełnienia, wymagają weryfikacji merytorycznej
klienta przed publikacją]** — typowe pytania w tej branży, których brakuje:
- „Czy mogę się rozliczyć, jeśli pracowałem w Niemczech tylko kilka miesięcy?"
- „Co się stanie, jeśli spóźnię się ze złożeniem deklaracji?"
- „Czy mogę rozliczyć się wspólnie z małżonkiem, jeśli on/ona nie pracuje w Niemczech?"
- „Czy pomagacie też w rozliczeniu za lata wcześniejsze (wsteczne)?"
Zaznaczam je jako propozycję TEMATÓW, nie gotowe odpowiedzi — treść
merytoryczna (terminy, kwoty, warunki) musi pochodzić od klienta/doradcy
podatkowego, nie być domyślana. Widoczny placeholder do wypełnienia w panelu.
---
## 3. Layout
- Nagłówek strony (spójny page-header jak w innych podstronach) + krótki
wstęp („Nie znalazłeś odpowiedzi? Napisz na WhatsApp" z linkiem — most do
konwersji nawet na stronie czysto informacyjnej).
- Kategorie jako sekcje z nagłówkiem H2, pod nimi akordeon pytań (H3 per
pytanie, poprawna hierarchia nagłówków — `wymagania-projektowe-strony.md`
§4 wymaga braku przeskoków poziomów).
- Jedno pytanie otwarte naraz w obrębie kategorii (spójnie z `faqTeaser` na
home, patrz [02-strona-glowna.md](./02-strona-glowna.md) §9).
- Opcjonalnie: pole wyszukiwania/filtrowania pytań na górze, jeśli lista
urośnie powyżej ~15 pozycji — na start (12 pytań) niepotrzebne, dodać
dopiero gdy lista faktycznie się rozrośnie (nie budować „na zapas" —
`fundamenty-projektu.md` §6).
## 4. Tło i animacja
Strona typu **Read** (patrz [01](./01-design-system-impeccable.md) §3) —
`sticky-progress` (cienka linia postępu czytania na górze) jako jedyny efekt
motion poza standardowym `reveal-up` na wejściu każdej kategorii. Tekstura
papieru z hero TU pomijamy — długi tekst do czytania potrzebuje maksymalnego
spokoju tła, nie dekoracji.
## 5. SEO
Ta strona to naturalny kandydat na `FAQPage` structured data (schema.org) —
pytania i odpowiedzi 1:1 z treścią widoczną na stronie (wymóg Google, nie
ukryty tekst). Szczegóły implementacji w
[11-integracje-seo-wydajnosc.md](./11-integracje-seo-wydajnosc.md) §2.
+95
View File
@@ -0,0 +1,95 @@
# Stowarzyszenie / Verein — `/pl/stowarzyszenie` i `/de/verein` (page id 7)
**Stan obecny: pusta** (`TextSection` = „Treść w przygotowaniu"). Ta strona
jest wskazywana z linku „Poznaj stowarzyszenie" w bloku `affiliation` na
home (patrz [02-strona-glowna.md](./02-strona-glowna.md) §7) — dziś ten link
prowadzi donikąd merytorycznie. To druga najważniejsza luka treściowa po FAQ.
**Kluczowe zastrzeżenie merytoryczne (żeby nie napisać czegoś nieprawdziwego):**
Janusz Kędzierski prowadzi własną, prywatną działalność (Finanz- &
Lohnbuchhaltung Dipl.-Ing. Janusz Kędzierski) i jest **Beratungsstellenleiter**
— prowadzącym punkt doradczy afiliowany przy już istniejącym, licencjonowanym
stowarzyszeniu **b.b.h. Lohnsteuerhilfeverein e.V.** (siedziba: Pleiskirchen).
Nie jest założycielem ani zarządem tego stowarzyszenia. Treść poniżej musi to
oddawać precyzyjnie — pomylenie „jestem punktem doradczym stowarzyszenia" z
„jestem stowarzyszeniem" to błąd prawny, nie kosmetyczny.
---
## 1. Cel strony
Odpowiedzieć na pytanie, które zada sobie ostrożny odwiedzający: **„czym
właściwie jest to b.b.h. i dlaczego to, że Janusz z nim współpracuje, ma
znaczenie dla mnie?"**. To strona budująca zaufanie przez wyjaśnienie modelu
prawnego, nie przez emocje.
---
## 2. Proponowana struktura treści (do zatwierdzenia przez klienta)
### Sekcja A — „Czym jest Lohnsteuerhilfeverein"
Prosto, bez żargonu: stowarzyszenie pomocy podatkowej działające na
podstawie niemieckiego prawa (Steuerberatungsgesetz), uprawnione do
prowadzenia rozliczeń podatkowych dla swoich CZŁONKÓW — w określonym,
ustawowym zakresie (ten sam zakres co w bloku `eligibility` na
`/uslugi`, patrz [03-uslugi.md](./03-uslugi.md) §3 — **nie duplikować
opisu limitów, tylko odesłać linkiem, żeby nie było dwóch wersji tej samej
informacji prawnej w dwóch miejscach — ryzyko rozjazdu treści**).
### Sekcja B — „b.b.h. Lohnsteuerhilfeverein e.V."
- Nazwa pełna, siedziba, forma prawna (e.V. = zarejestrowane stowarzyszenie).
- Skala działania (stowarzyszenie ma punkty doradcze w wielu miejscach w
Niemczech — do potwierdzenia dokładnej liczby/zasięgu z klientem lub
oficjalną stroną `bbh-lohnsteuerhilfe.de`, nie zgadywać liczby).
- Link do oficjalnej strony stowarzyszenia (`https://bbh-lohnsteuerhilfe.de`)
— już jest w danych globala Footer (`association.link`), tu wart
powtórzenia jako wyraźny, klikalny odnośnik z opisem „więcej o stowarzyszeniu
na jego oficjalnej stronie".
### Sekcja C — „Rola Janusza Kędzierskiego jako Beratungsstellenleiter"
Jasne wytłumaczenie modelu: Janusz prowadzi lokalny punkt doradczy (Beratungsstelle)
afiliowany przy b.b.h. — to ON jest bezpośrednim kontaktem, obsługuje w
języku polskim, ale odpowiedzialność zawodowa/licencja pochodzi z
członkostwa stowarzyszenia. To właściwie odpowiedź na pytanie „czy to na
pewno legalne" bez używania tego słowa wprost.
### Sekcja D — „Co to oznacza dla Ciebie jako klienta"
Praktyczne konsekwencje członkostwa: (a) usługa jest dostępna wyłącznie w
ramach członkostwa w stowarzyszeniu (jeśli tak to działa — do potwierdzenia
z klientem, czy jest osobna „składka członkowska" jak na bbh, czy Janusz
rozlicza to inaczej — **to wpływa na treść blisko 1:1, nie da się tego
zgadnąć**), (b) zakres ochrony/odpowiedzialności, (c) że to NIE jest to samo
co doradca podatkowy (Steuerberater) z pełnymi uprawnieniami — świadome,
ustawowo ograniczone doradztwo dla pracowników najemnych.
---
## 3. Layout
- Page-header spójny z resztą serwisu.
- Sekcje A–D jako kolejne bloki tekstowe z nagłówkami H2, przeplatane:
- Logo b.b.h. (to samo, które trafia do bloku `affiliation` na home) jako
duży, spokojny element wizualny przy Sekcji B — jedyny „ozdobnik"
graficzny na tej stronie, reszta to czysty, dobrze złożony tekst.
- Cytat/pull-quote z oficjalnej misji stowarzyszenia (jeśli dostępny z ich
strony — **zweryfikować z klientem, nie kopiować z bbh-lohnsteuerhilfe.de
bez zgody/atrybucji**, to cudza treść).
- Sekcja D kończy się miękkim CTA — nie „Napisz na WhatsApp" (to strona
wyjaśniająca, nie sprzedażowa), raczej „Masz pytania o zasady członkostwa? →
Kontakt" jako link tekstowy, nie duży przycisk.
## 4. Tło i animacja
Strona **Read** jak FAQ — spokojne tło, `reveal-up` standard, brak
parallax/stamp-in (te efekty rezerwujemy dla stron `Persuade`). Logo b.b.h.
może dostać pojedynczy `stamp-in` przy wejściu w viewport — to jedyny
uzasadniony akcent ruchu na tej stronie, bo to dosłownie pieczęć wiarygodności.
## 5. Zależność blokująca
Ta strona **nie powinna wejść do produkcji z treścią „w przygotowaniu"** —
to jest dokładnie ten typ strony, który budzi nieufność, jeśli jest pusty
(„firma powołuje się na stowarzyszenie, ale nie potrafi go opisać"). Jeśli
klient nie dostarczy treści na czas, lepiej tymczasowo NIE linkować do niej
z `affiliation` na home (patrz [02-strona-glowna.md](./02-strona-glowna.md) §7)
niż zostawić widoczny link do pustej strony.
+61
View File
@@ -0,0 +1,61 @@
# Kontakt — `/pl/kontakt` i `/de/kontakt` (page id 6)
Bloki: `pageHeader` → `contactInfo`. Najprostsza strona w serwisie
funkcjonalnie, ale to jest strona, na którą prowadzą WSZYSTKIE inne CTA —
musi działać bezbłędnie i dawać więcej niż jedną drogę kontaktu.
---
## 1. PageHeader
**[ZACHOWAĆ treść]** „Kontakt / Masz pytania dotyczące rozliczenia..." —
spójny wzorzec.
---
## 2. ContactInfo
**[WYMAGA DANYCH OD KLIENTA]** patrz [10-architektura-cms.md](./10-architektura-cms.md)
§1 — adres, telefon, e-mail, godziny wszystkie placeholder.
**Layout:** ta sama „karta-wizytówka" co na `/jak-sie-umowic`
(patrz [04-jak-sie-umowic.md](./04-jak-sie-umowic.md) §3) — świadomie spójny
komponent w dwóch miejscach, nie warto projektować dwóch różnych wersji tego
samego bloku.
**Duży przycisk WhatsApp** ponad kartą z danymi — to strona kontaktowa,
priorytet CTA musi być jednoznaczny (WhatsApp = 1 klik, reszta danych = dla
tych, którzy wolą zadzwonić/napisać mail).
---
## 3. [NOWE — rekomendacja] Formularz kontaktowy jako opcja zapasowa
Obecnie CAŁA konwersja na stronie opiera się na WhatsApp. To dobre dla
głównej grupy odbiorców, ale traci część ruchu: (a) osoby niekorzystające z
WhatsApp lub wolące zostawić wiadomość poza godzinami pracy bez presji
„czatu na żywo", (b) ruch z Google/SEO, który oczekuje formularza jako
standardu zaufania na stronie firmowej (patrz `wymagania-projektowe-strony.md`
§9 — formularze i pozyskiwanie leadów to osobna, obowiązkowa sekcja checklisty
P1/P2).
**Rekomendacja:** prosty formularz (imię, e-mail LUB telefon, wiadomość,
checkbox zgody RODO) jako druga opcja pod/obok WhatsApp, nie zamiast niego.
Szczegóły techniczne (SMTP, Turnstile, walidacja, `resolveFormMessage`,
zgoda RODO jako osobny niezaznaczony checkbox) w
[11-integracje-seo-wydajnosc.md](./11-integracje-seo-wydajnosc.md) §4 — to
jest rekomendacja zakresu, nie blokuje uruchomienia strony bez niego (WhatsApp
sam w sobie jest kompletną ścieżką konwersji).
**Layout, jeśli wdrożony:** karta obok `contactInfo` (dwie kolumny na
desktopie: dane kontaktowe + WhatsApp po lewej, formularz po prawej), na
mobile formularz pod danymi kontaktowymi. Stan sukcesu po wysłaniu: prosty
komunikat „Dziękujemy, odezwiemy się w ciągu 1 dnia roboczego" — bez przekierowania
na osobną stronę thank-you (niepotrzebna komplikacja dla tak prostego
formularza).
## 4. Tło i animacja
Strona **Persuade** miękki — `reveal-up` standard, brak parallax. Jedyny
akcent: `stamp-in` na przycisku WhatsApp, spójnie z jego rolą głównego CTA
w całym serwisie.
+128
View File
@@ -0,0 +1,128 @@
# Strony prawne — Impressum, Polityka prywatności, Polityka cookies
`/impressum` (id 10), `/polityka-prywatnosci` ↔ `/datenschutzerklarung` (id 8),
`/polityka-cookies` ↔ `/cookie-richtlinie` (id 9). Wszystkie trzy obecnie
puste (`"Treść w przygotowaniu"`).
> **Granica odpowiedzialności — zgodnie z `wymagania-prawne.md` §6:**
> „Nie jesteśmy kancelarią. Nie piszemy treści prawnych ani nie doradzamy
> prawnie." Ten plik dostarcza **strukturę i punkty do wypełnienia**, nie
> gotowy tekst prawny do wklejenia i publikacji. Każdy fragment oznaczony
> `[DO POTWIERDZENIA]` wymaga danych od klienta lub jego prawnika/doradcy
> podatkowego przed publikacją. Dołączone przez Ciebie pliki
> `polityka-prywatnosci.txt`, `polityka-plikow-cookies.txt`,
> `warunki-korzystania-ze-strony-internetowej.txt` dotyczą **innej firmy**
> (The Clean Team — firma sprzątająca, VAN STEV Sp. z o.o., Opole) — traktuję
> je jako wzorzec STRUKTURY dokumentu (jakie sekcje, jaki poziom
> szczegółowości), nie jako źródło treści do skopiowania z podmianą nazwy.
> Podmiana samej nazwy administratora przy zachowaniu cudzej treści
> merytorycznej (cele przetwarzania, podstawy prawne, okresy przechowywania)
> byłaby błędem — te elementy muszą odzwierciedlać RZECZYWISTĄ działalność
> Janusza Kędzierskiego, nie sklepu sprzątającego.
**Ważna różnica jurysdykcyjna:** działalność klienta jest zarejestrowana w
Niemczech (Ludwigshafen am Rhein — adres do potwierdzenia, patrz
[10-architektura-cms.md](./10-architektura-cms.md) §1) i działa jako
Beratungsstelle stowarzyszenia b.b.h. Lohnsteuerhilfeverein e.V. Impressum
strony niemieckiej podlega niemieckiemu **Digitale-Dienste-Gesetz (DDG,
dawniej TMG) §5** — inny reżim formalny niż polska ustawa o świadczeniu usług
drogą elektroniczną, mimo że RODO/DSGVO (to ta sama regulacja UE 2016/679) i
tak obowiązuje w obu wersjach językowych. **Rekomendacja: treść wersji
niemieckiej (Impressum, Datenschutzerklärung) powinien zweryfikować
niemiecki prawnik lub doradca podatkowy klienta** — polski wzorzec RODO nie
pokrywa niemieckich wymogów Impressumspflicht i specyficznych obowiązków
informacyjnych dla Lohnsteuerhilfevereine (np. wskazanie właściwego organu
nadzoru — Aufsichtsbehörde — który przyznał uznanie na mocy §4 Nr. 11 StBerG).
---
## 1. Impressum
Strona istnieje tylko jako pojedynczy tytuł bez wersji PL merytorycznie
odrębnej od DE w praktyce niemieckiej (Impressum to niemiecki wymóg prawny —
nawet polska wersja UI strony pokazuje te same dane rejestrowe, bo dotyczą
niemieckiego podmiotu). Wymagane elementy do zebrania od klienta:
| Element | Status | Notatka |
|---|---|---|
| Pełna nazwa firmy | `[DO POTWIERDZENIA]` | z danych: „Finanz- & Lohnbuchhaltung Dipl.-Ing. Janusz Kędzierski" — potwierdzić dokładną formę rejestrową (Einzelunternehmen? Gewerbe angemeldet unter...?) |
| Adres siedziby | `[DO POTWIERDZENIA]` | dwie sprzeczne wersje w dotychczasowych ustaleniach (Böhlstraße 2 vs Bismarckstr. 112, Ludwigshafen) — wymaga jednoznacznego potwierdzenia, nie zgadywać |
| Telefon, e-mail | `[DO POTWIERDZENIA]` | placeholder w danych (`+49 123 456 789`, `[email protected]`) |
| Steuernummer / USt-IdNr. | `[DO POTWIERDZENIA]` | jeśli dotyczy formy działalności |
| Wskazanie stowarzyszenia i podstawy uznania | `[DO POTWIERDZENIA z prawnikiem]` | typowy dla Lohnsteuerhilfeverein/Beratungsstelle wymóg: nazwa stowarzyszenia (b.b.h. Lohnsteuerhilfeverein e.V.), właściwy **Aufsichtsbehörde** (organ nadzoru, który przyznał uznanie wg §4 Nr. 11 StBerG), często też odesłanie do rejestru Lohnsteuerhilfevereine — **to jest specyficzny dla tej branży wymóg, którego NIE ma w dołączonych wzorcach (branża sprzątająca) — wymaga osobnej weryfikacji prawnej, nie da się go wywnioskować z ogólnego szablonu RODO** |
| Odpowiedzialny za treść (redaktor) | `[DO POTWIERDZENIA]` | zwykle Janusz Kędzierski jako Beratungsstellenleiter |
| Link do platformy ODR (jeśli dotyczy B2C UE) | do oceny z prawnikiem | standardowy element niemieckich Impressów |
**Layout:** prosty, jednokolumnowy tekst — to strona typu **Read**, zero
dekoracji, żadnej tekstury papieru (tu akurat dosłowność „dokumentu" nie
potrzebuje metafory, bo TO JEST dokument formalny). Czytelna typografia,
`sticky-progress` opcjonalnie (raczej niepotrzebne, strona krótka).
---
## 2. Polityka prywatności / Datenschutzerklärung
Struktura oparta na sekcjach z dołączonego wzorca (`polityka-prywatnosci.txt`),
ale z rzeczywistymi celami przetwarzania danych DLA TEJ strony i tej
działalności — nie kopiować sekcji „Złożenie zamówienia w Sklepie" (nie ma
tu sklepu):
| Sekcja | Treść realna dla tego projektu |
|---|---|
| Administrator danych | Dane firmy Janusza (patrz Impressum wyżej) — `[DO POTWIERDZENIA]` |
| Twoje uprawnienia (RODO) | Standardowy katalog art. 15–21 RODO — struktura ze wzorca jest tu poprawna do przeniesienia niemal 1:1 (to prawa ustawowe, nie treść specyficzna dla branży sprzątającej) |
| Cel: kontakt przez WhatsApp/formularz | **[NOWE — nie ma odpowiednika we wzorcu]** trzeba opisać wprost: dane podane w wiadomości WhatsApp/formularzu przetwarzane w celu udzielenia odpowiedzi i przygotowania oferty rozliczenia podatkowego; podstawa — działania przed zawarciem umowy (art. 6 ust. 1 lit. b RODO) lub zgoda |
| Cel: realizacja usługi rozliczenia podatkowego | **[NOWE]** to jest GŁÓWNY cel przetwarzania tej firmy i we wzorcu (firma sprzątająca) nie występuje w ogóle — wymaga opisania: jakie dane osobowe/podatkowe klient przekazuje (Lohnsteuerbescheinigung, IdNr/PESEL, dane o dochodach), komu są przekazywane (Finanzamt, stowarzyszenie b.b.h.), jak długo przechowywane (przepisy o przechowywaniu dokumentacji podatkowej w Niemczech mają własne, dłuższe terminy niż ogólne RODO — **do potwierdzenia z doradcą podatkowym klienta, nie zgadywać**) |
| Cel: analiza/cookies statystyczne | Zależne od decyzji w [11-integracje-seo-wydajnosc.md](./11-integracje-seo-wydajnosc.md) §3 — jeśli GA4/Plausible zostanie wdrożone, opisać tu zgodnie z realnym narzędziem |
| Odbiorcy danych | b.b.h. Lohnsteuerhilfeverein e.V. (jako stowarzyszenie, w ramach którego świadczona jest usługa), niemiecki Finanzamt, dostawca hostingu/poczty — **lista do potwierdzenia z klientem, nie zgadywać dostawców** |
| Przekazanie danych poza UE | Do zweryfikowania w zależności od dostawcy hostingu (patrz [10-architektura-cms.md](./10-architektura-cms.md) — jeśli Hetzner/UE, odpowiedź: „nie ma miejsca"; jeśli inny dostawca spoza UE, wymaga osobnej klauzuli) |
| Bezpieczeństwo danych | SSL/TLS — struktura ze wzorca poprawna do przeniesienia |
**Layout:** identyczny jak Impressum — czysty tekst, długie akapity, spis
treści/kotwice do sekcji na początku strony (skoki nawigacyjne ułatwiają
znalezienie interesującego fragmentu na długiej stronie prawnej).
---
## 3. Polityka cookies / Cookie-Richtlinie
Tu wzorzec (`polityka-plikow-cookies.txt`) jest strukturalnie bardzo blisko
tego, co faktycznie potrzebne — tabela cookies ma być realna dla TEGO stacku
technicznego, nie skopiowana z cudzej strony:
| Cookie | Cel | Okres | Kategoria | Źródło |
|---|---|---|---|---|
| `ipal-locale` | zapamiętanie wybranej wersji językowej (PL/DE) | sesyjny | funkcjonalny | plugin ipal-kit (potwierdzone w kodzie) |
| `payload-token` | uwierzytelnienie w panelu administracyjnym (tylko zalogowani redaktorzy, nie zwykli odwiedzający) | 2h (domyślny czas życia tokena) | niezbędny | Payload CMS (potwierdzone w kodzie) |
| `theme` (next-themes) | zapamiętanie wybranego motywu jasny/ciemny | trwały (localStorage, nie cookie — **do weryfikacji technicznej, next-themes domyślnie używa localStorage, nie ciasteczka** — jeśli tak, ta pozycja idzie do sekcji „localStorage", nie do tabeli cookies) | funkcjonalny | `next-themes` |
| `_ga`, `_ga_<id>` | jeśli GA4 zostanie wdrożone — patrz [11](./11-integracje-seo-wydajnosc.md) §3 | 2 lata (Google default) | statystyczny | Google Analytics (WARUNKOWE — tylko jeśli faktycznie wdrożone) |
| Cookie zgody na baner (`cookie-consent` / nazwa z `ConsentProvider`) | zapamiętanie wyboru użytkownika w bannerze cookies | do potwierdzenia w kodzie pluginu | niezbędny | ipal-kit consent |
**Uwaga:** tabela MUSI zostać zweryfikowana względem faktycznego audytu
przeglądarki (DevTools → Application → Cookies) na wdrożonej stronie
staging, nie tylko na podstawie czytania kodu — zgodnie z narzędziem
„Cookiebot audit" / „DevTools → Application" w `wymagania-projektowe-strony.md`
§3. Publikowanie listy cookies, która nie odpowiada rzeczywistości
technicznej, to sam w sobie błąd zgodności RODO/ePrivacy.
**Layout:** tabela (nie proza) — to jedyna z trzech stron prawnych, gdzie
tabelaryczne zestawienie jest czytelniejsze niż akapity, spójnie z tym, jak
wzorzec `polityka-plikow-cookies.txt` już to robi.
---
## 4. Baner zgody na cookies (element techniczny, nie treść strony)
Patrz `wymagania-prawne.md` §2 — plugin `ipal-kit` dostarcza `CookieBanner`/
`CookieButton`/`ConsentProvider` z 4 kategoriami (necessary/functional/
analytics/marketing) i enforcementem („Odrzuć" na równi z „Akceptuj"). Do
zweryfikowania w [10-architektura-cms.md](./10-architektura-cms.md) §4, czy
komponent jest już podłączony w `layout.tsx` — w przeglądanych plikach kodu
(`Header`, `Footer`, `Providers`) nie natrafiłem na jawne wywołanie
`<CookieBanner/>`, co może oznaczać, że jest jeszcze do wpięcia.
**Wygląd banera** (jeśli jeszcze do zbudowania/dostosowania wizualnie):
spójny z resztą serwisu — karta w stylu „dokumentu" (biały/kremowy panel,
cienka ramka, przycisk akcentowy), umieszczona jako pasek dolny (nie modal na
środku ekranu blokujący całą treść — mniej agresywne, lepiej konwertujące
UX), z linkiem do `/polityka-cookies` przez `getSystemPagePath`.
+132
View File
@@ -0,0 +1,132 @@
# Architektura i zmiany w CMS
Zgodnie z `fundamenty-projektu.md` i `standardy-kodu.md` — zmiany warstwowo:
co jest treścią (panel), co strukturą (Payload config), co kodem projektu.
Zero hardkodu — każda wartość poniżej ląduje w polu `localized`/`upload`/env,
zgodnie z `antigravity-zasady-agent.md` A1–A4.
---
## 1. Dane wejściowe od klienta (blokujące, zebrać przed dalszą pracą)
To jedyna sekcja tego planu, która nie jest decyzją projektową — to lista
pytań do Michała/klienta. Bez tego część planu z plików `02`–`09` zostaje na
placeholderach niezależnie od tego, jak dobrze zbudowany będzie kod.
| # | Dane | Gdzie trafia | Status w zipie |
|---|---|---|---|
| 1 | Realny adres biura | global `Company` | `"DO POTWIERDZENIA PRZEZ KLIENTA"` — dwie sprzeczne wersje w poprzednich ustaleniach (Böhlstraße 2 vs Bismarckstr. 112, Ludwigshafen), **wymaga jednoznacznej odpowiedzi klienta** |
| 2 | Realny telefon | global `Company` | placeholder `+49 123 456 789` |
| 3 | Realny e-mail | global `Company` | placeholder `[email protected]` |
| 4 | Numer WhatsApp (format `49XXXXXXXXX`, bez `+`/spacji) | global `Company.whatsappNumber` | placeholder `49123456789` |
| 5 | Zdjęcie Janusza (portret + kontekst pracy) | media, użyte w `hero`, `bio` | brak w paczce |
| 6 | Logo b.b.h. Lohnsteuerhilfeverein e.V. | media, użyte w `affiliation.logo`, `Footer.association.logo` | klient wg wcześniejszych ustaleń je posiada — brak w paczce, dostarczyć w wersji wektorowej/PNG na przezroczystym tle |
| 7 | Logo/marka własnej firmy Janusza (jeśli istnieje osobne od b.b.h.) | `site-settings.logo`, favicon | brak potwierdzenia czy istnieje |
| 8 | Forma prawna działalności, ew. Steuernummer/USt-IdNr. | strony prawne (Impressum) | nieustalone, patrz [09-strony-prawne.md](./09-strony-prawne.md) §1 |
| 9 | Czy istnieje formularz członkostwa/składka w ramach b.b.h. (dla treści strony Stowarzyszenie) | `/stowarzyszenie` | nieustalone, patrz [07-stowarzyszenie.md](./07-stowarzyszenie.md) §2 Sekcja D |
| 10 | Skala firmy: czy to tylko Janusz, czy zespół | blok `team` na `/o-nas` | dane pokazują 1 osobę — potwierdzić, nie zgadywać (patrz [05-o-nas.md](./05-o-nas.md)) |
| 11 | Aktualność progów `18 000 € / 36 000 €` i `§4 Nr. 11 StBerG` na bieżący rok podatkowy | blok `eligibility` | treść już jest, wymaga tylko potwierdzenia aktualności, nie przepisywania |
| 12 | Teksty bannera cookies PL/DE | global `Cookie Settings` w panelu | puste w bazie — renderuje się angielski fallback z pluginu, wymaga uzupełnienia |
---
## 2. Zmiany w blokach (Payload config + Component)
| Blok | Zmiana | Powód | Priorytet |
|---|---|---|---|
| `faqTeaser` → nowy `faqFull` (lub rozszerzenie configu istniejącego) | dodać pole grupowania `category` (opcjonalny text) w `questions[]`, wykorzystywane na `/faq`; `faqTeaser` na home zostaje bez zmian strukturalnych, tylko dodać `ctaText`/`ctaUrl` (wzorem `process`) do linkowania na pełne FAQ | patrz [06-faq.md](./06-faq.md) | P1 |
| `servicesList` | dodać pole `linkUrl` per usługa (obecnie tylko `linkText` bez celu linku) | naprawia martwe „Zobacz więcej" na home, patrz [02-strona-glowna.md](./02-strona-glowna.md) §5 | P1 |
| `affiliation` | wypełnić `trustPoints[]` (pole już istnieje w schemacie, obecnie puste `[]`) i `logo` | patrz [02-strona-glowna.md](./02-strona-glowna.md) §7 | P1 |
| `Team/Component.tsx` | dodać warunek: gdy `members.length === 1`, renderować pojedynczą kartę bez siatki grid (albo pominąć render bloku całkowicie — decyzja klienta, patrz [05-o-nas.md](./05-o-nas.md) §3) | unika redundancji z `bio` | P2 |
| `hero` | dodać `id` do sekcji `process` na home (`id="jak-to-dziala"`), żeby `secondaryCta.url` z hero (`#jak-to-dziala`) faktycznie trafiał gdzieś | martwy kotwica-link, błąd funkcjonalny | P1 |
| `TextSection` (Impressum/Datenschutz/Cookies/Stowarzyszenie/FAQ dziś) | upewnić się, że pole `text` to `richText`, nie zwykły `textarea` — długie strony prawne potrzebują list, nagłówków, linków w treści, nie jednego bloku tekstu | wymóg funkcjonalny dla treści z [07](./07-stowarzyszenie.md) i [09](./09-strony-prawne.md) | P1 |
**Nowy blok do rozważenia (faza 2, nie blokuje startu):** `VideoSection`
— patrz [02-strona-glowna.md](./02-strona-glowna.md) §11.
**Nowy element UI (nie blok CMS, komponent globalny):** floating WhatsApp
button — patrz [02-strona-glowna.md](./02-strona-glowna.md) §0. Dane
(`whatsappNumber`) już istnieją w globalu `Company` — tylko brakuje
komponentu w `layout.tsx`.
---
## 3. Media — kolekcja i pipeline
- `Media.ts` ma już `normalizeFilenameHook` (zgodnie ze standardem) — bez zmian.
- **Brak wariantów rozmiarów (`imageSizes`)** w przejrzanym configu —
do dodania zgodnie z `wymagania-projektowe-strony.md` §6 (P1: „Warianty
rozmiarowe generowane przy uploadzie w Payload (sharp)"). Bez tego każde
zdjęcie (hero, bio, process) ląduje w pełnej rozdzielczości na każdym
urządzeniu — bezpośrednio uderza w LCP (cel < 2,5s), patrz
[11-integracje-seo-wydajnosc.md](./11-integracje-seo-wydajnosc.md) §5.
- Format: AVIF/WebP w `next.config` (`formats: ['image/avif','image/webp']`)
— sprawdzić, czy już ustawione.
- Favicon: **brak w danych** (`site-settings.favicon: null`) — wgrać przez
panel, renderować przez `buildIconsMetadata` z pluginu (NIGDY ręcznie w
`<head>`, zgodnie z antywzorcem #favicon w `standardy-kodu.md` §6).
---
## 4. System Pages — role nieprzypisane
`site-settings.privacyPolicy`, `.cookiePolicy`, `.termsOfService` = `null` dla
obu języków. Bez tego `getSystemPagePath` (używane przez baner cookies,
stopkę, formularze) nie ma czego zwrócić — linki do polityk będą albo martwe,
albo (gorzej) zahardkodowane jako `/pl/polityka-prywatnosci` w obejściu, co
łamie zasadę A3 z `antigravity-zasady-agent.md`.
**Do zrobienia w panelu (nie w kodzie):** Site Settings → System Pages →
przypisać:
- `homepage` → już ustawione (page 1) ✓
- `privacyPolicy` → page 8 (Polityka prywatności / Datenschutzerklärung)
- `cookiePolicy` → page 9 (Polityka cookies / Cookie-Richtlinie)
- `termsOfService` → **brak strony regulaminu w ogóle w obecnej mapie stron**
— do decyzji: czy przy modelu „wizytówka + WhatsApp" (bez zamawiania usług
online, bez kont użytkowników) regulamin jest w ogóle wymagany. Wg
`wymagania-prawne.md` checklist: „Regulamin — jeśli strona świadczy usługi
/ sprzedaż / konta" — tu formalnie świadczona jest usługa doradztwa, więc
**rekomendacja: dodać krótki regulamin świadczenia usługi drogą
elektroniczną (zakres: korzystanie z formularza kontaktowego/WhatsApp,
nie regulamin sklepu)**, konsultowany z prawnikiem klienta, jako 11. strona.
Impressum ma częściowo tę rolę po stronie niemieckiej, ale nie zastępuje
polskiego wymogu regulaminu usług elektronicznych po stronie PL.
Satzung/Beitragsordnung (statut i regulamin składek b.b.h., wzorem bbh) — **nie
dotyczą tej strony**: to dokumenty SAMEGO stowarzyszenia b.b.h., nie firmy
Janusza. Jeśli mają się pojawić, to jako link zewnętrzny do
`bbh-lohnsteuerhilfe.de/satzung` w obrębie strony Stowarzyszenie ([07](./07-stowarzyszenie.md)),
nie jako własne strony w tym repo.
---
## 5. Nawigacja — Header/Footer
Obecna nawigacja header (5 pozycji: Usługi, Jak się umówić, O nas, kotwica
FAQ, Kontakt) pomija bezpośredni link do `/stowarzyszenie` — do rozważenia,
czy dodać do głównego menu, czy zostawić jako link wtórny (z bloku
`affiliation` + stopki, gdzie już jest). Rekomendacja: **zostawić poza
głównym menu** — to strona uzupełniająca, nie ścieżka konwersji; upychanie
jej w header rozmywa priorytet (Usługi → Jak się umówić → Kontakt to
właściwa ścieżka do WhatsApp, nie przeciążać nawigacji).
Stopka (`Footer.navigation`) linkuje już do stron 2,3,4,6,8,9,10 — brakuje
FAQ (5) i Stowarzyszenie (7) w liście stopki, mimo że istnieją jako strony —
**dodać oba do nawigacji stopki**, żeby były osiągalne bez polegania
wyłącznie na kotwicach/linkach kontekstowych.
---
## 6. Porządki w repo (drobne, ale wpływają na jakość odbioru)
- `src/app/(frontend)/styles.css` — domyślny boilerplate Payloada
(`background: rgb(0,0,0)`, `font-family: system-ui`), realny design system
żyje w `globals.css` przez Tailwind `@theme`. Zweryfikować, czy plik jest
w ogóle importowany; jeśli nie — usunąć, żeby nie mylić przyszłych sesji
co do „gdzie są prawdziwe tokeny" (zgodnie z zasadą jednego źródła prawdy,
`standardy-kodu.md` §2.2).
- `scripts/update_*.py`, `scripts/fix_*.ts` w repo — robocze skrypty
migracyjne z wcześniejszych sesji; jeśli zadania już wykonane i nieaktualne,
rozważyć przeniesienie do `scripts/archive/` albo usunięcie, żeby nie
myliły co do aktualnego sposobu edycji treści (treść edytuje się przez
panel, nie przez skrypty — `architektura-tresci.md`).
+111
View File
@@ -0,0 +1,111 @@
# Integracje, SEO, bezpieczeństwo, wydajność
Zakres odpowiada sekcjom 5–10 i 13 `wymagania-projektowe-strony.md`,
zawężonym do tego, co faktycznie dotyczy tego projektu (bez np. e-commerce,
CRM — których tu nie ma).
---
## 1. WhatsApp — jedyna „ciężka" integracja tego projektu
Nie wymaga API/klucza — to prosty link `https://wa.me/{numer}?text={wiadomość}`.
Do ustalenia:
- **Numer** — z global `Company.whatsappNumber`, patrz [10-architektura-cms.md](./10-architektura-cms.md) §1.
- **Prefill wiadomości** — rekomendacja: każdy CTA „Napisz na WhatsApp" może
nieść inny, kontekstowy tekst startowy (np. z `/uslugi`: „Dzień dobry, mam
pytanie o rozliczenie podatku z Niemiec" — z `/jak-sie-umowic`: „Chciałbym
rozpocząć proces rozliczenia"). To niewielki dodatek do configu bloku
`finalCta`/`hero` (pole `whatsappMessage` opcjonalne), ale realnie
podnosi jakość pierwszego kontaktu — klient wie, z jakiej podstrony
ktoś pisze, zanim jeszcze odpowie.
- **Śledzenie konwersji** — kliknięcie w link WhatsApp jako zdarzenie
(`whatsapp_click`) wysyłane do analityki PO zgodzie (patrz §3) —
jedyny sposób, żeby zmierzyć skuteczność strony, skoro nie ma
tradycyjnego „wysłania formularza" jako punktu konwersji.
## 2. Formularz kontaktowy (jeśli wdrożony — patrz [08-kontakt.md](./08-kontakt.md) §3)
Zgodnie z `wymagania-projektowe-strony.md` §9 i `wymagania-prawne.md` §3:
- Walidacja klient + serwer (nie ufać samemu frontowi).
- Ochrona antyspam: Turnstile (plugin ipal-kit ma wsparcie, patrz
`turnstile.md` w docs pluginu) — bez własnej implementacji captchy.
- Zgoda RODO: osobny, NIEZAZNACZONY checkbox z linkiem do polityki
prywatności (przez `getSystemPagePath`), enforcement server-side
(`validateSubmission`, `consentFieldName`) — zgodnie z `wymagania-prawne.md` §3.
Formularz bez zaznaczonej zgody ma nie przejść nawet przy bezpośrednim
requeście (nie tylko blokada w UI).
- SMTP: przez `panelSmtpAdapter`/mailAdapter pluginu, testowane przez
Mail-Tester przed produkcją (SPF/DKIM/DMARC — inaczej maile lądują w spamie
i formularz jest bezużyteczny mimo poprawnego kodu).
- Stan sukcesu: prosty komunikat inline (patrz [08-kontakt.md](./08-kontakt.md) §3),
bez osobnej strony thank-you.
## 3. Analityka — za zgodą, nie przed
- Rekomendacja narzędzia: **Plausible** (prostsze, nie wymaga cookie
zgody na poziomie technicznym tak restrykcyjnie jak GA4, mniejszy ciężar
strony) LUB **GA4**, jeśli klient chce integrację z szerszym ekosystemem
Google — decyzja do podjęcia z klientem, nie zakładać automatycznie GA4.
- Niezależnie od wyboru: **zero requestów do domeny analitycznej przed
akceptacją w bannerze cookies** (weryfikacja: DevTools → Network, filtr po
domenie analitycznej, przed i po kliknięciu „Tylko niezbędne" —
`wymagania-projektowe-strony.md` §8).
- Zdarzenia do zdefiniowania: `whatsapp_click` (per lokalizacja CTA — hero,
finalCta, floating button), `phone_click`, `email_click`, `form_submit`
(jeśli formularz wdrożony).
## 4. SEO — structured data (schema.org)
Zgodnie z `antigravity-zasady-agent.md` część C, punkt 12–13 (funkcje już
częściowo dostarcza plugin — sprawdzić `seo.md` w docs przed pisaniem
czegokolwiek własnego):
| Typ | Gdzie | Dane |
|---|---|---|
| `ProfessionalService` (nie generyczny `Organization` — branża regulowana) | root layout, wszystkie strony | nazwa, adres, telefon, logo, `areaServed` (Niemcy), `knowsLanguage` (pl, de) |
| `WebSite` | root layout | tylko jeśli jest realna wyszukiwarka na stronie (obecnie brak — pominąć `SearchAction`, zgodnie z ostrzeżeniem w `antigravity-zasady-agent.md` „TYLKO jeśli jest realna wyszukiwarka") |
| `FAQPage` | `/faq` | 1:1 z widoczną treścią pytań/odpowiedzi (patrz [06-faq.md](./06-faq.md) §5) — nie ukryty tekst |
| `BreadcrumbList` | każda podstrona poza home | z realnej ścieżki (`resolveRoute`/routing pluginu), nie zaszyte |
| Recenzje/`Review` | **[do rozważenia, NIE wdrażać bez realnych danych]** — 3 testimoniale na home mają tylko imię+miasto, nie są zweryfikowanymi recenzjami z zewnętrznej platformy (Google/Trustpilot); oznaczanie ich jako `AggregateRating`/`Review` w schema.org bez faktycznej platformy-źródła to ryzyko naruszenia wytycznych Google (rich results dla fałszywych/niepotwierdzalnych ocen) |
## 5. Wydajność — cele i konkretne działania
Core Web Vitals (`wymagania-projektowe-strony.md` §6): LCP < 2,5s, INP < 200ms,
CLS < 0,1.
- **LCP** — obraz hero (`image` w bloku `hero`) musi mieć `priority` w
`next/image`, prawidłowe `sizes`, i realne warianty rozmiarów z Payload
(patrz [10-architektura-cms.md](./10-architektura-cms.md) §3) — bez tego
cel LCP jest nieosiągalny niezależnie od reszty optymalizacji.
- **CLS** — `floatingStat` w hero, akordeon FAQ (rozwijanie odpowiedzi),
floating WhatsApp button — wszystkie muszą rezerwować miejsce z góry
(aspect-ratio/min-height), nie „wskakiwać" po hydratacji.
- **INP** — Framer Motion już w użyciu (parallax hero) — pilnować, żeby
ciężkie komponenty (np. przyszły `VideoSection`) ładowały się przez
`next/dynamic`, nie w głównym bundlu.
- **Bundle** — sprawdzić `@next/bundle-analyzer`, czy `framer-motion` nie
przecieka do stron, które go nie potrzebują (strony prawne — czysty tekst —
nie powinny ciągnąć animacji).
## 6. Bezpieczeństwo
Zgodnie z `wymagania-projektowe-strony.md` §7 — w większości odpowiedzialność
pluginu (`buildSecurityHeaders`), do weryfikacji na wdrożonym środowisku:
- Nagłówki CSP/HSTS/X-Content-Type-Options/Referrer-Policy/Permissions-Policy
→ Mozilla Observatory, cel ocena A.
- HTTPS wymuszony, przekierowanie HTTP→HTTPS.
- Panel administracyjny (`/admin`) — silne hasło, brak wystawienia na
publiczne indeksowanie (sprawdzić `robots.txt`).
## 7. i18n — hreflang i routing
- Sprawdzić, czy `hreflang` między `/pl/...` a `/de/...` jest generowany
przez plugin (powinien, zgodnie z `seo.md`) — zweryfikować narzędziem
hreflang Tags Testing Tool po wdrożeniu.
- Przełącznik języka (`LanguageSwitcher`, już w kodzie) musi zachowywać
bieżącą podstronę (np. z `/pl/uslugi` na `/de/leistungen`, nie na `/de`) —
to już wygląda na zaimplementowane przez `clientSwitchLocalePath.ts`
(patrz `.agents/context/plugin-issues.md` w repo) — potwierdzić ręcznym
testem na każdej z 10 stron, nie tylko na home.
+57
View File
@@ -0,0 +1,57 @@
# Checklist odbioru — j_kedzierski
Wyciąg z `wymagania-projektowe-strony.md`, zawężony i spriorytetyzowany pod
ten konkretny projekt (wizytówka + generator leadów, nie e-commerce). P1 =
blokuje uruchomienie. Odhaczać `[ ]` → `[x]` przy odbiorze, zgodnie z formatem
źródłowego dokumentu.
## P1 — blokuje start
- [ ] Realne dane firmy w globalu `Company` (adres, telefon, e-mail, WhatsApp) — zero „DO POTWIERDZENIA" ani `+49 123 456 789` na produkcji
- [ ] Zdjęcie Janusza w hero i na `/o-nas` — zero pustych/placeholder obrazów
- [ ] Logo b.b.h. w bloku `affiliation` i stopce
- [ ] Favicon i `site-settings.logo` wgrane przez panel
- [ ] Treść stron: Impressum, Polityka prywatności, Polityka cookies, Stowarzyszenie, FAQ — żadna nie zostaje z „Treść w przygotowaniu" ([06](./06-faq.md), [07](./07-stowarzyszenie.md), [09](./09-strony-prawne.md))
- [ ] System Pages role przypisane (`privacyPolicy`, `cookiePolicy`) — linki w bannerze cookies i stopce prowadzą do realnych stron, nie 404
- [ ] Baner cookies działa: pokazuje się przy pierwszej wizycie, „Odrzuć" na równi z „Akceptuj", zero cookies analitycznych przed zgodą (test w DevTools → Application)
- [ ] Martwy kotwica-link `#jak-to-dziala` z hero naprawiony ([10](./10-architektura-cms.md) §2)
- [ ] `servicesList.linkUrl` uzupełnione — „Zobacz więcej" prowadzi gdzieś ([10](./10-architektura-cms.md) §2)
- [ ] Wszystkie 10 stron istnieją i renderują się poprawnie w PL i DE, przełącznik języka zachowuje bieżącą podstronę
- [ ] Formularz (jeśli wdrożony) ma server-side walidację zgody RODO — nie tylko UI
- [ ] Kontrast tekst/tło sprawdzony na ciepłym papierowym tle (WebAIM Contrast Checker) — min. 4,5:1
- [ ] `prefers-reduced-motion` respektowany na wszystkich animacjach z [01](./01-design-system-impeccable.md) §4
- [ ] Obraz hero ma `priority`, LCP < 2,5s (PageSpeed Insights, dane polowe)
- [ ] Nagłówki bezpieczeństwa (CSP/HSTS/...) — Mozilla Observatory ocena A
- [ ] `sitemap.xml`/`robots.txt` generowane i poprawne, zgłoszone w Search Console
- [ ] Panel `/admin` zabezpieczony (silne hasło), nie indeksowany
## P2 — ważne dla jakości, nie blokuje
- [ ] `/impeccable detect` bez findings „AI slop" (patrz checklista [01](./01-design-system-impeccable.md) §5) na wszystkich 10 stronach
- [ ] `trustPoints` w bloku `affiliation` wypełnione ([02](./02-strona-glowna.md) §7)
- [ ] FAQ pogrupowane w kategorie + `FAQPage` schema.org ([06](./06-faq.md))
- [ ] Blok `team` naprawiony (bez redundancji z `bio` przy jednej osobie — [05](./05-o-nas.md) §3)
- [ ] Warianty rozmiarów obrazów (`imageSizes`) skonfigurowane w Payload
- [ ] `hreflang` między `/pl` i `/de` poprawny (hreflang Tags Testing Tool)
- [ ] Analytics wdrożone za zgodą, zdarzenie `whatsapp_click` mierzone
- [ ] Regulamin świadczenia usług — decyzja podjęta i wdrożona lub świadomie odrzucona z uzasadnieniem ([10](./10-architektura-cms.md) §4)
- [ ] Stopka linkuje do FAQ i Stowarzyszenie ([10](./10-architektura-cms.md) §5)
- [ ] `styles.css` boilerplate usunięty lub potwierdzony jako nieużywany ([10](./10-architektura-cms.md) §6)
- [ ] Lighthouse Accessibility ≥ 95 na kluczowych szablonach
## P3 — opcjonalne / faza 2
- [ ] Sekcja wideo „Co to jest Lohnsteuerhilfe" ([02](./02-strona-glowna.md) §11)
- [ ] Formularz kontaktowy jako opcja zapasowa obok WhatsApp ([08](./08-kontakt.md) §3)
- [ ] Newsletter (wzorem bbh) — tylko jeśli klient chce prowadzić komunikację cykliczną
- [ ] Blog/porady podatkowe (wzorem sekcji „Steuerspar-Tipps" na bbh) — wymaga cyklicznej produkcji treści, nie wdrażać bez zobowiązania klienta do jej utrzymywania
## Weryfikacja końcowa (przed przekazaniem klientowi)
1. `pnpm build --webpack` przechodzi lokalnie bez błędów (`standardy-kodu.md` §7.3)
2. Test ręczny: każda z 10 stron w PL i DE, motyw jasny i ciemny, mobile
(375px) + desktop (1440px) — patrz Responsively App / DevTools Device Mode
3. Test klawiaturą: cała strona wyłącznie Tab/Shift+Tab/Enter/Esc
4. `npx impeccable audit` jako ostatni przelot jakości wizualnej
5. Odczytanie własnego diffu przez osobę, która go nie pisała — „czy następny
człowiek/agent to zrozumie za pół roku" (`standardy-kodu.md`, kompas senior)