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
+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.