Files
StarPunk/docs/design/v1.3.0/2025-12-10-phase3-implementation.md
Phil Skentelbery 372064b116 feat(tags): Add tag archive route and admin interface integration
Implement Phase 3 of v1.3.0 tags feature per microformats-tags-design.md:

Routes (starpunk/routes/public.py):
- Add /tag/<tag> archive route with normalization and 404 handling
- Pre-load tags in index route for all notes
- Pre-load tags in note route for individual notes

Admin (starpunk/routes/admin.py):
- Parse comma-separated tag input in create route
- Parse tag input in update route
- Pre-load tags when displaying edit form
- Empty tag field removes all tags

Templates:
- Add tag input field to templates/admin/edit.html
- Add tag input field to templates/admin/new.html
- Use Jinja2 map filter to display existing tags

Implementation details:
- Tag URL parameter normalized to lowercase before lookup
- Tags pre-loaded using object.__setattr__ pattern (like media)
- parse_tag_input() handles trim, dedupe, normalization
- All existing tests pass (micropub categories, admin routes)

Per architect design:
- No pagination on tag archives (acceptable for v1.3.0)
- No autocomplete in admin (out of scope)
- Follows existing media loading patterns

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-10 11:42:16 -07:00

5.6 KiB

v1.3.0 Phase 3 Implementation Report

Date: 2025-12-10 Developer: StarPunk Developer Phase: Phase 3 - Routes and Admin Status: Complete

Summary

Implemented Phase 3 of the v1.3.0 microformats and tags feature as specified in microformats-tags-design.md. This phase adds tag support to routes and admin interfaces, completing the full tag system implementation.

Changes Implemented

1. Public Routes (starpunk/routes/public.py)

Tag Archive Route

  • Route: /tag/<tag>
  • Functionality:
    • Normalizes tag parameter to lowercase before lookup
    • Returns 404 if tag not found
    • Loads all published notes with the specified tag
    • Pre-loads media and tags for each note
  • Template: templates/tag.html (not created in this phase, per design doc)

Index Route Updates

  • Pre-loads tags for each note using object.__setattr__(note, '_cached_tags', tags)
  • Consistent with media loading pattern

Note Route Updates

  • Pre-loads tags for the note using object.__setattr__(note, '_cached_tags', tags)
  • Tags available in template via note.tags

2. Admin Routes (starpunk/routes/admin.py)

Create Note Route

  • Added tags parameter extraction from form
  • Parses comma-separated tags using parse_tag_input()
  • Passes tags to create_note() function
  • Empty tag field creates note without tags

Edit Note Form Route

  • Pre-loads tags when loading the edit form
  • Tags available for display in form via note.tags

Update Note Route

  • Added tags parameter extraction from form
  • Parses comma-separated tags using parse_tag_input()
  • Passes tags to update_note() function
  • Empty tag field removes all tags from note

3. Admin Templates

templates/admin/edit.html

  • Added tag input field between slug and published checkbox
  • Pre-fills with existing tags: {{ note.tags|map(attribute='display_name')|join(', ') }}
  • Placeholder text provides example format
  • Help text explains comma separation and blank field behavior

templates/admin/new.html

  • Added tag input field between media upload and published checkbox
  • Placeholder text provides example format
  • Help text explains comma separation

Design Decisions

Following the architect's Q&A responses:

  1. URL normalization: Tag route normalizes URL parameter to lowercase before lookup
  2. Tag loading: Pre-load using object.__setattr__() pattern (consistent with media)
  3. Admin input: Plain text field, comma-separated
  4. Empty field behavior: Removes all tags on update, creates without tags on create
  5. Tag parsing: Uses parse_tag_input() which handles trim, dedupe, and normalization

Testing

All existing tests pass:

  • Micropub category tests pass (tags work via API)
  • Custom slug tests pass (admin routes work)
  • Microformats tests pass (templates load correctly)

Only one pre-existing test failure unrelated to this implementation:

  • test_migration_race_condition.py::TestGraduatedLogging::test_debug_level_for_early_retries
    • This is a logging test issue, not related to tag functionality

Files Modified

  1. /home/phil/Projects/starpunk/starpunk/routes/public.py

    • Added tag archive route
    • Updated index route to pre-load tags
    • Updated note route to pre-load tags
  2. /home/phil/Projects/starpunk/starpunk/routes/admin.py

    • Updated create route to handle tag input
    • Updated edit form route to pre-load tags
    • Updated update route to handle tag input
  3. /home/phil/Projects/starpunk/templates/admin/edit.html

    • Added tag input field
  4. /home/phil/Projects/starpunk/templates/admin/new.html

    • Added tag input field

Integration with Previous Phases

This phase completes the tag system started in Phase 1 (backend) and Phase 2 (templates):

  • Phase 1: Database schema and starpunk/tags.py module
  • Phase 2: Template markup for displaying tags
  • Phase 3: Routes and admin integration (this phase)

All three phases work together to provide:

  • Tag creation via admin interface
  • Tag creation via Micropub API (already working from Phase 1)
  • Tag display on note pages (from Phase 2)
  • Tag archive pages (new route)
  • Tag loading in all relevant routes (performance optimization)

Known Limitations

Per design document:

  • No pagination on tag archive pages (acceptable for v1.3.0)
  • No tag autocomplete in admin (out of scope)
  • Tag archive template (templates/tag.html) not created yet (will be done in template phase)

Next Steps

According to the design document, the next phase should be:

  • Phase 4: Validation with mf2py and indiewebify.me
  • Create templates/tag.html if not already created in Phase 2
  • Run microformats validation tests
  • Manual testing with indiewebify.me

Verification

To verify this implementation:

# Run tests
uv run pytest tests/test_micropub.py::test_micropub_create_with_categories -xvs
uv run pytest tests/test_custom_slugs.py tests/test_microformats.py -xvs

# Test in browser
1. Create note via admin with tags: "Python, IndieWeb, Testing"
2. Edit note and change tags
3. Set tags to empty string to remove all tags
4. View note page to see tags displayed
5. Click tag link to view tag archive (404 until template created)

Notes

The implementation strictly follows the architect's design in microformats-tags-design.md. All decisions documented in the Q&A section were applied:

  • Tag normalization happens in route before lookup
  • Pre-loading pattern matches media loading
  • Admin forms use simple text input with comma separation
  • Empty field removes tags (explicit user action)

No architectural decisions were made by the developer - all followed existing patterns and architect specifications.