Add implementation plan for product selection landing page (Feature 002)

Completed planning phases 0 and 1 for simple landing page feature.

## Plan Overview:

**Approach**: Minimal addition to existing Flask app - reuse Product model,
add one route, one template. No new dependencies or complexity.

**Constitution Check**:  All 5 principles satisfied
- Specification-first development (spec.md complete)
- Test-first discipline (TDD workflow defined)
- Independent user stories (3 stories, all independently testable)
- Simplicity (reuses existing Flask/Jinja2/Product architecture)
- Documentation as code (all artifacts in specs/002-product-list/)

## Artifacts Created:

### Phase 0: Research (research.md)
- Reuses infrastructure from feature 001 (Flask, Jinja2, file storage)
- Single new decision: Product.load_active() method for filtering/sorting
- Performance analysis: <100ms for 100 products (well under 1s target)

### Phase 1: Design & Contracts
- **data-model.md**: Documents Product model extension (load_active method)
- **contracts/landing-page.yaml**: OpenAPI contract for GET / route
- **quickstart.md**: Developer implementation guide with:
  - Step-by-step implementation checklist
  - Code snippets for route, template, tests
  - TDD workflow (write tests → verify fail → implement → pass)
  - Manual verification checklist

### Agent Context
- Updated CLAUDE.md with feature technologies (no new tech added)

## Implementation Summary:

**New Files** (to be created):
- app/routes/landing.py - Landing page route handler
- app/templates/landing/index.html - Product list template
- tests/contract/test_landing_routes.py - Contract tests (6 scenarios)
- tests/integration/test_landing_flow.py - User journey test

**Modified Files**:
- app/models/product.py - Add load_active() class method
- app/__init__.py - Register landing blueprint

## Key Technical Decisions:

1. **Filtering**: status=='active' AND submission_url_slug exists
2. **Sorting**: Alphabetical by name (case-insensitive), then product_id
3. **Empty State**: "No products are currently accepting feedback" message
4. **XSS Prevention**: Jinja2 auto-escaping (no manual escaping needed)
5. **Performance**: File I/O sufficient (<1s for 100 products, no caching)

## Next Steps:

