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:
@@ -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: |
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Select a Product</title></head>
|
||||
<body>
|
||||
<h1>Select a Product for Feedback</h1>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/submit/acme-app">Acme Application</a>
|
||||
<p>Enterprise resource planning system</p>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/submit/beta-service">Beta Service</a>
|
||||
<p>Cloud infrastructure platform</p>
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
no_products:
|
||||
summary: No active products (empty state)
|
||||
value: |
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Select a Product</title></head>
|
||||
<body>
|
||||
<h1>Select a Product for Feedback</h1>
|
||||
<p>No products are currently accepting feedback. Please check back later.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
product_without_description:
|
||||
summary: Product without description (no placeholder text)
|
||||
value: |
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Select a Product</title></head>
|
||||
<body>
|
||||
<h1>Select a Product for Feedback</h1>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/submit/simple-app">Simple App</a>
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
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 <script> in product name)
|
||||
# - SC-007: No JavaScript in response (server-side rendered only)
|
||||
# - SC-008: Visual separation via HTML list structure
|
||||
Reference in New Issue
Block a user