# Implementation Plan: Product Selection Landing Page **Branch**: `002-product-list` | **Date**: 2025-10-17 | **Spec**: [spec.md](./spec.md) ## Summary Add a landing page at root URL (`/`) that lists all active products, enabling visitors to discover and select products for feedback submission. This removes the barrier of requiring users to know direct product URLs. **Technical approach**: Add new Flask route, reuse existing Product model, create simple HTML template with server-side rendering. No new dependencies needed. ## Technical Context **Language/Version**: Python 3.11+ **Primary Dependencies**: Flask 3.0+, Jinja2 (built-in) **Storage**: File-based (data/products/*/config.yaml - existing) **Testing**: pytest + pytest-flask (existing) **Target Platform**: Linux server (existing deployment) **Project Type**: Web application (Flask backend with server-side rendering) **Performance Goals**: <1 second page load for up to 100 products **Constraints**: Server-side rendering only (no JavaScript), minimal CSS (no frameworks) **Scale/Scope**: Simple single-page addition to existing Flask app ## Constitution Check *GATE: Must pass before Phase 0 research.* ### Principle I: Specification-First Development ✅ **PASS** - Complete specification exists at spec.md with prioritized user stories, functional requirements, and success criteria. ### Principle II: Test-First Discipline ✅ **PASS** - Implementation will follow TDD: contract tests → integration tests → implementation. ### Principle III: Independent User Stories ✅ **PASS** - All 3 user stories (P1: Browse/Select, P2: Status visibility, P3: Direct nav) are independently testable and deliverable. ### Principle IV: Simplicity & Justification ✅ **PASS** - Feature reuses existing architecture (Flask routes, Product model, Jinja2 templates). No new abstractions, dependencies, or complexity added. ### Principle V: Documentation as Code ✅ **PASS** - Specification, plan, and implementation artifacts maintained in specs/002-product-list/ with version control. **Constitution Status**: ✅ All principles satisfied. No violations to justify. ## Project Structure ### Documentation (this feature) ``` specs/002-product-list/ ├── spec.md # Feature specification (complete) ├── plan.md # This file ├── research.md # Phase 0 - Technical research (minimal - reuses 001) ├── data-model.md # Phase 1 - Data model (reference to existing Product) ├── contracts/ # Phase 1 - API contract (GET / route) │ └── landing-page.yaml ├── quickstart.md # Phase 1 - Developer quickstart └── tasks.md # Phase 2 - Task breakdown (/speckit.tasks) ``` ### Source Code (repository root) ``` app/ ├── models/ │ └── product.py # Existing - no changes needed ├── routes/ │ └── landing.py # NEW - landing page route └── templates/ └── landing/ └── index.html # NEW - product list template tests/ ├── contract/ │ └── test_landing_routes.py # NEW - contract tests for GET / └── integration/ └── test_landing_flow.py # NEW - end-to-end user journey tests ``` **Structure Decision**: Reuse existing Flask application structure. Landing page is a simple addition: one new route file, one new template, and corresponding tests. Follows established patterns from feature 001. ## Complexity Tracking *No violations - table not needed.* All complexity requirements from Constitution Principle IV are satisfied: - No additional abstraction layers - No new dependencies - No new design patterns - Reuses existing Flask/Jinja2/Product architecture --- ## Phase 0: Research ### Research Scope Since this feature builds on existing infrastructure from 001-build-an-application, minimal research is needed. Key questions already answered: 1. **Product data access**: Resolved in 001 - Product.load_all() method exists 2. **Template rendering**: Resolved in 001 - Jinja2 with server-side rendering 3. **Route patterns**: Resolved in 001 - Flask blueprints for organization 4. **Sorting implementation**: Python built-in sorted() with key function ### New Technical Decisions Only one new decision needed for this feature: **Product List Retrieval & Sorting** - Decision: Extend existing Product model with `load_active()` class method - Rationale: Centralizes "active products only" logic, enables reuse - Sorting: Python's `sorted()` with `key=lambda p: (p.name.lower(), p.product_id)` - Performance: File I/O for 100 products ~10-50ms (acceptable for <1s target) **Output**: research.md (minimal - references 001, documents sorting decision) --- ## Phase 1: Design & Contracts ### Data Model **Entities**: Reuse existing Product model from 001-build-an-application **Extension needed**: ```python # app/models/product.py - add class method @classmethod def load_active(cls): """Load all active products, sorted alphabetically by name then product_id""" all_products = cls.load_all() active = [p for p in all_products if p.status == 'active' and p.submission_url_slug] return sorted(active, key=lambda p: (p.name.lower(), p.product_id)) ``` **Output**: data-model.md (references existing Product entity, documents extension) ### API Contracts **New Route**: `GET /` **Contract**: ```yaml # contracts/landing-page.yaml paths: /: get: summary: Landing page - list active products operationId: getLandingPage responses: '200': description: HTML page with product list content: text/html: schema: type: string examples: with_products: summary: Multiple active products value: |
No products are currently accepting feedback.
``` **Output**: contracts/landing-page.yaml ### Developer Quickstart Key implementation points for developers: 1. **Route**: app/routes/landing.py with `@app.route('/')` 2. **Template**: app/templates/landing/index.html - loop over products 3. **XSS Prevention**: Use Jinja2 auto-escaping for product names/descriptions 4. **Empty State**: Check `if products` to show appropriate message 5. **Logging**: Log landing page access with product count **Output**: quickstart.md ### Agent Context Update Run: `.specify/scripts/bash/update-agent-context.sh claude` **Expected update**: No new technologies added (reuses Flask, Jinja2, Python 3.11+) **Output**: Updated .claude.md or equivalent agent context file --- ## Phase 2: Task Generation **Not executed by /speckit.plan** - run `/speckit.tasks` next. Expected task structure: 1. Contract tests for GET / (various scenarios) 2. Integration test for user journey 3. Implement Product.load_active() method 4. Implement landing route 5. Create landing template 6. Add logging 7. Manual verification **Output**: tasks.md (generated by /speckit.tasks command) --- ## Next Steps 1. ✅ Phase 0 complete: Generate research.md 2. ✅ Phase 1 complete: Generate data-model.md, contracts/, quickstart.md 3. ⏭️ Run `/speckit.tasks` to generate tasks.md 4. ⏭️ Run `/speckit.implement` to execute tasks **Branch**: 002-product-list **Plan**: /home/markus/workspace/reklamator/specs/002-product-list/plan.md