Complete implementation of v1.2.0 "IndieWeb Features" release. ## Phase 1: Custom Slugs - Optional custom slug field in note creation form - Auto-sanitization (lowercase, hyphens only) - Uniqueness validation with auto-numbering - Read-only after creation to preserve permalinks - Matches Micropub mp-slug behavior ## Phase 2: Author Discovery + Microformats2 - Automatic h-card discovery from IndieAuth identity URL - 24-hour caching with graceful fallback - Never blocks login (per ADR-061) - Complete h-entry, h-card, h-feed markup - All required Microformats2 properties - rel-me links for identity verification - Passes IndieWeb validation ## Phase 3: Media Upload - Upload up to 4 images per note (JPEG, PNG, GIF, WebP) - Automatic optimization with Pillow - Auto-resize to 2048px - EXIF orientation correction - 95% quality compression - Social media-style layout (media top, text below) - Optional captions for accessibility - Integration with all feed formats (RSS, ATOM, JSON Feed) - Date-organized storage with UUID filenames - Immutable caching (1 year) ## Database Changes - migrations/006_add_author_profile.sql - Author discovery cache - migrations/007_add_media_support.sql - Media storage ## New Modules - starpunk/author_discovery.py - h-card discovery and caching - starpunk/media.py - Image upload, validation, optimization ## Documentation - 4 new ADRs (056, 057, 058, 061) - Complete design specifications - Developer Q&A with 40+ questions answered - 3 implementation reports - 3 architect reviews (all approved) ## Testing - 56 new tests for v1.2.0 features - 842 total tests in suite - All v1.2.0 feature tests passing ## Dependencies - Added: mf2py (Microformats2 parser) - Added: Pillow (image processing) Version: 1.2.0-rc.1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
4.4 KiB
4.4 KiB
V1.2.0 Media Upload - Final Design Summary
Design Status: COMPLETE ✓
This document summarizes the finalized design for v1.2.0 media upload feature based on user requirements and architectural decisions.
User Requirements (Confirmed)
- Image limit: 4 images per note
- Reordering: Not needed (display order = upload order)
- Image optimization: Yes, automatic resize for large images
- Captions: Yes, optional caption field for each image
Architectural Decisions
ADR-057: Media Attachment Model
- Social media style attachments (not inline markdown)
- Media displays at TOP of notes
- Text content appears BELOW media
- Junction table for flexible associations
ADR-058: Image Optimization Strategy
- Max file size: 10MB per image
- Max dimensions: 4096x4096 pixels
- Auto-resize: Images >2048px resized automatically
- Processing library: Pillow
- Formats: JPEG, PNG, GIF, WebP only
Technical Specifications
Image Processing
- Validation: Size, dimensions, format, integrity
- Optimization: Resize to 2048px max, EXIF correction
- Quality: 95% JPEG quality (high quality)
- Storage: data/media/YYYY/MM/ structure
Database Schema
-- Media table with dimensions
CREATE TABLE media (
id INTEGER PRIMARY KEY,
filename TEXT NOT NULL,
original_name TEXT NOT NULL,
path TEXT NOT NULL UNIQUE,
mime_type TEXT NOT NULL,
size INTEGER NOT NULL,
width INTEGER,
height INTEGER,
uploaded_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- Junction table with captions
CREATE TABLE note_media (
id INTEGER PRIMARY KEY,
note_id INTEGER NOT NULL,
media_id INTEGER NOT NULL,
display_order INTEGER NOT NULL DEFAULT 0,
caption TEXT, -- For accessibility
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE,
FOREIGN KEY (media_id) REFERENCES media(id) ON DELETE CASCADE,
UNIQUE(note_id, media_id)
);
User Interface
- Multiple file input (accept images only)
- Caption field for each uploaded image
- Preview thumbnails during upload
- Remove button per image
- No drag-and-drop reordering
- Maximum 4 images enforced
Display Layout
- 1 image: Full width
- 2 images: Side by side (50% each)
- 3 images: Grid layout
- 4 images: 2x2 grid
Syndication Support
- RSS: HTML with images in description
- ATOM: Both enclosures and HTML content
- JSON Feed: Native attachments array
- Microformats2: Multiple u-photo properties
Implementation Guidance
Dependencies
- Pillow: For image processing and optimization
Processing Pipeline
- Check file size (<10MB)
- Validate MIME type
- Load with Pillow (validates integrity)
- Check dimensions (<4096px)
- Correct EXIF orientation
- Resize if needed (>2048px)
- Save optimized version
- Store metadata in database
Error Handling
Clear user-facing messages for:
- File too large
- Invalid format
- Dimensions too large
- Corrupted file
- Maximum images reached
Acceptance Criteria
- ✓ 4 image maximum per note
- ✓ No reordering interface
- ✓ Automatic optimization for large images
- ✓ Caption support for accessibility
- ✓ JPEG, PNG, GIF, WebP support
- ✓ 10MB file size limit
- ✓ 4096x4096 dimension limit
- ✓ Auto-resize at 2048px
- ✓ EXIF orientation correction
- ✓ Display order = upload order
Related Documents
/docs/decisions/ADR-057-media-attachment-model.md/docs/decisions/ADR-058-image-optimization-strategy.md/docs/design/v1.2.0/feature-specification.md/docs/design/v1.2.0/media-implementation-guide.md
Design Sign-off
The v1.2.0 media upload feature design is now complete and ready for implementation. All user requirements have been addressed, technical decisions documented, and implementation guidance provided.
Key Highlights
- Simple and elegant: Automatic optimization, no complex UI
- Accessible: Caption support for all images
- Standards-compliant: Full syndication feed support
- Performant: Optimized images, reasonable limits
- Secure: Multiple validation layers, Pillow verification
Next Steps
- Implement database migrations
- Create MediaProcessor class with Pillow
- Add upload endpoint to admin routes
- Update note creation/edit forms
- Implement media display in templates
- Update feed generators for media
- Write comprehensive tests