Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3222620cee | |||
| 247eb34c36 | |||
| 41b65703f9 | |||
| f901aa2242 | |||
| 5ca8b7e9b4 | |||
| 3d80e1af51 | |||
| 372064b116 | |||
| 377027e79a | |||
| f10d0679da | |||
| 927db4aea0 | |||
| 27501f6381 | |||
| 10d85bb78b | |||
| dd822a35b5 |
114
CHANGELOG.md
114
CHANGELOG.md
@@ -7,6 +7,120 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.3.0] - 2025-12-10
|
||||
|
||||
### Added
|
||||
|
||||
- **Tag/Category System** - Complete tag support with hierarchical organization
|
||||
- Tag creation and management via web UI and Micropub
|
||||
- Support for Micropub `category` property in JSON and form-encoded requests
|
||||
- Tag archive pages at `/tags/{tag}` with all tagged notes
|
||||
- Tag cloud display on homepage showing all used tags
|
||||
- Tag filtering in database queries (list_notes_by_tag)
|
||||
- Reserved tag validation (prevents tags like 'api', 'admin', etc.)
|
||||
- Comprehensive tag management in admin dashboard
|
||||
- Database schema: tags table with slug and name fields
|
||||
- Many-to-many relationship between notes and tags
|
||||
- Automatic tag cleanup (removes orphaned tags)
|
||||
|
||||
- **Strict Microformats2 Compliance** - Enhanced h-entry markup for parsers
|
||||
- p-category property for each tag in note markup
|
||||
- dt-updated property displays when note is modified
|
||||
- dt-published always shown for temporal context
|
||||
- u-uid property matches u-url for permalink stability
|
||||
- Proper h-feed structure on homepage and tag archives
|
||||
- p-name property only when note has explicit title (# heading)
|
||||
- e-content wraps full note content
|
||||
- Nested h-card for author within each h-entry
|
||||
- Homepage displays as complete h-feed with feed properties
|
||||
|
||||
- **h-feed Properties** - Proper feed markup on collection pages
|
||||
- Homepage marked as h-feed with p-name "Recent Notes"
|
||||
- Tag archive pages marked as h-feed with descriptive p-name
|
||||
- Each feed contains multiple h-entry items
|
||||
- Feed structure validates with Microformats2 parsers
|
||||
- Supports feed readers and IndieWeb aggregators
|
||||
|
||||
### Changed
|
||||
|
||||
- **Template Structure** - Reorganized for better Microformats2 compliance
|
||||
- Homepage template now wraps entries in proper h-feed
|
||||
- Note display templates use semantic h-entry markup
|
||||
- Tag display integrated throughout note views
|
||||
- Consistent Microformats2 patterns across all pages
|
||||
|
||||
### Technical Details
|
||||
|
||||
- Migration 006: Add tags table and note_tags junction table
|
||||
- New module: `starpunk/tags.py` with tag CRUD operations
|
||||
- Enhanced: `starpunk/notes.py` with tag relationship handling
|
||||
- Enhanced: `starpunk/micropub.py` with category property support
|
||||
- Enhanced: Templates with p-category and h-feed markup
|
||||
- All tests passing (580+ tests)
|
||||
- 100% backward compatible with existing notes
|
||||
|
||||
## [1.2.0] - 2025-12-09
|
||||
|
||||
### Added
|
||||
- **Feed Media Enhancement** - Media RSS and JSON Feed image support for improved feed reader compatibility
|
||||
- RSS feeds now include Media RSS namespace (xmlns:media) for structured media metadata
|
||||
- RSS enclosure element added for first image (per RSS 2.0 spec)
|
||||
- Media RSS media:content elements for all images with type, medium, and fileSize attributes
|
||||
- Media RSS media:thumbnail element for first image preview
|
||||
- JSON Feed items include "image" field with first image URL (per JSON Feed 1.1 spec)
|
||||
- Image field absent (not null) when no media attached
|
||||
- Both feed formats maintain existing HTML embedding for universal reader support
|
||||
- Provides enhanced display in modern feed readers (Feedly, Inoreader, NetNewsWire)
|
||||
|
||||
- **Custom Slug Input Field** - Web UI now supports custom slugs (v1.2.0 Phase 1)
|
||||
- Added optional custom slug field to note creation form
|
||||
- Slugs are read-only after creation to preserve permalinks
|
||||
- Auto-validates and sanitizes slug format (lowercase, numbers, hyphens only)
|
||||
- Shows helpful placeholder text and validation guidance
|
||||
- Matches Micropub `mp-slug` behavior for consistency
|
||||
- Falls back to auto-generation when field is left blank
|
||||
|
||||
- **Author Profile Discovery** - Automatic h-card discovery from IndieAuth identity (v1.2.0 Phase 2)
|
||||
- Discovers author information from user's IndieAuth profile URL on login
|
||||
- Caches author h-card data (name, photo, bio, rel-me links) for 24 hours
|
||||
- Uses mf2py library for reliable Microformats2 parsing
|
||||
- Graceful fallback to domain name if discovery fails
|
||||
- Never blocks login functionality (per ADR-061)
|
||||
- Eliminates need for manual author configuration
|
||||
|
||||
- **Complete Microformats2 Support** - Full IndieWeb h-entry, h-card, h-feed markup (v1.2.0 Phase 2)
|
||||
- All notes display as proper h-entry with required properties (u-url, dt-published, e-content, p-author)
|
||||
- Author h-card nested within each h-entry (not standalone)
|
||||
- p-name property only added when note has explicit title (starts with # heading)
|
||||
- u-uid and u-url match for notes (permalink stability)
|
||||
- Homepage displays as h-feed with proper structure
|
||||
- rel-me links from discovered profile added to HTML head
|
||||
- dt-updated property shown when note is modified
|
||||
- Passes Microformats2 validation (indiewebify.me compatible)
|
||||
|
||||
- **Media Upload Support** - Image upload and display for notes (v1.2.0 Phase 3)
|
||||
- Upload up to 4 images per note via web UI (JPEG, PNG, GIF, WebP)
|
||||
- Automatic image optimization with Pillow library
|
||||
- Rejects files over 10MB or dimensions over 4096x4096 pixels
|
||||
- Auto-resizes images over 2048px (longest edge) to improve performance
|
||||
- EXIF orientation correction ensures proper display
|
||||
- Social media style layout: media displays at top, text content below
|
||||
- Optional captions for accessibility (used as alt text)
|
||||
- Media stored in date-organized folders (data/media/YYYY/MM/)
|
||||
- UUID-based filenames prevent collisions
|
||||
- Media included in all syndication feeds (RSS, ATOM, JSON Feed)
|
||||
- RSS: HTML embedding in description
|
||||
- ATOM: Both enclosures and HTML content
|
||||
- JSON Feed: Native attachments array
|
||||
- Multiple u-photo properties in Microformats2 markup
|
||||
- Media files cached immutably (1 year) for performance
|
||||
|
||||
### Fixed
|
||||
- **Media Display on Homepage** - Images now display correctly on homepage, not just individual note pages
|
||||
- **Responsive Image Sizing** - Images constrained to container width with proper CSS
|
||||
- **Caption Display** - Captions now used as alt text only, not displayed as visible text
|
||||
- **Logging Correlation ID** - Fixed crash in non-request contexts (app init, memory monitor)
|
||||
|
||||
## [1.1.2] - 2025-11-28
|
||||
|
||||
### Fixed
|
||||
|
||||
85
CLAUDE.md
85
CLAUDE.md
@@ -8,97 +8,50 @@ This file contains operational instructions for Claude agents working on this pr
|
||||
- All Python commands must be run with `uv run` prefix
|
||||
- Example: `uv run pytest`, `uv run flask run`
|
||||
|
||||
## Agent Protocol (All Agents)
|
||||
|
||||
**IMPORTANT**: All agents must review `docs/DOCUMENTATION.md` before starting work. This file is the authoritative source for documentation organization and supersedes any other instructions.
|
||||
|
||||
## Agent-Architect Protocol
|
||||
|
||||
When invoking the agent-architect, always remind it to:
|
||||
|
||||
1. Review documentation in docs/ before working on the task it is given
|
||||
- docs/architecture, docs/decisions, docs/standards are of particular interest
|
||||
1. Review `docs/DOCUMENTATION.md` for documentation organization standards
|
||||
|
||||
2. Give it the map of the documentation folder as described in the "Understanding the docs/ Structure" section below
|
||||
2. Review documentation in docs/ before working on the task it is given
|
||||
- docs/architecture, docs/decisions, docs/standards are of particular interest
|
||||
|
||||
3. Search for authoritative documentation for any web standard it is implementing on https://www.w3.org/
|
||||
|
||||
4. If it is reviewing a developers implementation report and it is accepts the completed work it should go back and update the project plan to reflect the completed work
|
||||
4. If it is reviewing a developers implementation report and it accepts the completed work it should go back and update the project plan to reflect the completed work
|
||||
|
||||
## Agent-Developer Protocol
|
||||
|
||||
When invoking the agent-developer, always remind it to:
|
||||
|
||||
1. **Document work in reports**
|
||||
- Create implementation reports in `docs/reports/`
|
||||
- Include date in filename: `YYYY-MM-DD-description.md`
|
||||
1. Review `docs/DOCUMENTATION.md` for documentation organization standards
|
||||
|
||||
2. **Update the changelog**
|
||||
2. **Document work in design folder**
|
||||
- Create implementation reports in `docs/design/{version}/`
|
||||
- Include date in filename: `YYYY-MM-DD-description.md`
|
||||
- All developer interaction (questions, responses, reports, reviews) goes in design/{version}/
|
||||
|
||||
3. **Update the changelog**
|
||||
- Add entries to `CHANGELOG.md` for user-facing changes
|
||||
- Follow existing format
|
||||
|
||||
3. **Version number management**
|
||||
4. **Version number management**
|
||||
- Increment version numbers according to `docs/standards/versioning-strategy.md`
|
||||
- Update version in `starpunk/__init__.py`
|
||||
|
||||
4. **Follow git protocol**
|
||||
5. **Follow git protocol**
|
||||
- Adhere to git branching strategy in `docs/standards/git-branching-strategy.md`
|
||||
- Create feature branches for non-trivial changes
|
||||
- Write clear commit messages
|
||||
|
||||
## Documentation Navigation
|
||||
## Documentation
|
||||
|
||||
### Understanding the docs/ Structure
|
||||
|
||||
The `docs/` folder is organized by document type and purpose:
|
||||
|
||||
- **`docs/architecture/`** - System design overviews, component diagrams, architectural patterns
|
||||
- **`docs/decisions/`** - Architecture Decision Records (ADRs), numbered sequentially (ADR-001, ADR-002, etc.)
|
||||
- **`docs/deployment/`** - Deployment guides, infrastructure setup, operations documentation
|
||||
- **`docs/design/`** - Detailed design documents, feature specifications, phase plans
|
||||
- **`docs/examples/`** - Example implementations, code samples, usage patterns
|
||||
- **`docs/migration/`** - Migration guides for upgrading between versions and configuration changes
|
||||
- **`docs/projectplan/`** - Project roadmaps, implementation plans, feature scope definitions
|
||||
- **`docs/releases/`** - Release-specific documentation, release notes, version information
|
||||
- **`docs/reports/`** - Implementation reports from developers (dated: YYYY-MM-DD-description.md)
|
||||
- **`docs/reviews/`** - Architectural reviews, design critiques, retrospectives
|
||||
- **`docs/security/`** - Security-related documentation, vulnerability analyses, best practices
|
||||
- **`docs/standards/`** - Coding standards, conventions, processes, workflows
|
||||
|
||||
### Where to Find Documentation
|
||||
|
||||
- **Before implementing a feature**: Check `docs/decisions/` for relevant ADRs and `docs/design/` for specifications
|
||||
- **Understanding system architecture**: Start with `docs/architecture/overview.md`
|
||||
- **Coding guidelines**: See `docs/standards/` for language-specific standards and best practices
|
||||
- **Past implementation context**: Review `docs/reports/` for similar work (sorted by date)
|
||||
- **Project roadmap and scope**: Refer to `docs/projectplan/`
|
||||
|
||||
### Where to Create New Documentation
|
||||
|
||||
**Create an ADR (`docs/decisions/`)** when:
|
||||
- Making architectural decisions that affect system design
|
||||
- Choosing between competing technical approaches
|
||||
- Establishing patterns that others should follow
|
||||
- Format: `ADR-NNN-brief-title.md` (find next number sequentially)
|
||||
|
||||
**Create a design doc (`docs/design/`)** when:
|
||||
- Planning a complex feature implementation
|
||||
- Detailing technical specifications
|
||||
- Documenting multi-phase development plans
|
||||
|
||||
**Create an implementation report (`docs/reports/`)** when:
|
||||
- Completing significant development work
|
||||
- Documenting implementation details for architect review
|
||||
- Format: `YYYY-MM-DD-brief-description.md`
|
||||
|
||||
**Update standards (`docs/standards/`)** when:
|
||||
- Establishing new coding conventions
|
||||
- Documenting processes or workflows
|
||||
- Creating checklists or guidelines
|
||||
|
||||
### Key Documentation References
|
||||
|
||||
- **Architecture**: See `docs/architecture/overview.md`
|
||||
- **Implementation Plan**: See `docs/projectplan/v1/implementation-plan.md`
|
||||
- **Feature Scope**: See `docs/projectplan/v1/feature-scope.md`
|
||||
- **Coding Standards**: See `docs/standards/python-coding-standards.md`
|
||||
- **Testing**: See `docs/standards/testing-checklist.md`
|
||||
See `docs/DOCUMENTATION.md` for the authoritative documentation structure, navigation guidance, and key references.
|
||||
|
||||
## Project Philosophy
|
||||
|
||||
|
||||
18
README.md
18
README.md
@@ -2,13 +2,13 @@
|
||||
|
||||
A minimal, self-hosted IndieWeb CMS for publishing notes with RSS syndication.
|
||||
|
||||
**Current Version**: 1.1.0
|
||||
**Current Version**: 1.2.0
|
||||
|
||||
## Versioning
|
||||
|
||||
StarPunk follows [Semantic Versioning 2.0.0](https://semver.org/):
|
||||
- Version format: `MAJOR.MINOR.PATCH`
|
||||
- Current: `1.1.0` (stable release)
|
||||
- Current: `1.2.0` (stable release)
|
||||
- Check version: `python -c "from starpunk import __version__; print(__version__)"`
|
||||
- See changes: [CHANGELOG.md](CHANGELOG.md)
|
||||
- Versioning strategy: [docs/standards/versioning-strategy.md](docs/standards/versioning-strategy.md)
|
||||
@@ -29,10 +29,14 @@ StarPunk is designed for a single user who wants to:
|
||||
- **File-based storage**: Notes are markdown files, owned by you
|
||||
- **IndieAuth authentication**: Use your own website as identity
|
||||
- **Micropub support**: Full W3C Micropub specification compliance
|
||||
- **RSS feed**: Automatic syndication
|
||||
- **Media attachments**: Upload and display images with your notes
|
||||
- **Microformats2**: Full h-entry, h-card, and h-feed markup for IndieWeb compatibility
|
||||
- **Author discovery**: Automatic profile discovery from your IndieWeb identity
|
||||
- **RSS, ATOM, JSON Feed**: Multiple syndication formats with Media RSS support
|
||||
- **Custom slugs**: Control your note permalinks
|
||||
- **No database lock-in**: SQLite for metadata, files for content
|
||||
- **Self-hostable**: Run on your own server
|
||||
- **Minimal dependencies**: 6 core dependencies, no build tools
|
||||
- **Minimal dependencies**: Core dependencies, no build tools
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -154,8 +158,10 @@ See [docs/architecture/](docs/architecture/) for complete documentation.
|
||||
StarPunk implements:
|
||||
- [Micropub](https://micropub.spec.indieweb.org/) - Publishing API
|
||||
- [IndieAuth](https://www.w3.org/TR/indieauth/) - Authentication
|
||||
- [Microformats2](http://microformats.org/) - Semantic HTML markup
|
||||
- [RSS 2.0](https://www.rssboard.org/rss-specification) - Feed syndication
|
||||
- [Microformats2](http://microformats.org/) - h-entry, h-card, h-feed markup
|
||||
- [RSS 2.0](https://www.rssboard.org/rss-specification) with Media RSS extensions
|
||||
- [ATOM 1.0](https://validator.w3.org/feed/docs/atom.html) - Syndication format
|
||||
- [JSON Feed 1.1](https://jsonfeed.org/version/1.1) - Modern feed format
|
||||
|
||||
## Deployment
|
||||
|
||||
|
||||
57
docs/DOCUMENTATION.md
Normal file
57
docs/DOCUMENTATION.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# PURPOSE
|
||||
|
||||
This document describes how documentation in this folder should be organized and supersedes any other instructions.
|
||||
|
||||
# FOLDERS
|
||||
|
||||
## ARCHITECTURE
|
||||
|
||||
The architecture folder should contain documentation reflecting the current design of the system and should be updated at the end of each release to ensure it is current.
|
||||
|
||||
## DECISIONS
|
||||
|
||||
This folder contains any architectural decisions, documented as ADRs.
|
||||
|
||||
- Format: `ADR-NNN-brief-title.md` (numbered sequentially)
|
||||
- Create an ADR when making architectural decisions, choosing between technical approaches, or establishing patterns
|
||||
|
||||
## DESIGN
|
||||
|
||||
This folder is used by the architect to document implementation designs to be handed off to the developer. These designs should be sorted into subfolders reflecting the semantic version number of the release in question (e.g., `v1.0.0/`, `v1.1.1/`).
|
||||
|
||||
All developer interaction belongs in the appropriate version subfolder:
|
||||
- Implementation designs and specifications
|
||||
- Developer questions to the architect
|
||||
- Architect responses
|
||||
- Implementation reports (format: `YYYY-MM-DD-description.md`)
|
||||
- Implementation reviews
|
||||
|
||||
## PROJECTPLAN
|
||||
|
||||
This folder contains documents relating to the future state of the project. There should be a single BACKLOG.md file that lists future features by priority as well as bugs (which are assumed to be high priority). Items in this file can have one of the following priorities:
|
||||
|
||||
- Critical - Items that break existing functionality
|
||||
- High
|
||||
- Medium
|
||||
- Low
|
||||
|
||||
In addition to the backlog file each version should have a folder named for its semantic version with a RELEASE.md file which lists the features and bugs to be addressed in that release.
|
||||
|
||||
## STANDARDS
|
||||
|
||||
Includes any standards written by the architect that the developer needs to reference during development. Any deprecated standards should be moved to the DEPRECATED subfolder when appropriate.
|
||||
|
||||
# WHERE TO FIND DOCUMENTATION
|
||||
|
||||
- **Before implementing a feature**: Check `decisions/` for relevant ADRs and `design/{version}/` for specifications
|
||||
- **Understanding system architecture**: Start with `architecture/`
|
||||
- **Coding guidelines**: See `standards/`
|
||||
- **Past implementation context**: Review `design/{version}/` for similar work
|
||||
- **Project roadmap and scope**: Refer to `projectplan/`
|
||||
|
||||
# KEY REFERENCES
|
||||
|
||||
- **Architecture**: `architecture/`
|
||||
- **Coding Standards**: `standards/python-coding-standards.md`
|
||||
- **Testing**: `standards/testing-checklist.md`
|
||||
- **Project Backlog**: `projectplan/BACKLOG.md`
|
||||
110
docs/decisions/ADR-056-no-selfhosted-indieauth.md
Normal file
110
docs/decisions/ADR-056-no-selfhosted-indieauth.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# ADR-056: Use External IndieAuth Provider (Never Self-Host)
|
||||
|
||||
## Status
|
||||
**ACCEPTED** - This is a permanent, non-negotiable decision.
|
||||
|
||||
## Context
|
||||
StarPunk is a minimal IndieWeb CMS focused on **content creation and syndication**, not identity infrastructure. The project philosophy demands that every line of code must justify its existence.
|
||||
|
||||
The question of whether to implement self-hosted IndieAuth has been raised multiple times. This ADR documents the final, permanent decision on this matter.
|
||||
|
||||
## Decision
|
||||
**StarPunk will NEVER implement self-hosted IndieAuth.**
|
||||
|
||||
We will always rely on external IndieAuth providers such as:
|
||||
- indielogin.com (primary recommendation)
|
||||
- Other established IndieAuth providers
|
||||
|
||||
This decision is **permanent and non-negotiable**.
|
||||
|
||||
## Rationale
|
||||
|
||||
### 1. Project Focus
|
||||
StarPunk's mission is to be a minimal CMS for publishing IndieWeb content. Our core competencies are:
|
||||
- Publishing notes with proper microformats
|
||||
- Generating RSS/Atom/JSON feeds
|
||||
- Implementing Micropub for content creation
|
||||
- Media management for content
|
||||
|
||||
Identity infrastructure is explicitly **NOT** our focus.
|
||||
|
||||
### 2. Complexity vs Value
|
||||
Implementing IndieAuth would require:
|
||||
- OAuth 2.0 implementation
|
||||
- Token management
|
||||
- Security considerations
|
||||
- Key storage and rotation
|
||||
- User profile management
|
||||
- Authorization code flows
|
||||
|
||||
This represents hundreds or thousands of lines of code that don't serve our core mission of content publishing.
|
||||
|
||||
### 3. Existing Solutions Work
|
||||
External IndieAuth providers like indielogin.com:
|
||||
- Are battle-tested
|
||||
- Handle security updates
|
||||
- Support multiple authentication methods
|
||||
- Are free to use
|
||||
- Align with IndieWeb principles of building on existing infrastructure
|
||||
|
||||
### 4. Philosophy Alignment
|
||||
Our core philosophy states: "Every line of code must justify its existence. When in doubt, leave it out."
|
||||
|
||||
Self-hosted IndieAuth cannot justify its existence in a minimal content-focused CMS.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Dramatically reduced codebase complexity
|
||||
- No security burden for identity management
|
||||
- Faster development of content features
|
||||
- Clear project boundaries
|
||||
- User authentication "just works" via proven providers
|
||||
|
||||
### Negative
|
||||
- Dependency on external service (indielogin.com)
|
||||
- Cannot function without internet connection to auth provider
|
||||
- No control over authentication user experience
|
||||
|
||||
### Mitigations
|
||||
- Document clear setup instructions for using indielogin.com
|
||||
- Support multiple external providers for redundancy
|
||||
- Cache authentication tokens appropriately
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
### 1. Self-Hosted IndieAuth (REJECTED)
|
||||
**Why considered:** Full control over authentication
|
||||
**Why rejected:** Massive scope creep, violates project philosophy
|
||||
|
||||
### 2. No Authentication (REJECTED)
|
||||
**Why considered:** Ultimate simplicity
|
||||
**Why rejected:** Single-user system still needs access control
|
||||
|
||||
### 3. Basic Auth or Simple Password (REJECTED)
|
||||
**Why considered:** Very simple to implement
|
||||
**Why rejected:** Not IndieWeb compliant, poor user experience
|
||||
|
||||
### 4. Hybrid Approach (REJECTED)
|
||||
**Why considered:** Optional self-hosted with external fallback
|
||||
**Why rejected:** Maintains complexity we're trying to avoid
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
All authentication code should:
|
||||
1. Assume an external IndieAuth provider
|
||||
2. Never include hooks or abstractions for self-hosting
|
||||
3. Document indielogin.com as the recommended provider
|
||||
4. Include clear error messages when auth provider is unavailable
|
||||
|
||||
## References
|
||||
- Project Philosophy: "Every line of code must justify its existence"
|
||||
- IndieAuth Specification: https://indieauth.spec.indieweb.org/
|
||||
- indielogin.com: https://indielogin.com/
|
||||
|
||||
## Final Note
|
||||
This decision has been made after extensive consideration and multiple discussions. It is final.
|
||||
|
||||
**Do not propose self-hosted IndieAuth in future architectural discussions.**
|
||||
|
||||
The goal of StarPunk is **content**, not **identity**.
|
||||
110
docs/decisions/ADR-057-media-attachment-model.md
Normal file
110
docs/decisions/ADR-057-media-attachment-model.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# ADR-057: Media Attachment Model
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The v1.2.0 media upload feature needed a clear model for how media relates to notes. Initial design assumed inline markdown image insertion (like a blog editor), but user feedback clarified that notes are more like social media posts (tweets, Mastodon toots) where media is attached rather than inline.
|
||||
|
||||
Key insights from user:
|
||||
- "Notes are more like tweets, thread posts, mastodon posts etc. where the media is inserted is kind of irrelevant"
|
||||
- Media should appear at the TOP of notes when displayed
|
||||
- Text content should appear BELOW media
|
||||
- Multiple images per note should be supported
|
||||
|
||||
## Decision
|
||||
We will implement a social media-style attachment model for media:
|
||||
|
||||
1. **Database Design**: Use a junction table (`note_media`) to associate media files with notes, allowing:
|
||||
- Multiple media per note (max 4)
|
||||
- Explicit ordering via `display_order` column
|
||||
- Per-attachment metadata (captions)
|
||||
- Future reuse of media across notes
|
||||
|
||||
2. **Display Model**: Media attachments appear at the TOP of notes:
|
||||
- 1 image: Full width display
|
||||
- 2 images: Side-by-side layout
|
||||
- 3-4 images: Grid layout
|
||||
- Text content always appears below media
|
||||
|
||||
3. **Syndication Strategy**:
|
||||
- RSS: Embed media as HTML in description (universal support)
|
||||
- ATOM: Use both `<link rel="enclosure">` and HTML content
|
||||
- JSON Feed: Use native `attachments` array (cleanest)
|
||||
|
||||
4. **Microformats2**: Multiple `u-photo` properties for multi-photo posts
|
||||
|
||||
## Rationale
|
||||
**Why attachment model over inline markdown?**
|
||||
- Matches user mental model (social media posts)
|
||||
- Simplifies UI/UX (no cursor tracking needed)
|
||||
- Better syndication support (especially JSON Feed)
|
||||
- Cleaner Microformats2 markup
|
||||
- Consistent display across all contexts
|
||||
|
||||
**Why junction table over array column?**
|
||||
- Better query performance for feeds
|
||||
- Supports future media reuse
|
||||
- Per-attachment metadata
|
||||
- Explicit ordering control
|
||||
- Standard relational design
|
||||
|
||||
**Why limit to 4 images?**
|
||||
- Twitter limit is 4 images
|
||||
- Mastodon limit is 4 images
|
||||
- Prevents performance issues
|
||||
- Maintains clean grid layouts
|
||||
- Sufficient for microblogging use case
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Clean separation of media and text content
|
||||
- Familiar social media UX pattern
|
||||
- Excellent syndication feed support
|
||||
- Future-proof for media galleries
|
||||
- Supports accessibility via captions
|
||||
- Efficient database queries
|
||||
|
||||
### Negative
|
||||
- No inline images in markdown content
|
||||
- All media must appear at top
|
||||
- Cannot mix text and images
|
||||
- More complex database schema
|
||||
- Additional JOIN queries needed
|
||||
|
||||
### Neutral
|
||||
- Different from traditional blog CMSs
|
||||
- Requires grid layout CSS
|
||||
- Media upload is separate from text editing
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
### Alternative 1: Inline Markdown Images
|
||||
Store media URLs in markdown content as ``.
|
||||
- **Pros**: Traditional blog approach, flexible positioning
|
||||
- **Cons**: Poor syndication, complex editing UX, inconsistent display
|
||||
|
||||
### Alternative 2: JSON Array in Notes Table
|
||||
Store media IDs as JSON array column in notes table.
|
||||
- **Pros**: Simpler schema, fewer tables
|
||||
- **Cons**: Poor query performance, no per-media metadata, violates 1NF
|
||||
|
||||
### Alternative 3: Single Media Per Note
|
||||
Restrict to one image per note.
|
||||
- **Pros**: Simplest implementation
|
||||
- **Cons**: Too limiting, doesn't match social media patterns
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
1. Migration will create both `media` and `note_media` tables
|
||||
2. Feed generators must query media via JOIN
|
||||
3. Template must render media before content
|
||||
4. Upload UI shows thumbnails, not markdown insertion
|
||||
5. Consider lazy loading for performance
|
||||
|
||||
## References
|
||||
- [IndieWeb multi-photo posts](https://indieweb.org/multi-photo)
|
||||
- [Microformats2 u-photo property](https://microformats.org/wiki/h-entry#u-photo)
|
||||
- [JSON Feed attachments](https://jsonfeed.org/version/1.1#attachments)
|
||||
- [Twitter photo upload limits](https://help.twitter.com/en/using-twitter/tweeting-gifs-and-pictures)
|
||||
183
docs/decisions/ADR-058-image-optimization-strategy.md
Normal file
183
docs/decisions/ADR-058-image-optimization-strategy.md
Normal file
@@ -0,0 +1,183 @@
|
||||
# ADR-058: Image Optimization Strategy
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The v1.2.0 media upload feature requires decisions about image size limits, optimization, and validation. Based on user requirements:
|
||||
- 4 images maximum per note (confirmed)
|
||||
- No drag-and-drop reordering needed (display order is upload order)
|
||||
- Image optimization desired
|
||||
- Optional caption field for each image (accessibility)
|
||||
|
||||
Research was conducted on:
|
||||
- Web image best practices (2024)
|
||||
- IndieWeb implementation patterns
|
||||
- Python image processing libraries
|
||||
- Storage implications for single-user CMS
|
||||
|
||||
## Decision
|
||||
|
||||
### Image Limits
|
||||
We will enforce the following limits:
|
||||
|
||||
1. **Count**: Maximum 4 images per note
|
||||
2. **File Size**: Maximum 10MB per image
|
||||
3. **Dimensions**: Maximum 4096x4096 pixels
|
||||
4. **Formats**: JPEG, PNG, GIF, WebP only
|
||||
|
||||
### Optimization Strategy
|
||||
We will implement **automatic resizing on upload**:
|
||||
|
||||
1. **Resize Policy**:
|
||||
- Images larger than 2048 pixels (longest edge) will be resized
|
||||
- Aspect ratio will be preserved
|
||||
- Original quality will be maintained (no aggressive compression)
|
||||
- EXIF orientation will be corrected
|
||||
|
||||
2. **Rejection Policy**:
|
||||
- Files over 10MB will be rejected (before optimization)
|
||||
- Dimensions over 4096x4096 will be rejected
|
||||
- Invalid formats will be rejected
|
||||
- Corrupted files will be rejected
|
||||
|
||||
3. **Processing Library**: Use **Pillow** for image processing
|
||||
|
||||
### Database Schema Updates
|
||||
Add caption field to `note_media` table:
|
||||
```sql
|
||||
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, -- Optional caption 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)
|
||||
);
|
||||
```
|
||||
|
||||
## Rationale
|
||||
|
||||
### Why 10MB file size limit?
|
||||
- Generous for high-quality photos from modern phones
|
||||
- Prevents storage abuse on single-user instance
|
||||
- Reasonable upload time even on slower connections
|
||||
- Matches or exceeds most social platforms
|
||||
|
||||
### Why 4096x4096 max dimensions?
|
||||
- Covers 16-megapixel images (4000x4000)
|
||||
- Sufficient for 4K displays (3840x2160)
|
||||
- Prevents memory issues during processing
|
||||
- Larger than needed for web display
|
||||
|
||||
### Why resize to 2048px?
|
||||
- Optimal balance between quality and performance
|
||||
- Retina-ready (2x scaling on 1024px display)
|
||||
- Significant file size reduction
|
||||
- Matches common social media limits
|
||||
- Preserves quality for most use cases
|
||||
|
||||
### Why Pillow over alternatives?
|
||||
- De-facto standard for Python image processing
|
||||
- Fastest for basic resize operations
|
||||
- Minimal dependencies
|
||||
- Well-documented and stable
|
||||
- Sufficient for our needs (resize, format conversion, EXIF)
|
||||
|
||||
### Why automatic optimization?
|
||||
- Better user experience (no manual intervention)
|
||||
- Consistent output quality
|
||||
- Storage efficiency
|
||||
- Faster page loads
|
||||
- Users still get good quality
|
||||
|
||||
### Why no thumbnail generation?
|
||||
- Adds complexity for minimal benefit
|
||||
- Modern browsers handle image scaling well
|
||||
- Single-user CMS doesn't need CDN optimization
|
||||
- Can be added later if needed
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Automatic optimization improves performance
|
||||
- Generous limits support high-quality photography
|
||||
- Captions improve accessibility
|
||||
- Storage usage remains reasonable
|
||||
- Fast processing with Pillow
|
||||
|
||||
### Negative
|
||||
- Users cannot upload raw/unprocessed images
|
||||
- Some quality loss for images over 2048px
|
||||
- No manual control over optimization
|
||||
- Additional processing time on upload
|
||||
|
||||
### Neutral
|
||||
- Requires Pillow dependency
|
||||
- Images stored at single resolution
|
||||
- No progressive enhancement (thumbnails)
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
### Alternative 1: No Optimization
|
||||
Accept images as-is, no processing.
|
||||
- **Pros**: Simpler, preserves originals
|
||||
- **Cons**: Storage bloat, slow page loads, memory issues
|
||||
|
||||
### Alternative 2: Strict Limits (1MB, 1920x1080)
|
||||
Match typical web recommendations.
|
||||
- **Pros**: Optimal performance, minimal storage
|
||||
- **Cons**: Too restrictive for photography, poor UX
|
||||
|
||||
### Alternative 3: Generate Multiple Sizes
|
||||
Create thumbnail, medium, and full sizes.
|
||||
- **Pros**: Optimal delivery, responsive images
|
||||
- **Cons**: Complex implementation, 3x storage, overkill for single-user
|
||||
|
||||
### Alternative 4: Client-side Resizing
|
||||
Resize in browser before upload.
|
||||
- **Pros**: Reduces server load
|
||||
- **Cons**: Inconsistent quality, browser limitations, poor UX
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
1. **Validation Order**:
|
||||
- Check file size (reject if >10MB)
|
||||
- Check MIME type (accept only allowed formats)
|
||||
- Load with Pillow (validates file integrity)
|
||||
- Check dimensions (reject if >4096px)
|
||||
- Resize if needed (>2048px)
|
||||
- Save optimized version
|
||||
|
||||
2. **Error Messages**:
|
||||
- "File too large. Maximum size is 10MB"
|
||||
- "Invalid image format. Accepted: JPEG, PNG, GIF, WebP"
|
||||
- "Image dimensions too large. Maximum is 4096x4096"
|
||||
- "Image appears to be corrupted"
|
||||
|
||||
3. **Pillow Configuration**:
|
||||
```python
|
||||
# Preserve quality during resize
|
||||
image.thumbnail((2048, 2048), Image.Resampling.LANCZOS)
|
||||
|
||||
# Correct EXIF orientation
|
||||
ImageOps.exif_transpose(image)
|
||||
|
||||
# Save with original quality
|
||||
image.save(output, quality=95, optimize=True)
|
||||
```
|
||||
|
||||
4. **Caption Implementation**:
|
||||
- Add caption field to upload form
|
||||
- Store in `note_media.caption`
|
||||
- Use as alt text in HTML
|
||||
- Include in Microformats markup
|
||||
|
||||
## References
|
||||
- [MDN Web Performance: Images](https://developer.mozilla.org/en-US/docs/Web/Performance/images)
|
||||
- [Pillow Documentation](https://pillow.readthedocs.io/)
|
||||
- [Web.dev Image Optimization](https://web.dev/fast/#optimize-your-images)
|
||||
- [Twitter Image Specifications](https://developer.twitter.com/en/docs/twitter-api/v1/media/upload-media/uploading-media/media-best-practices)
|
||||
281
docs/decisions/ADR-059-full-feed-media-standardization.md
Normal file
281
docs/decisions/ADR-059-full-feed-media-standardization.md
Normal file
@@ -0,0 +1,281 @@
|
||||
# ADR-059: Full Feed Media Standardization (Option 3)
|
||||
|
||||
## Status
|
||||
Proposed (For v1.3.0 Backlog)
|
||||
|
||||
## Context
|
||||
StarPunk v1.2.0 introduced media attachments for notes (images). The initial implementation embeds media as HTML in feed description fields. Option 2 (implemented in v1.2.x) adds Media RSS extension elements and JSON Feed image fields for better feed reader compatibility.
|
||||
|
||||
This ADR documents Option 3: Full Standardization, which provides comprehensive media support across all syndication formats, including video, audio, and advanced features. This is planned for v1.3.0 or later.
|
||||
|
||||
## Decision
|
||||
Document the scope of "Full Standardization" for feed media support to be implemented in a future release. This option goes beyond Option 2's basic Media RSS support to include:
|
||||
|
||||
1. **Complete Media RSS Specification Support**
|
||||
2. **Podcast RSS Support (RSS 2.0 enclosures for audio)**
|
||||
3. **Video Support**
|
||||
4. **Multiple Image Sizes/Thumbnails**
|
||||
5. **Full JSON Feed 1.1 Media Compliance**
|
||||
|
||||
## Scope of Full Standardization
|
||||
|
||||
### 1. Complete Media RSS Implementation
|
||||
|
||||
**Research Required**: Full Media RSS specification at https://www.rssboard.org/media-rss
|
||||
|
||||
**Elements to Implement**:
|
||||
- `<media:content>` with full attribute support:
|
||||
- `url` (required) - Direct URL to media file
|
||||
- `fileSize` - Size in bytes
|
||||
- `type` - MIME type
|
||||
- `medium` - Type: "image", "audio", "video", "document", "executable"
|
||||
- `isDefault` - Boolean for default rendition
|
||||
- `expression` - "full", "sample", "nonstop"
|
||||
- `bitrate` - Kilobits per second
|
||||
- `framerate` - Frames per second (video)
|
||||
- `samplingrate` - Samples per second (audio)
|
||||
- `channels` - Audio channels
|
||||
- `duration` - Seconds
|
||||
- `height` / `width` - Dimensions in pixels
|
||||
- `lang` - RFC-3066 language code
|
||||
|
||||
- `<media:group>` - Container for multiple renditions of same content
|
||||
- `<media:thumbnail>` - Multiple sizes with url, width, height, time
|
||||
- `<media:title>` - Media title (type="plain" or "html")
|
||||
- `<media:description>` - Media description (type="plain" or "html")
|
||||
- `<media:keywords>` - Comma-separated keywords
|
||||
- `<media:category>` - Categorization with scheme attribute
|
||||
- `<media:credit>` - Credit attribution with role and scheme
|
||||
- `<media:copyright>` - Copyright information
|
||||
- `<media:rating>` - Content rating (scheme-based)
|
||||
- `<media:hash>` - MD5/SHA-1 hash for integrity
|
||||
- `<media:player>` - Embeddable player URL
|
||||
|
||||
**Effort Estimate**: 8-12 hours
|
||||
|
||||
### 2. Podcast RSS Support
|
||||
|
||||
**Research Required**:
|
||||
- Apple Podcast RSS specification
|
||||
- Google Podcast RSS requirements
|
||||
- Podcast Index namespace (podcast:)
|
||||
|
||||
**Elements to Implement**:
|
||||
- iTunes namespace (`xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"`):
|
||||
- `<itunes:summary>` - Episode summary
|
||||
- `<itunes:duration>` - Audio duration (HH:MM:SS)
|
||||
- `<itunes:image>` - Episode artwork
|
||||
- `<itunes:explicit>` - Content rating
|
||||
- `<itunes:episode>` - Episode number
|
||||
- `<itunes:season>` - Season number
|
||||
- `<itunes:episodeType>` - "full", "trailer", "bonus"
|
||||
- `<itunes:author>` - Author name
|
||||
- `<itunes:owner>` - Owner contact
|
||||
|
||||
- Standard RSS `<enclosure>` for audio:
|
||||
- `url` - Direct audio file URL
|
||||
- `length` - File size in bytes
|
||||
- `type` - MIME type (audio/mpeg, audio/mp4, etc.)
|
||||
|
||||
**Database Changes**:
|
||||
- Add `duration` column to `note_media` table
|
||||
- Add `media_type` enum (image, audio, video)
|
||||
- Consider `podcast_metadata` table for series-level data
|
||||
|
||||
**Effort Estimate**: 10-16 hours
|
||||
|
||||
### 3. Video Support
|
||||
|
||||
**Research Required**:
|
||||
- Video hosting considerations (storage, bandwidth)
|
||||
- Supported formats (mp4, webm, ogg)
|
||||
- Transcoding requirements
|
||||
- Poster image generation
|
||||
|
||||
**Implementation Scope**:
|
||||
- Accept video uploads via Micropub media endpoint
|
||||
- Generate poster thumbnails automatically
|
||||
- Include in Media RSS with proper video attributes:
|
||||
- `medium="video"`
|
||||
- `framerate`, `duration`, `bitrate`
|
||||
- Associated `<media:thumbnail>` for poster
|
||||
|
||||
- HTML5 `<video>` element in feed description
|
||||
- Consider video hosting limits (file size, duration)
|
||||
|
||||
**Database Changes**:
|
||||
- Video-specific metadata in `media` table
|
||||
- Poster image path
|
||||
- Transcoding status (if needed)
|
||||
|
||||
**Effort Estimate**: 16-24 hours (significant)
|
||||
|
||||
### 4. Multiple Image Sizes (Thumbnails)
|
||||
|
||||
**Research Required**:
|
||||
- Responsive image best practices
|
||||
- WebP generation
|
||||
- srcset/sizes patterns
|
||||
|
||||
**Implementation Scope**:
|
||||
- Generate multiple sizes on upload:
|
||||
- Thumbnail: 150x150 (square crop)
|
||||
- Small: 320px width
|
||||
- Medium: 640px width
|
||||
- Large: 1280px width
|
||||
- Original: preserved
|
||||
|
||||
- Store all sizes in `media_variants` table
|
||||
- Include in Media RSS:
|
||||
```xml
|
||||
<media:group>
|
||||
<media:content url="large.jpg" isDefault="true" width="1280" />
|
||||
<media:content url="medium.jpg" width="640" />
|
||||
<media:content url="small.jpg" width="320" />
|
||||
</media:group>
|
||||
<media:thumbnail url="thumb.jpg" width="150" height="150" />
|
||||
```
|
||||
|
||||
- JSON Feed: Use `image` for default, include variants in `_starpunk` extension
|
||||
|
||||
**Database Changes**:
|
||||
- `media_variants` table: media_id, variant_type, path, width, height, size_bytes
|
||||
- Add `has_variants` boolean to `media` table
|
||||
|
||||
**Effort Estimate**: 8-12 hours
|
||||
|
||||
### 5. Full JSON Feed 1.1 Media Compliance
|
||||
|
||||
**Research Required**: JSON Feed 1.1 specification for extensions
|
||||
|
||||
**Implementation Scope**:
|
||||
- Top-level `image` field (URL of first image, per spec)
|
||||
- Top-level `banner_image` if applicable
|
||||
- Item-level `image` field (main/featured image)
|
||||
- Item-level `banner_image` for posts with banners
|
||||
- Complete `attachments` array:
|
||||
```json
|
||||
{
|
||||
"url": "https://example.com/media/image.jpg",
|
||||
"mime_type": "image/jpeg",
|
||||
"title": "Image caption",
|
||||
"size_in_bytes": 245760,
|
||||
"duration_in_seconds": null
|
||||
}
|
||||
```
|
||||
- Audio attachments with `duration_in_seconds`
|
||||
- Video attachments (if supported)
|
||||
|
||||
**Effort Estimate**: 4-6 hours
|
||||
|
||||
### 6. ATOM Feed Media Extensions
|
||||
|
||||
**Research Required**:
|
||||
- ATOM Media extension namespace
|
||||
- `<link rel="enclosure">` best practices
|
||||
|
||||
**Implementation Scope**:
|
||||
- `<link rel="enclosure">` for each media item
|
||||
- `type` attribute with MIME type
|
||||
- `length` attribute with file size
|
||||
- `title` attribute with caption
|
||||
- Consider `<link rel="related">` for thumbnails
|
||||
|
||||
**Effort Estimate**: 3-5 hours
|
||||
|
||||
## Total Effort Estimate
|
||||
|
||||
| Feature | Minimum | Maximum |
|
||||
|---------|---------|---------|
|
||||
| Complete Media RSS | 8 hours | 12 hours |
|
||||
| Podcast RSS Support | 10 hours | 16 hours |
|
||||
| Video Support | 16 hours | 24 hours |
|
||||
| Multiple Image Sizes | 8 hours | 12 hours |
|
||||
| JSON Feed Compliance | 4 hours | 6 hours |
|
||||
| ATOM Extensions | 3 hours | 5 hours |
|
||||
| **Total** | **49 hours** | **75 hours** |
|
||||
|
||||
**Note**: Video support is the most complex feature and could be deferred to v1.4.0 "Media" release.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before implementing Full Standardization:
|
||||
|
||||
1. **Option 2 Complete**: Basic Media RSS and JSON Feed `image` field
|
||||
2. **Image Optimization**: ADR-058 image optimization strategy implemented
|
||||
3. **Media Storage Architecture**: Clear path for large file storage
|
||||
4. **Test Infrastructure**: Feed validation tests in place
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase A: Enhanced Image Support (v1.3.0)
|
||||
- Multiple image sizes/thumbnails
|
||||
- Full Media RSS for images
|
||||
- Enhanced JSON Feed attachments
|
||||
- **Effort**: 12-18 hours
|
||||
|
||||
### Phase B: Audio Support (v1.3.x or v1.4.0)
|
||||
- Podcast RSS implementation
|
||||
- Audio duration extraction
|
||||
- iTunes namespace
|
||||
- **Effort**: 10-16 hours
|
||||
|
||||
### Phase C: Video Support (v1.4.0 "Media")
|
||||
- Video upload handling
|
||||
- Poster generation
|
||||
- Video in feeds
|
||||
- **Effort**: 16-24 hours
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Best-in-class feed reader compatibility
|
||||
- Podcast distribution capability
|
||||
- Video content support
|
||||
- Professional media syndication
|
||||
- Future-proof architecture
|
||||
|
||||
### Negative
|
||||
- Significant implementation effort (50-75 hours total)
|
||||
- Increased storage requirements
|
||||
- More complex feed generation
|
||||
- Processing overhead for image variants
|
||||
- Larger codebase to maintain
|
||||
|
||||
### Neutral
|
||||
- Aligns with media-focused v1.4.0 roadmap
|
||||
- Phased implementation possible
|
||||
- Optional features can be configuration-gated
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
### Alternative 1: Minimal Enhancement (Option 2 Only)
|
||||
Just implement basic Media RSS and JSON Feed image field.
|
||||
- **Pros**: Low effort, immediate benefit
|
||||
- **Cons**: Misses podcast/video opportunity
|
||||
|
||||
### Alternative 2: Third-Party Media Service
|
||||
Use external service (Cloudinary, etc.) for media processing.
|
||||
- **Pros**: Offloads complexity
|
||||
- **Cons**: External dependency, cost, data ownership concerns
|
||||
|
||||
### Alternative 3: Plugin Architecture
|
||||
Make media support pluggable for advanced features.
|
||||
- **Pros**: Keeps core simple
|
||||
- **Cons**: Added architectural complexity
|
||||
|
||||
## References
|
||||
|
||||
- [Media RSS Specification](https://www.rssboard.org/media-rss)
|
||||
- [JSON Feed 1.1 Specification](https://jsonfeed.org/version/1.1)
|
||||
- [Apple Podcast RSS Requirements](https://podcasters.apple.com/support/823-podcast-requirements)
|
||||
- [Podcast Index Namespace](https://github.com/Podcastindex-org/podcast-namespace)
|
||||
- [RSS 2.0 Enclosure Specification](https://www.rssboard.org/rss-specification#ltenclosuregtSubelementOfLtitemgt)
|
||||
- [ADR-057: Media Attachment Model](/home/phil/Projects/starpunk/docs/decisions/ADR-057-media-attachment-model.md)
|
||||
- [ADR-058: Image Optimization Strategy](/home/phil/Projects/starpunk/docs/decisions/ADR-058-image-optimization-strategy.md)
|
||||
|
||||
## Decision
|
||||
This ADR documents the scope of Full Standardization (Option 3) for the project backlog. Implementation should be scheduled for v1.3.0 and v1.4.0 releases according to the phased approach outlined above.
|
||||
|
||||
**Immediate Action**: Implement Option 2 (ADR-060) for v1.2.x release.
|
||||
**Future Action**: Review and refine this scope when scheduling v1.3.0 work.
|
||||
111
docs/decisions/ADR-061-author-discovery.md
Normal file
111
docs/decisions/ADR-061-author-discovery.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# ADR-061: Author Profile Discovery from IndieAuth
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
StarPunk v1.2.0 requires Microformats2 compliance, including proper h-card author information in h-entries. The original design assumed author information would be configured via environment variables (AUTHOR_NAME, AUTHOR_PHOTO, etc.).
|
||||
|
||||
However, since StarPunk uses IndieAuth for authentication, and users authenticate with their domain/profile URL, we have an opportunity to discover author information directly from their IndieWeb profile rather than requiring manual configuration.
|
||||
|
||||
The user explicitly stated: "These should be retrieved from the logged in profile domain (rel me etc.)" when asked about author configuration.
|
||||
|
||||
## Decision
|
||||
Implement automatic author profile discovery from the IndieAuth 'me' URL:
|
||||
|
||||
1. When a user logs in via IndieAuth, fetch their profile page
|
||||
2. Parse h-card microformats and rel-me links from the profile
|
||||
3. Cache this information in a new `author_profile` database table
|
||||
4. Use discovered information in templates for Microformats2 markup
|
||||
5. Provide fallback behavior when discovery fails
|
||||
|
||||
## Rationale
|
||||
1. **IndieWeb Native**: Discovery from profile URLs is a core IndieWeb pattern
|
||||
2. **DRY Principle**: Author already maintains their profile; no need to duplicate
|
||||
3. **Dynamic Updates**: Profile changes are reflected on next login
|
||||
4. **Standards-Based**: Uses existing h-card and rel-me specifications
|
||||
5. **User Experience**: Zero configuration for author information
|
||||
6. **Consistency**: Author info always matches their IndieWeb identity
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- No manual configuration of author information required
|
||||
- Automatically stays in sync with user's profile
|
||||
- Supports full IndieWeb identity model
|
||||
- Works with any IndieAuth provider
|
||||
- Discoverable rel-me links for identity verification
|
||||
|
||||
### Negative
|
||||
- Requires network request during login (mitigated by caching)
|
||||
- Depends on proper markup on user's profile page
|
||||
- Additional database table required
|
||||
- More complex than static configuration
|
||||
- Parsing complexity for microformats
|
||||
|
||||
### Implementation Details
|
||||
|
||||
#### Database Schema
|
||||
```sql
|
||||
CREATE TABLE author_profile (
|
||||
id INTEGER PRIMARY KEY,
|
||||
me_url TEXT NOT NULL UNIQUE,
|
||||
name TEXT,
|
||||
photo TEXT,
|
||||
bio TEXT,
|
||||
rel_me_links TEXT, -- JSON array
|
||||
discovered_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
#### Discovery Flow
|
||||
1. User authenticates with IndieAuth
|
||||
2. On successful login, trigger discovery
|
||||
3. Fetch user's profile page (with timeout)
|
||||
4. Parse h-card for: name, photo, bio
|
||||
5. Parse rel-me links
|
||||
6. Store in database with timestamp
|
||||
7. Use cache for 7 days, refresh on login
|
||||
|
||||
#### Fallback Strategy
|
||||
- If discovery fails during login, use cached data if available
|
||||
- If no cache exists, use minimal defaults (domain as name)
|
||||
- Never block login due to discovery failure
|
||||
- Log failures for monitoring
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
### 1. Environment Variables (Original Design)
|
||||
Static configuration via .env file
|
||||
- ✅ Simple, no network requests
|
||||
- ❌ Requires manual configuration
|
||||
- ❌ Duplicates information already on profile
|
||||
- ❌ Can become out of sync
|
||||
|
||||
### 2. Hybrid Approach
|
||||
Environment variables with optional discovery
|
||||
- ✅ Flexibility for both approaches
|
||||
- ❌ More complex configuration
|
||||
- ❌ Unclear which takes precedence
|
||||
|
||||
### 3. Discovery Only, No Cache
|
||||
Fetch profile on every request
|
||||
- ✅ Always up to date
|
||||
- ❌ Performance impact
|
||||
- ❌ Reliability issues
|
||||
|
||||
### 4. Static Import Tool
|
||||
CLI command to import profile once
|
||||
- ✅ No runtime discovery needed
|
||||
- ❌ Manual process
|
||||
- ❌ Can become stale
|
||||
|
||||
## Implementation Priority
|
||||
High - Required for v1.2.0 Microformats2 compliance
|
||||
|
||||
## References
|
||||
- https://microformats.org/wiki/h-card
|
||||
- https://indieweb.org/rel-me
|
||||
- https://indieweb.org/discovery
|
||||
- W3C IndieAuth specification
|
||||
@@ -1,41 +0,0 @@
|
||||
# Deployment Documentation Index
|
||||
|
||||
This directory contains deployment guides, infrastructure setup instructions, and operations documentation for StarPunk CMS.
|
||||
|
||||
## Deployment Guides
|
||||
|
||||
- **[container-deployment.md](container-deployment.md)** - Container-based deployment guide (Docker, Podman)
|
||||
|
||||
## Deployment Options
|
||||
|
||||
### Container Deployment (Recommended)
|
||||
Container deployment provides:
|
||||
- Consistent environment across platforms
|
||||
- Easy updates and rollbacks
|
||||
- Resource isolation
|
||||
- Simplified dependency management
|
||||
|
||||
See: [container-deployment.md](container-deployment.md)
|
||||
|
||||
### Manual Deployment
|
||||
For manual deployment without containers:
|
||||
- Follow [../standards/development-setup.md](../standards/development-setup.md)
|
||||
- Configure systemd service
|
||||
- Set up reverse proxy (nginx/Caddy)
|
||||
- Configure SSL/TLS certificates
|
||||
|
||||
### Cloud Deployment
|
||||
StarPunk can be deployed to:
|
||||
- Any container platform (Kubernetes, Docker Swarm)
|
||||
- VPS providers (DigitalOcean, Linode, Vultr)
|
||||
- PaaS platforms supporting containers
|
||||
|
||||
## Related Documentation
|
||||
- **[../standards/development-setup.md](../standards/development-setup.md)** - Development environment setup
|
||||
- **[../architecture/](../architecture/)** - System architecture
|
||||
- **[README.md](../../README.md)** - Quick start guide
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2025-11-25
|
||||
**Maintained By**: Documentation Manager Agent
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user