feat: ship public site with SEO and visuals
Publish CMS content on public routes with responsive media, accessibility checks, and deterministic visual baselines. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
## ADDED 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
|
||||
Reference in New Issue
Block a user