Implements feed caching layer with LRU eviction, TTL expiration, and ETag support. Phase 3.1: Feed Caching (Complete) - LRU cache with configurable max_size (default: 50 feeds) - TTL-based expiration (default: 300 seconds = 5 minutes) - SHA-256 checksums for cache keys and ETags - Weak ETag generation (W/"checksum") - If-None-Match header support for 304 Not Modified responses - Cache invalidation (全体 or per-format) - Hit/miss/eviction statistics tracking - Content-based cache keys (changes when notes are modified) Implementation: - Created starpunk/feeds/cache.py with FeedCache class - Integrated caching into feed routes (RSS, ATOM, JSON Feed) - Added ETag headers to all feed responses - 304 Not Modified responses for conditional requests - Configuration: FEED_CACHE_ENABLED, FEED_CACHE_MAX_SIZE - Global cache instance with singleton pattern Architecture: - Two-level caching: 1. Note list cache (simple dict, existing) 2. Feed content cache (LRU with TTL, new) - Cache keys include format + notes checksum - Checksums based on note IDs + updated timestamps - Non-streaming generators used for cacheable content Testing: - 25 comprehensive cache tests (100% passing) - Tests for LRU eviction, TTL expiration, statistics - Tests for checksum generation and consistency - Tests for ETag generation and uniqueness - All 114 feed tests passing (no regressions) Quality Metrics: - 114/114 tests passing (100%) - Zero breaking changes - Full backward compatibility - Cache disabled mode supported (FEED_CACHE_ENABLED=false) Performance Benefits: - Database queries reduced (note list cached) - Feed generation reduced (content cached) - Bandwidth saved (304 responses) - Memory efficient (LRU eviction) Note: Phase 3 is partially complete. Still pending: - Feed statistics dashboard - OPML 2.0 export endpoint 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
StarPunk
A minimal, self-hosted IndieWeb CMS for publishing notes with RSS syndication.
Current Version: 1.1.0
Versioning
StarPunk follows Semantic Versioning 2.0.0:
- Version format:
MAJOR.MINOR.PATCH - Current:
1.1.0(stable release) - Check version:
python -c "from starpunk import __version__; print(__version__)" - See changes: CHANGELOG.md
- Versioning strategy: docs/standards/versioning-strategy.md
Philosophy
"Every line of code must justify its existence. When in doubt, leave it out."
StarPunk is designed for a single user who wants to:
- Publish short notes to their personal website
- Own their content (notes stored as portable markdown files)
- Syndicate via RSS
- Support IndieWeb standards (Micropub, IndieAuth)
- Run on minimal resources
Features
- 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
- 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
Requirements
- Python 3.11 or higher
- 500MB disk space
- Linux, macOS, or Windows with WSL2
Quick Start
# Clone repository
git clone https://github.com/YOUR_USERNAME/starpunk.git
cd starpunk
# Install uv (package manager)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create virtual environment
uv venv .venv --python 3.11
# Install dependencies
uv pip install -r requirements.txt
# Configure
cp .env.example .env
# Edit .env and set ADMIN_ME and SESSION_SECRET
# Initialize database
mkdir -p data/notes
.venv/bin/python -c "from starpunk.database import init_db; init_db()"
# Note: Database also auto-initializes on first run if not present
# Run development server
.venv/bin/flask --app app.py run --debug
# Visit http://localhost:5000
Configuration
All configuration is in the .env file. Required settings:
ADMIN_ME- Your IndieWeb identity URL (e.g., https://yoursite.com)SESSION_SECRET- Random secret key (generate withpython3 -c "import secrets; print(secrets.token_hex(32))")SITE_URL- Public URL of your site
See .env.example for all options.
Project Structure
starpunk/
├── app.py # Application entry point
├── starpunk/ # Application code
├── data/ # Your notes and database (gitignored)
│ ├── notes/ # Markdown files
│ └── starpunk.db # SQLite database
├── static/ # CSS and JavaScript
├── templates/ # HTML templates
└── tests/ # Test suite
Usage
Publishing Notes
Via Web Interface:
- Navigate to
/admin - Login with your IndieWeb identity
- Create notes in markdown
Via Micropub Client:
- Configure client with your site URL
- Authenticate via IndieAuth
- Publish from any Micropub-compatible app
Backing Up Your Data
Your notes are stored as plain markdown files in data/notes/. Back up this directory:
# Simple backup
tar -czf backup.tar.gz data/
# Or use rsync
rsync -av data/ /backup/starpunk/
Development
See docs/standards/development-setup.md for detailed setup.
# Install dev dependencies
uv pip install -r requirements-dev.txt
# Run tests
.venv/bin/pytest
# Format code
.venv/bin/black starpunk/ tests/
# Lint
.venv/bin/flake8 starpunk/ tests/
Architecture
StarPunk uses a hybrid storage approach:
- Notes content: Markdown files (portable, human-readable)
- Metadata: SQLite database (fast queries)
This gives you both portability AND performance.
See docs/architecture/ for complete documentation.
IndieWeb Compliance
StarPunk implements:
- Micropub - Publishing API
- IndieAuth - Authentication
- Microformats2 - Semantic HTML markup
- RSS 2.0 - Feed syndication
Deployment
Production Setup
# Install gunicorn
uv pip install gunicorn
# Run with gunicorn
.venv/bin/gunicorn -w 4 -b 127.0.0.1:8000 app:app
# Configure nginx/Caddy for HTTPS
# Set up systemd for process management
# Enable regular backups of data/ directory
See docs/standards/deployment-standards.md for details.
License
MIT License - see LICENSE file
Credits
Built with:
- Flask - Web framework
- python-markdown - Markdown processing
- feedgen - RSS generation
- httpx - HTTP client
- IndieLogin - Authentication service
Contributing
This is a personal project optimized for single-user use. If you want additional features, consider forking!
Support
- Documentation: docs/
- Issues: GitHub Issues
- IndieWeb: indieweb.org