# public-site-pages Specification ## Purpose Define public routes, editorial home, catalog pages, institutional/error pages, and contact placeholder for the marketing site. ## Requirements ### Requirement: Public routes serve published content without authentication The system SHALL expose the public routes of SPEC §5.1: `home` (`/`), `services.index` (`/servicos`), `portfolio.index` (`/portfolio`), `portfolio.show` (`/portfolio/{slug}`), `about` (`/sobre`), `contact` (`/contato`) and `privacy` (`/privacidade`). Every public route MUST respond without authentication and MUST NOT expose unpublished content, internal fields, or internal notes (SPEC §19). #### Scenario: Guest reaches every public route - **WHEN** an unauthenticated visitor requests any public route - **THEN** the response status MUST be 200 - **AND** no redirect to `/admin/login` MUST occur #### Scenario: Unpublished content is invisible - **GIVEN** a service, portfolio case, or testimonial with `published_at` null - **WHEN** a visitor loads the corresponding public page - **THEN** the record MUST NOT appear in the rendered output #### Scenario: Unpublished case detail returns 404 - **GIVEN** a portfolio case saved as draft - **WHEN** a visitor requests `/portfolio/{slug}` for that case - **THEN** the response status MUST be 404 #### Scenario: Published case detail becomes reachable - **GIVEN** a portfolio case saved as draft - **WHEN** an admin fills the required fields and publishes the case - **THEN** `/portfolio/{slug}` MUST respond 200 - **AND** the case MUST appear in the `/portfolio` listing ### Requirement: Home renders the editorial structure from CMS content The home page SHALL render, in the order defined by SPEC §6.2, header/navigation, hero, featured visual proof, services summary, working method, selected cases, testimonials, final briefing CTA, and footer with contact, social links and legal links (WEB-01). Hero copy, brand name and contact data MUST come from `site_settings`; services, cases and testimonials MUST come from published records. #### Scenario: Published content is displayed in configured order - **GIVEN** published services, cases and testimonials exist - **WHEN** a visitor loads the home - **THEN** the published content MUST be displayed following the `sort_order` and featured flags - **AND** the hero MUST show the values stored in `site_settings` #### Scenario: CTA leads to the briefing page - **WHEN** a visitor activates the primary or final CTA on the home - **THEN** the visitor MUST be taken to the `contact` route #### Scenario: Empty content does not break the home - **GIVEN** no published services, cases or testimonials - **WHEN** a visitor loads the home - **THEN** the response MUST be 200 - **AND** the affected sections MUST be omitted instead of rendering empty containers #### Scenario: Home has no console errors - **WHEN** the home is loaded in a real browser at desktop and mobile viewports - **THEN** the browser console MUST contain no JavaScript errors ### Requirement: Listing and detail pages exist for catalog content The system SHALL render a services listing (WEB-02) and a portfolio listing plus case detail (WEB-03). The case detail MUST present summary, event type, optional city/venue/date, challenge, solution, optional result, cover image and the ordered gallery. #### Scenario: Services listing shows published services - **WHEN** a visitor loads `/servicos` - **THEN** every published service MUST be listed with title and summary in `sort_order` #### Scenario: Gallery respects stored order - **GIVEN** a published case with multiple gallery images - **WHEN** a visitor loads the case detail - **THEN** the images MUST be rendered ordered by `sort_order` #### Scenario: Listings paginate open-ended growth - **WHEN** the number of published cases exceeds the page size - **THEN** `/portfolio` MUST paginate instead of rendering all records ### Requirement: Institutional and error pages have brand identity The system SHALL provide the Sobre and Política de privacidade pages and branded error pages (WEB-07). The 404 page MUST use the public layout, and the 500 page MUST NOT expose stack traces or internal details when `APP_DEBUG` is false. #### Scenario: Unknown URL renders branded 404 - **WHEN** a visitor requests a non-existent public URL - **THEN** the response status MUST be 404 - **AND** the page MUST use the public layout and offer navigation back to the home #### Scenario: Server error hides internals in production - **GIVEN** `APP_DEBUG` is false - **WHEN** an unhandled exception occurs on a public route - **THEN** the response MUST be a generic branded error page - **AND** MUST NOT contain a stack trace, file path, or environment variable ### Requirement: Contact page presents contact data as briefing placeholder The `contact` route SHALL render the contact page using `site_settings` (e-mail, phone, city, social links) so the home CTA has a valid destination before the briefing form exists. The page MUST NOT create leads in this change. #### Scenario: Contact page shows configured contact data - **WHEN** a visitor loads `/contato` - **THEN** the e-mail and phone stored in `site_settings` MUST be displayed - **AND** no lead record MUST be created ### Requirement: Public pages avoid N+1 queries Public pages SHALL load related content with explicit eager loading through dedicated read Queries in the Application layer. Rendering a page MUST NOT issue one query per related record (SPEC §19). #### Scenario: Case detail loads gallery in bounded queries - **WHEN** a case detail page with many gallery images is rendered - **THEN** the gallery MUST be loaded with eager loading - **AND** the query count MUST NOT grow with the number of images