Files
Reklamator/specs/002-product-list/contracts/landing-page.yaml
T
gurixandClaude 0f71ba969f 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>
2025-10-17 14:26:47 +02:00

102 lines
4.0 KiB
YAML

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