1. Run /speckit.tasks to generate tasks.md
2. Run /speckit.implement to execute TDD workflow
3. Verify all tests pass
4. Manual verification checklist
5. Create pull request

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-17 14:26:47 +02:00
co-authored by Claude
parent fb418bac65
commit 0f71ba969f
7 changed files with 868 additions and 13 deletions
+23 -12
View File
@@ -5,6 +5,16 @@
**Status**: Draft
**Input**: User description: "At the moment visitors of the website need to know the link to the product submission page when they want to submit a feedback. The now should be able to see a list of all active products in order to choose what product they want to give a feedback."
## Clarifications
### Session 2025-10-17
- Q: When a product configuration has a missing or invalid `submission_url_slug`, how should the landing page handle it? → A: Skip the product silently and log an error (user sees only valid products)
- Q: How should archived products be handled on the landing page? → A: Do not display archived products at all (only show active products)
- Q: When an authenticated product owner or admin accesses the landing page at `/`, what should happen? → A: Show the landing page normally (authentication doesn't affect access)
- Q: When a product has no description field (or it's empty), what should be displayed? → A: Display product name only (no description text shown)
- Q: When multiple products have identical names, how should they be sorted in the alphabetical list? → A: Order by product_id alphabetically as secondary sort
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Browse and Select Product (Priority: P1)
@@ -17,7 +27,7 @@ A visitor arrives at the Reklamator platform without knowing the specific produc
**Acceptance Scenarios**:
1. **Given** a visitor arrives at the platform root URL (`/`), **When** they view the page, **Then** they see a list of all active products with product names and brief descriptions
1. **Given** a visitor arrives at the platform root URL (`/`), **When** they view the page, **Then** they see a list of all active products with product names (and descriptions if available)
2. **Given** multiple active products exist in the system, **When** a visitor views the landing page, **Then** all active products are displayed in a clear, organized list
3. **Given** a visitor sees the product list, **When** they click on a product name or "Submit Feedback" button, **Then** they are redirected to that product's submission form (`/submit/{product-slug}`)
4. **Given** a product has a descriptive summary, **When** displayed on the landing page, **Then** the summary helps the visitor understand what the product is
@@ -31,13 +41,13 @@ A visitor wants to understand which products are currently accepting feedback an
**Why this priority**: Provides transparency about product status and prevents user frustration. This is secondary to basic discovery but improves user experience by setting clear expectations.
**Independent Test**: Can be tested independently by creating products with different statuses (active, archived) and verifying that only active products appear on the landing page, or that archived products are clearly marked as not accepting feedback.
**Independent Test**: Can be tested independently by creating products with different statuses (active, archived) and verifying that only active products appear on the landing page (archived products are not displayed).
**Acceptance Scenarios**:
1. **Given** a product has status "active", **When** the landing page loads, **Then** the product appears in the list
2. **Given** a product has status "archived", **When** the landing page loads, **Then** the product does NOT appear in the list (or appears with clear "not accepting feedback" indicator)
3. **Given** some products are active and some are archived, **When** the landing page loads, **Then** only active products are shown by default
2. **Given** a product has status "archived", **When** the landing page loads, **Then** the product does NOT appear in the list
3. **Given** some products are active and some are archived, **When** the landing page loads, **Then** only active products are shown
4. **Given** a visitor views the landing page, **When** they see a product listed, **Then** they can trust that clicking it will allow them to submit feedback
---
@@ -61,12 +71,12 @@ A visitor who already knows which product they want to submit feedback for can q
### Edge Cases
- **What happens when there are no active products?** Display a message: "No products are currently accepting feedback. Please check back later."
- **What happens when all products are archived?** Same as no active products - show appropriate message explaining no products available
- **What happens when a product has no description?** Display product name only, or show placeholder text like "No description available"
- **What happens when a visitor accesses the landing page while authenticated as a product owner?** They should still see the landing page (authentication doesn't affect anonymous submission access), or optionally redirect to dashboard
- **What happens when all products are archived?** Same as no active products - display the "No products are currently accepting feedback" message (archived products are not shown)
- **What happens when a product has no description?** Display product name only (no description text or placeholder shown)
- **What happens when a visitor accesses the landing page while authenticated as a product owner?** They see the landing page normally (authentication doesn't affect landing page access)
- **What happens when product names are very long or contain special characters?** Ensure proper text truncation/wrapping and HTML escaping for XSS prevention
- **What happens when multiple products have similar names?** Display them all clearly - let descriptions help differentiate
- **What happens if a product's submission_url_slug is missing or invalid?** Skip that product in the listing with error logged, or show error state
- **What happens when multiple products have identical names?** Display them all; sort by product_id alphabetically as secondary sort (after name)
- **What happens if a product's submission_url_slug is missing or invalid?** Skip that product silently in the listing and log an error for admin investigation
## Requirements *(mandatory)*
@@ -77,15 +87,16 @@ A visitor who already knows which product they want to submit feedback for can q
- **FR-003**: System MUST filter products to show ONLY those with `status: active` in their config.yaml
- **FR-004**: System MUST display for each product: product name (`name` field from config.yaml)
- **FR-005**: System MUST provide a clickable link/button for each product that navigates to `/submit/{submission_url_slug}`
- **FR-006**: System MUST handle products without descriptions gracefully (show name only or placeholder)
- **FR-006**: System MUST handle products without descriptions gracefully (show product name only, no placeholder text)
- **FR-007**: System MUST maintain existing direct URL functionality (`/submit/{product-slug}` continues to work)
- **FR-008**: Landing page MUST be accessible to anonymous users (no authentication required)
- **FR-009**: System MUST sort products in a consistent, predictable order (alphabetical by name recommended)
- **FR-008**: Landing page MUST be accessible to anonymous users (no authentication required); authenticated users also see the landing page normally
- **FR-009**: System MUST sort products alphabetically by name (case-insensitive); if names are identical, use product_id alphabetically as secondary sort
- **FR-010**: System MUST handle the case where no active products exist (display appropriate message)
- **FR-011**: Product listing MUST be server-side rendered (consistent with project's no-JavaScript requirement)
- **FR-012**: System MUST escape all product names and descriptions to prevent XSS attacks
- **FR-013**: Landing page MUST use the same minimal HTML/CSS styling as the rest of the application (no frameworks)
- **FR-014**: System MUST log when the landing page is accessed (for monitoring/analytics)
- **FR-015**: System MUST skip products with missing or invalid `submission_url_slug` and log an error (product not shown to users)
### Key Entities