- Add ADR-014: RSS Feed Implementation - Add ADR-015: Phase 5 Implementation Approach - Add Phase 5 design documents (RSS and container) - Add pre-implementation review - Add RSS and container validation reports - Add architectural approval for v0.6.0 release Architecture reviews confirm 98/100 (RSS) and 96/100 (container) scores. Phase 5 approved for production deployment. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
12 KiB
Phase 5 Quick Reference Guide
Phase: 5 - RSS Feed & Production Container Version: 0.6.0 Status: Implementation Ready
Pre-Implementation Setup
Version Numbering
Decision: Go directly from 0.5.1 → 0.6.0
- Phase 5 introduces significant new functionality (RSS feeds and container deployment)
- Skip intermediate versions (e.g., 0.5.2) - go straight to 0.6.0
- This follows semantic versioning for new feature additions
Git Workflow
Decision: Use feature branch feature/phase-5-rss-container
- Create and checkout feature branch:
git checkout -b feature/phase-5-rss-container - Implement all Phase 5 features on this branch
- Create PR to merge into main when complete
- This provides cleaner history and easier rollback if needed
Overview
Phase 5 implements:
- RSS 2.0 feed generation for syndicating published notes
- Production-ready container for deployment with HTTPS/IndieAuth testing
Implementation Checklist
Part 1: RSS Feed (Estimated: 3-4 hours)
Step 1: Create Feed Module
- Create
starpunk/feed.py - Implement
generate_feed()using feedgen - Implement
format_rfc822_date()for date formatting - Implement
get_note_title()for title extraction - Implement
clean_html_for_rss()for CDATA safety
Step 2: Add Feed Route
- Update
starpunk/routes/public.py - Add
@bp.route("/feed.xml")handler - Implement in-memory caching (5 minutes)
- Add ETag generation and support
- Set proper Content-Type and Cache-Control headers
Step 3: Update Templates
- Add RSS discovery link to
templates/base.html - Add RSS link to navigation in
templates/index.html
Step 4: Configuration
- Update
starpunk/config.pywith feed settings - Add FEED_MAX_ITEMS (default: 50)
- Add FEED_CACHE_SECONDS (default: 300)
- Update
.env.examplewith feed variables
Step 5: RSS Testing
- Create
tests/test_feed.pyfor unit tests - Create
tests/test_routes_feed.pyfor route tests - Test feed generation with various note counts
- Test caching behavior
- Test ETag validation
- Validate with W3C Feed Validator
Part 2: Production Container (Estimated: 3-4 hours)
Step 6: Create Container Files
- Create
Containerfilewith multi-stage build - Create
compose.yamlfor orchestration - Create
.containerignoreto exclude unnecessary files - Create
Caddyfile.examplefor reverse proxy - Create
nginx.conf.exampleas alternative
Step 7: Add Health Check
- Add
/healthendpoint tostarpunk/__init__.py - Check database connectivity
- Check filesystem access
- Return JSON with status and version
Step 8: Container Configuration
- Update
.env.examplewith container variables - Add VERSION=0.6.0
- Add WORKERS=4
- Add WORKER_TIMEOUT=30
- Document environment variables
Step 9: Container Testing
- Build container with Podman
- Build container with Docker
- Test container startup
- Test health endpoint
- Test data persistence
- Test with compose orchestration
Step 10: Production Deployment Testing
- Deploy container to public server
- Configure reverse proxy (Caddy or Nginx)
- Set up HTTPS with Let's Encrypt
- Test IndieAuth authentication flow
- Verify callback URLs work
- Test session creation and persistence
Part 3: Documentation (Estimated: 1-2 hours)
Step 11: Update Documentation
- Update CHANGELOG.md for v0.6.0
- Increment version in
starpunk/__init__.pyfrom 0.5.1 to 0.6.0 - Create deployment guide
- Document RSS feed usage
- Document container deployment
- Document IndieAuth testing with HTTPS
File Locations
New Files
starpunk/feed.py # RSS generation module
Containerfile # Container build definition
compose.yaml # Container orchestration
.containerignore # Container build exclusions
Caddyfile.example # Caddy reverse proxy config
nginx.conf.example # Nginx reverse proxy config
tests/test_feed.py # Feed unit tests
tests/test_routes_feed.py # Feed route tests
docs/designs/phase-5-rss-and-container.md # This phase design
docs/designs/phase-5-quick-reference.md # This guide
docs/decisions/ADR-014-rss-feed-implementation.md # RSS ADR
Modified Files
starpunk/routes/public.py # Add /feed.xml route
starpunk/__init__.py # Add /health endpoint
starpunk/config.py # Add feed configuration
templates/base.html # Add RSS discovery link
templates/index.html # Add RSS nav link
.env.example # Add feed/container vars
CHANGELOG.md # Document v0.6.0
Key Implementation Details
RSS Feed Module
File: starpunk/feed.py
Core Function:
from feedgen.feed import FeedGenerator
from starpunk.notes import list_notes
def generate_feed(site_url, site_name, site_description, notes, limit=50):
"""Generate RSS 2.0 XML feed"""
fg = FeedGenerator()
# Set channel metadata
fg.title(site_name)
fg.link(href=site_url, rel='alternate')
fg.description(site_description)
fg.language('en')
fg.link(href=f'{site_url}/feed.xml', rel='self')
# Add items
for note in notes[:limit]:
fe = fg.add_entry()
fe.title(get_note_title(note))
fe.link(href=f'{site_url}/note/{note.slug}')
fe.guid(f'{site_url}/note/{note.slug}', permalink=True)
fe.pubDate(note.created_at.replace(tzinfo=timezone.utc))
fe.description(note.html) # HTML content
return fg.rss_str(pretty=True).decode('utf-8')
Feed Route
File: starpunk/routes/public.py
Add to existing blueprint:
@bp.route("/feed.xml")
def feed():
"""RSS 2.0 feed endpoint with caching"""
# Check cache (implementation in design doc)
# Generate feed if cache expired
# Return XML with proper headers
pass
Health Check Endpoint
File: starpunk/__init__.py
Add before return app:
@app.route('/health')
def health_check():
"""Container health check"""
try:
# Check database and filesystem
return jsonify({'status': 'healthy', 'version': '0.6.0'}), 200
except Exception as e:
return jsonify({'status': 'unhealthy', 'error': str(e)}), 500
Containerfile
Key Sections:
# Multi-stage build for smaller image
FROM python:3.11-slim AS builder
# ... install dependencies in venv ...
FROM python:3.11-slim
# ... copy venv, run as non-root ...
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "app:app"]
Testing Commands
RSS Feed Testing
# Unit tests
uv run pytest tests/test_feed.py -v
# Route tests
uv run pytest tests/test_routes_feed.py -v
# Manual test
curl http://localhost:5000/feed.xml
# Validate XML
curl http://localhost:5000/feed.xml | xmllint --noout -
# W3C Validation (manual)
# Visit: https://validator.w3.org/feed/
# Enter: http://your-domain.com/feed.xml
Container Testing
# Build with Podman
podman build -t starpunk:0.6.0 -f Containerfile .
# Build with Docker
docker build -t starpunk:0.6.0 -f Containerfile .
# Run with Podman
mkdir -p container-data/notes
podman run -d --name starpunk \
-p 127.0.0.1:8000:8000 \
-v $(pwd)/container-data:/data:rw,Z \
--env-file .env \
starpunk:0.6.0
# Check health
curl http://localhost:8000/health
# Check feed
curl http://localhost:8000/feed.xml
# View logs
podman logs starpunk
# Test with compose
podman-compose up -d
podman-compose logs -f
Configuration Examples
.env for Container
# Required
SITE_URL=https://your-domain.com
SITE_NAME=My StarPunk Site
ADMIN_ME=https://your-identity.com
SESSION_SECRET=<random-secret>
# Feed configuration
FEED_MAX_ITEMS=50
FEED_CACHE_SECONDS=300
# Container configuration
VERSION=0.6.0
ENVIRONMENT=production
WORKERS=4
FLASK_ENV=production
FLASK_DEBUG=0
Caddy Reverse Proxy
your-domain.com {
reverse_proxy localhost:8000
log {
output file /var/log/caddy/starpunk.log
}
encode gzip zstd
}
Nginx Reverse Proxy
upstream starpunk {
server localhost:8000;
}
server {
listen 443 ssl http2;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
location / {
proxy_pass http://starpunk;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Common Issues & Solutions
Issue: Feed not updating
Solution: Check cache duration (5 minutes default), force refresh by restarting
Issue: Container won't start
Solution: Check logs (podman logs starpunk), verify .env file exists
Issue: IndieAuth callback fails
Solution: Verify SITE_URL matches public URL exactly (no trailing slash)
Issue: Data not persisting
Solution: Check volume mount is correct, verify permissions
Issue: RSS validation errors
Solution: Check date formatting (RFC-822), verify XML structure
Deployment Workflow
1. Local Testing
# Test feed locally
uv run flask --app app.py run --debug
curl http://localhost:5000/feed.xml
2. Container Testing
# Build and test container
podman build -t starpunk:0.6.0 .
podman run -d -p 8000:8000 --name starpunk-test starpunk:0.6.0
curl http://localhost:8000/health
3. Production Deployment
# On server
git clone <repo>
cd starpunk
cp .env.example .env
# Edit .env with production values
# Build and run
podman-compose up -d
# Configure reverse proxy (Caddy or Nginx)
# Set up HTTPS with certbot or Caddy auto-HTTPS
# Test IndieAuth
# Visit https://your-domain.com/admin/login
Success Criteria
Phase 5 complete when:
- RSS feed validates with W3C validator
- Feed appears correctly in RSS readers
- Container builds and runs successfully
- Health check endpoint responds
- Data persists across container restarts
- IndieAuth works with public HTTPS URL
- All tests pass (>90% coverage)
- Documentation complete
- Version incremented from 0.5.1 to 0.6.0 in
starpunk/__init__.py - Feature branch
feature/phase-5-rss-containermerged to main
Time Estimate
- RSS Feed Implementation: 3-4 hours
- Container Implementation: 3-4 hours
- Testing: 2-3 hours
- Documentation: 1-2 hours
Total: 9-13 hours
Next Steps After Completion
- Ensure all changes committed on feature branch:
git add . git commit -m "feat: implement RSS feed and production container (v0.6.0)" - Create PR to merge
feature/phase-5-rss-containerinto main - After merge, tag release on main:
git checkout main git pull git tag -a v0.6.0 -m "Release 0.6.0: RSS feed and production container" git push --tags - Create implementation report in
docs/reports/ - Begin Phase 6 planning (Micropub implementation)
Reference Documents
Phase: 5 Version: 0.6.0 Date: 2025-11-18 Status: Ready for Implementation