Files
FDMTech/FRONTEND_CONTRACT.md

3.7 KiB

FDMTech — interfejs PHP dla projektanta (v1)

Projektant jest właścicielem templates/layout.php, templates/home.php, public/assets/css/site.css, public/assets/js/site.js i logo. Renderer nie edytuje tych plików. PHP 8.2+, bez frameworka. public/ jest document root.

Zmienne w obu szablonach

  • $site: tablica name, contact_email, contact_phone, navigation (lista {label, url}). Puste dane kontaktowe są dozwolone, nie wymyślamy adresów.
  • $page: slug, title, seo_title, seo_description, published_html, published_css, published_at (string/null). Tylko opublikowane dane.
  • $meta: title, description, canonical (pełny URL lub pusty), robots.
  • $isDemo: bool. Demo należy oznaczyć widocznym komunikatem „Tryb demonstracyjny — formularz nie wysyła zgłoszeń”.
  • $csrfToken: string; $formAction: /inquiries; $formValues: name/email/company/phone/message/consent; $formErrors: mapa błędów; $formNotice: string lub null, sukces mówi wyłącznie o zapisie; $formStatus: idle|invalid|saved|unavailable|limited; $smtpStatus: disabled.
  • $statusCode: HTTP status; $nonce: nonce CSP, jeśli potrzebny dla zaufanego lokalnego skryptu. Skrypty lokalne z defer są dozwolone; inline wymagają nonce.
  • $e($value): HTML/attribute escaping. Wszystkie teksty, atrybuty, meta i URL wyświetlać przez $e. Tylko $content, $cmsHtml i $cmsStyleTag są gotowym bezpiecznym HTML.
  • $cmsHtml: przefiltrowany fragment publikacji; $cmsStyleTag: gotowy element style z nonce i CSS ograniczonym do #cms-content (albo pusty).

Sposób renderowania

templates/home.php jest używany tylko w jawnym demo na / jako zaprojektowana strona pokazowa. Produkcyjna strona główna pochodzi z publikacji slug home, tak jak pozostałe strony. Aplikacja buduje $content jako <main id="cms-content">…</main> zawierający treść publikacji. W demo na / zawartość home.php trafia do tego samego main: szablon home nie dodaje własnego main ani ID cms-content.

templates/layout.php otrzymuje $content i tworzy cały dokument: head (escaped SEO, canonical, robots, $cmsStyleTag, CSS), globalny header/nav, <?= $content ?>, footer, lokalny JS. Nawigacja i kontakt pochodzą z $site. Nie umieszczać URL panelu Sensory. layout.php jest używany także dla błędów i formularza.

Formularz aplikacji dostępny pod /kontakt (trasa zarezerwowana, zawsze działa bez JS); linki CTA można kierować na /kontakt. Własny formularz w home: POST $formAction, hidden _csrf=$csrfToken, hidden source=home, pola name, email, opcjonalne company, phone, message, checkbox consent=1 wymagany. Honeypot website ma pozostać pusty (ukryty, tabindex=-1, autocomplete=off). Błędy walidacji wracają na stronę formularza z kodem 422 i zachowanymi wartościami; po zapisie jest 303 do /kontakt, notice jednokrotny. Demo POST zwraca 503, nigdy fikcyjny sukces.

Jawne demo i brak szablonów

APP_DEMO=true w środowisku/.env uruchamia dane demonstracyjne bez łączenia z DB. Domyślnie false. Demo otrzymuje noindex, nofollow. Awaria DB w produkcyjnym trybie zawsze zwraca 503. Brak home.php: semantyczna strona demo aplikacji. Brak layout.php: techniczny dokument HTML z globalną nawigacją i stopką z app/View.php, bez prac nad stylistyką.

Zasoby lokalne /assets/... (wersjonowane query ?v=N, bo serwer wysyła długi cache). CSP blokuje skrypty publikacji, inline event handlers, zewnętrzne skrypty, iframes i obiekty. Obrazy HTTPS są dopuszczone (media CMS muszą być publicznie dostępne). Nie używać inline style w home; CSS projektanta pozostaje w site.css. Fonty marki wyłącznie lokalnie w /assets/fonts/ (latin-ext obowiązkowo); brak ładowania z Google Fonts.