# Syndication Architecture ## Overview StarPunk's syndication architecture provides multiple feed formats for content distribution, ensuring broad compatibility with feed readers and IndieWeb tools while maintaining simplicity. ## Current State (v1.1.0) ``` ┌─────────────┐ │ Database │ │ (Notes) │ └──────┬──────┘ │ ┌──────▼──────┐ │ feed.py │ │ (RSS 2.0) │ └──────┬──────┘ │ ┌──────▼──────┐ │ /feed.xml │ │ endpoint │ └─────────────┘ ``` ## Target Architecture (v1.1.2+) ``` ┌─────────────┐ │ Database │ │ (Notes) │ └──────┬──────┘ │ ┌──────▼──────────────────┐ │ Feed Generation Layer │ ├──────────┬───────────────┤ │ feed.py │ json_feed.py │ │ RSS/ATOM│ JSON │ └──────────┴───────────────┘ │ ┌──────▼──────────────────┐ │ Feed Endpoints │ ├─────────┬───────────────┤ │/feed.xml│ /feed.atom │ │ (RSS) │ (ATOM) │ ├─────────┼───────────────┤ │ /feed.json │ │ (JSON Feed) │ └─────────────────────────┘ ``` ## Design Principles ### 1. Format Independence Each syndication format operates independently: - No shared state between formats - Failures in one don't affect others - Can be enabled/disabled individually ### 2. Shared Data Access All formats read from the same data source: - Single query pattern for notes - Consistent ordering (newest first) - Same publication status filtering ### 3. Library Leverage Maximize use of existing libraries: - `feedgen` for RSS and ATOM - Native Python `json` for JSON Feed - No custom XML generation ## Component Design ### Feed Generation Module (`feed.py`) **Current Responsibility**: RSS 2.0 generation **Future Enhancement**: Add ATOM generation function ```python # Pseudocode structure def generate_rss_feed(notes, config) -> str def generate_atom_feed(notes, config) -> str # New ``` ### JSON Feed Module (`json_feed.py`) **New Component**: Dedicated JSON Feed generation ```python # Pseudocode structure def generate_json_feed(notes, config) -> str def format_json_item(note) -> dict ``` ### Route Handlers Simple pass-through to generation functions: ```python @app.route('/feed.xml') # Existing @app.route('/feed.atom') # New @app.route('/feed.json') # New ``` ## Data Flow 1. **Request**: Client requests feed at endpoint 2. **Query**: Fetch published notes from database 3. **Transform**: Convert notes to format-specific structure 4. **Serialize**: Generate final output (XML/JSON) 5. **Response**: Return with appropriate Content-Type ## Microformats2 Architecture ### Template Layer Enhancement Microformats2 operates at the HTML template layer: ``` ┌──────────────┐ │ Data Model │ │ (Notes) │ └──────┬───────┘ │ ┌──────▼───────┐ │ Templates │ │ + mf2 markup│ └──────┬───────┘ │ ┌──────▼───────┐ │ HTML Output │ │ (Semantic) │ └──────────────┘ ``` ### Markup Strategy - **Progressive Enhancement**: Add classes without changing structure - **CSS Independence**: Use mf2-specific classes, not styling classes - **Validation First**: Test with parsers during development ## Configuration Requirements ### New Configuration Variables ```ini # Author information for h-card AUTHOR_NAME = "Site Author" AUTHOR_URL = "https://example.com" AUTHOR_PHOTO = "/static/avatar.jpg" # Optional # Feed settings FEED_LIMIT = 50 FEED_FORMATS = "rss,atom,json" # Comma-separated ``` ## Performance Considerations ### Caching Strategy - Feed generation is read-heavy, write-light - Consider caching generated feeds (5-minute TTL) - Invalidate cache on note creation/update ### Resource Usage - RSS/ATOM: ~O(n) memory for n notes - JSON Feed: Similar memory profile - Microformats2: No additional server resources ## Security Considerations ### Content Sanitization - HTML in feeds must be properly escaped - CDATA wrapping for RSS/ATOM - JSON string encoding for JSON Feed - No script injection vectors ### Rate Limiting - Apply same limits as HTML endpoints - Consider aggressive caching for feeds - Monitor for feed polling abuse ## Testing Architecture ### Unit Tests ``` tests/ ├── test_feed.py # Enhanced for ATOM ├── test_json_feed.py # New test module └── test_microformats.py # Template parsing tests ``` ### Integration Tests - Validate against external validators - Test feed reader compatibility - Verify IndieWeb tool parsing ## Backwards Compatibility ### URL Structure - `/feed.xml` remains RSS 2.0 (no breaking change) - New endpoints are additive only - Auto-discovery links updated in templates ### Database - No schema changes required - All features use existing Note model - No migration needed ## Future Extensibility ### Potential Enhancements 1. Content negotiation on `/feed` 2. WebSub (PubSubHubbub) support 3. Custom feed filtering (by tag, date) 4. Feed pagination for large sites ### Format Support Matrix | Format | v1.1.0 | v1.1.2 | v1.2.0 | |--------|--------|--------|--------| | RSS 2.0 | ✅ | ✅ | ✅ | | ATOM | ❌ | ✅ | ✅ | | JSON Feed | ❌ | ✅ | ✅ | | Microformats2 | Partial | Partial | ✅ | ## Decision Rationale ### Why Multiple Formats? 1. **No Universal Standard**: Different ecosystems prefer different formats 2. **Low Maintenance**: Feed formats are stable, rarely change 3. **User Choice**: Let users pick their preferred format 4. **IndieWeb Philosophy**: Embrace plurality and interoperability ### Why This Architecture? 1. **Simplicity**: Each component has single responsibility 2. **Testability**: Isolated components are easier to test 3. **Maintainability**: Changes to one format don't affect others 4. **Performance**: Can optimize each format independently ## References - [RSS 2.0 Specification](https://www.rssboard.org/rss-specification) - [ATOM RFC 4287](https://tools.ietf.org/html/rfc4287) - [JSON Feed Specification](https://www.jsonfeed.org/) - [Microformats2](https://microformats.org/wiki/microformats2)