# turnstile Cloudflare Turnstile: widget (client) + weryfikacja (server). Klucze z SiteIntegrations (panel, nie env). Widget dostaje `siteKey` jako prop; verify czyta secret server-side. ## Config Brak opcji — pola `turnstileSiteKey` / `turnstileSecretKey` są w SiteIntegrations (tab Turnstile). Edytor wpisuje klucze w panelu. ## Front — widget (client) Import z `ipal-kit/client`. `siteKey` pobierz server-side i przekaż jako prop: ```tsx // server component — pobiera publiczny siteKey z panelu import { getSiteIntegrations } from 'ipal-kit' const { turnstileSiteKey } = await getSiteIntegrations(payload) // przekaż do swojego client-formularza → widget ``` ```tsx 'use client' import { Turnstile } from 'ipal-kit/client' import { useState } from 'react' function ContactForm({ siteKey }) { const [token, setToken] = useState(null) return (
{/* pola */} ) } ``` Widget ładuje skrypt Turnstile sam (bez `next/script`), zwraca token przez `onToken` (null przy wygaśnięciu/błędzie). ## Front — verify (server) ```ts import { verifyTurnstile } from 'ipal-kit/server' const ok = await verifyTurnstile({ token, payload, ip }) if (!ok) { // odrzuć zgłoszenie } ``` `verifyTurnstile` czyta secret z SiteIntegrations (Local API), woła Cloudflare. Zwraca `false` na każdy problem (brak klucza, sieć, odrzucenie) — traktuj `false` jako „nie ufaj temu zgłoszeniu". `server-only` gwarantuje, że nie trafi do bundla przeglądarki. > W formularzach zwykle nie wołasz `verifyTurnstile` wprost — robi to > `submitForm` (patrz [forms.md](./forms.md)).