diff --git a/CLAUDE.md b/CLAUDE.md
index 60829bc..99c5cbb 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -4,6 +4,8 @@ Auto-generated from all feature plans. Last updated: 2025-10-15
## Active Technologies
- Python 3.11+ + Flask (web framework), no CSS frameworks, no JavaScript libraries (001-build-an-application)
+- Python 3.11+ + Flask 3.0+, Jinja2 (built-in) (002-product-list)
+- File-based (data/products/*/config.yaml - existing) (002-product-list)
## Project Structure
```
@@ -19,7 +21,8 @@ cd src [ONLY COMMANDS FOR ACTIVE TECHNOLOGIES][ONLY COMMANDS FOR ACTIVE TECHNOLO
Python 3.11+: Follow standard conventions
## Recent Changes
+- 002-product-list: Added Python 3.11+ + Flask 3.0+, Jinja2 (built-in)
- 001-build-an-application: Added Python 3.11+ + Flask (web framework), no CSS frameworks, no JavaScript libraries
-
\ No newline at end of file
+
diff --git a/specs/002-product-list/contracts/landing-page.yaml b/specs/002-product-list/contracts/landing-page.yaml
new file mode 100644
index 0000000..b92e40d
--- /dev/null
+++ b/specs/002-product-list/contracts/landing-page.yaml
@@ -0,0 +1,101 @@
+openapi: 3.0.3
+info:
+ title: Reklamator Landing Page API
+ version: 1.0.0
+ description: Product selection landing page contract for feature 002-product-list
+
+paths:
+ /:
+ get:
+ summary: Landing page - list active products
+ description: |
+ Display a landing page showing all active products available for feedback submission.
+ Products are sorted alphabetically by name (case-insensitive), with product_id as tiebreaker.
+ operationId: getLandingPage
+ tags:
+ - Landing Page
+ responses:
+ '200':
+ description: HTML page with product list or empty state message
+ content:
+ text/html:
+ schema:
+ type: string
+ description: Server-rendered HTML page
+ examples:
+ with_products:
+ summary: Multiple active products displayed
+ value: |
+
+
+
Select a Product
+
+ Select a Product for Feedback
+
+
+
+
+ no_products:
+ summary: No active products (empty state)
+ value: |
+
+
+ Select a Product
+
+ Select a Product for Feedback
+ No products are currently accepting feedback. Please check back later.
+
+
+
+ product_without_description:
+ summary: Product without description (no placeholder text)
+ value: |
+
+
+ Select a Product
+
+ Select a Product for Feedback
+
+
+
+
+components:
+ schemas:
+ # No request/response schemas needed (HTML rendering)
+ # Product data comes from file-based storage, not API request body
+
+# Contract Test Scenarios
+# These scenarios should be covered in tests/contract/test_landing_routes.py:
+#
+# 1. GET / with active products → 200 OK with product list HTML
+# 2. GET / with no active products → 200 OK with empty state message
+# 3. GET / with mixed active/archived → 200 OK showing only active
+# 4. GET / verifies alphabetical sorting (name, then product_id)
+# 5. GET / excludes products with missing submission_url_slug
+# 6. GET / properly escapes product names (XSS prevention)
+# 7. GET / displays descriptions when present
+# 8. GET / omits description placeholder when missing
+# 9. GET / accessible to anonymous users
+# 10. GET / accessible to authenticated users (same behavior)
+
+# Success Criteria Validation:
+# - SC-001: Page contains clickable links to /submit/{slug}
+# - SC-002: Response time <1s for up to 100 products
+# - SC-004: Existing /submit/{slug} routes still functional (backwards compatibility)
+# - SC-005: Empty state message displayed when no active products
+# - SC-006: HTML escaping prevents XSS (test with "
+ # Assert: HTML is escaped, script not executed
+ pass
+
+@pytest.mark.contract
+def test_get_landing_page_missing_slug(client, temp_data_dir):
+ """T306: GET / excludes products with missing submission_url_slug"""
+ # Setup: Product with submission_url_slug = None
+ # Assert: Product not shown in list
+ pass
+```
+
+---
+
+### 5. Write Integration Tests
+
+**File**: `tests/integration/test_landing_flow.py` (new file)
+
+**User journey test**:
+
+```python
+@pytest.mark.integration
+def test_landing_to_submission_flow(client, temp_data_dir):
+ """T307: Complete flow - landing page → product selection → submission form"""
+ # Step 1: Visit landing page, see products
+ # Step 2: Click product link
+ # Step 3: Verify redirected to /submit/{slug}
+ pass
+```
+
+---
+
+## Key Implementation Notes
+
+### XSS Prevention
+- ✅ Jinja2 auto-escaping handles product names and descriptions
+- ✅ No manual HTML escaping needed
+- ✅ Test with `