Files
Reklamator/specs/002-product-list/plan.md
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

7.7 KiB

Implementation Plan: Product Selection Landing Page

Branch: 002-product-list | Date: 2025-10-17 | Spec: 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:

# 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:

# 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: |
                    <html>
                      <h1>Select a Product</h1>
                      <ul>
                        <li><a href="/submit/product-a">Product A</a> - Description</li>
                        <li><a href="/submit/product-b">Product B</a></li>
                      </ul>
                    </html>
                no_products:
                  summary: No active products
                  value: |
                    <html>
                      <p>No products are currently accepting feedback.</p>
                    </html>

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