- Add Starlette GZipMiddleware for response compression (~60% smaller HTML)
- Extract 290 lines of inline CSS to /static/site.css (browser-cacheable)
- Bump HTML Cache-Control from 5min to 1hr
- Reduce Granian workers from 4 to 2 (matches shared-cpu-2x)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Octocat banner in the upper right links to the .md source file for each
page. Directory indexes link to index.md, regular pages to their .md,
and the homepage falls back to the repo root.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Flask blueprints aren't used in production — engine.py with
Responder is what Fly actually runs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Swagger UI Execute needs responses defined to display results.
Auto-detect search query params for /api/search routes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Schema at /api/schema now introspects api.router.routes for paths
and docstrings instead of maintaining a static dict. Skips catch-all
and internal routes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Schema served as JSON at /api/schema, docs rendered with Redoc at /api.
No more inline YAML — clean separation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Inline OpenAPI spec avoids catch-all route conflict. Elements UI
with sidebar layout, no external schema fetch needed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Avoids catch-all route intercepting /schema.yml.
Swagger UI at /api/docs, schema at /api/schema.yml.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
/api/icon/{article_path} didn't match paths with slashes like
essays/2026-03-25-foo. Changed to {article_path:path}.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Uses responder's built-in RateLimiter. Returns 429 with Retry-After
header when exceeded. Adds X-RateLimit-Limit and X-RateLimit-Remaining
headers to all responses.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
find_adjacent_posts result was never used in template (like
find_related_posts before it). Added _cached_render() to cache
parsed markdown in memory — content only changes on deploy so
there's no reason to re-parse on every request.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
find_related_posts was doing TF-IDF comparison against all 250+ essays
on every request (1 second each) but the result was never rendered in
the template. Essays now serve at 105 req/s instead of 19.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The catch-all route wasn't passing article_themes to the post template.
Now looks up detected themes from the themes cache for each essay.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Search:
- Build search index at startup instead of scanning 727 files per query
- Add /api/search/autocomplete for whole-site title matching
- Autocomplete now server-side, covers all content not just essays
- Remove client-side /api/blog preload from search page
AI section:
- Create 5 missing index.md files for navigational orphan directories
- Update "277 file" count to actual 352 across all references
- Tone down Lumina poetry index to match actual content quality
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Security:
- Add path traversal protection to serve_data_file and og_image routes
- Bound OG image cache to 256 entries to prevent memory growth
Performance:
- Pre-build legacy URL lookup tables at startup instead of rglob on every 404
- Extract _generate_pdf helper, eliminating duplicate PDF code
Templates:
- Add dark mode support to graph.html and error.html
Content:
- Remove third-person sidenotes from yoga-meditation.md, great-music.md,
and idea_amplification essay
- Fix sidenote formatting in yoga-meditation.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Recent writing now pulls 5 latest posts dynamically with icons
- Collapsed theme/beyond sections into flowing Threads paragraph
- Added .muted class for subtle text styling with dark mode support
- Removed redundant footer nav links
- Simplified subtitle styling
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Search endpoint now scans all markdown files in data/ directory
- Results show section labels (Essays, Software, Themes, etc.) instead
of hardcoded "Essay" type
- Updated placeholder text to reflect whole-site search
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Themes dropdown mirrors Browse structure with tree-item icons
- Populated from data/themes/ directory via /api/themes endpoint
- Search link added between Archive and Themes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Warms all caches (blog, sidenotes, outlines, quotes, connections,
terms, themes) in background thread on startup.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Handle .md and .pdf extensions inside catch-all since path:path
is greedy. Add WeasyPrint availability check for PDF button.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Initial Responder port — core content serving working
Homepage, markdown pages, directory listings, image galleries
all rendering. Flask template compatibility via RequestWrapper
and FakeConfig shims.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Complete Responder port — all routes working
Ported all routes from Flask blueprints: archive, search, OG images,
RSS, sitemap, robots.txt, API endpoints, directory browser.
All 25+ routes returning 200.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Update Dockerfile for Responder, warm caches on import
CMD now runs engine_responder:api via uvicorn.
Cache warming happens on module import for production.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Rename engine_responder.py to engine.py
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Update colophon for Responder
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix essay pages, OG images, and PDF export
- Fix find_related_posts and find_adjacent_posts call signatures
- Fix OG image route to use path:path for nested paths
- Add PDF export route with WeasyPrint
- All test plan items passing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace gunicorn/gevent with uvicorn for ASGI support
- Add asgiref to wrap Flask WSGI app for uvicorn compatibility
- Enable auto-reload in docker-compose for development
- Add current_path to all content render_template calls
- Simplify breadcrumb template to exclude current page
- Only show breadcrumbs for nested paths (> 1 segment)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Removed the engine_new.py file as part of restructuring.
- Implemented actual search functionality in api.py, allowing for searching through blog posts with relevance scoring and snippet extraction.
- Enhanced caching in cache.py with a clear_cache function and improved content cleaning for search indexing.
- Deleted outdated homepage-revised.html template and ensured search.html template displays search results with additional metadata such as date and matches found.
- Detect directory paths (ending with / or pointing to directories)
- Use generate_folder_icon() for directories instead of regular article icons
- Read index.md files for directory titles when available
- Fallback to directory name for folder icon generation
- Fixes AI personalities link and other directory links to show proper folder icons
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add themes directory to content cache for proper icon generation
- Remove colored dots from themes/index.md to enable icon display
- Fix JavaScript to handle links wrapped in strong tags
- Improve icon positioning with refined margins and alignment
- Prevent icons from loading on index/archive pages
- Fix navigation link to point to /themes instead of /themes/
- Optimize icon spacing and vertical alignment across devices
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix data URL display issue by using inline SVG instead of img src
- Add LRU cache to icon API for better performance
- Expand icon coverage to all internal links (not just essays)
- Add software, poetry, and talks directories to content cache
- Implement fallback logic to read files directly when not in blog cache
- Fix Requests icon to use full title "Requests: HTTP for Humans"
- Improve icon positioning with negative margins and vertical alignment
- Add graceful fallback icons for missing content
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Enhanced simple_extract_excerpt() function to filter markdown images
- Added support for linked images [](url)
- Improved line-by-line filtering to find meaningful content
- Reduced excerpt length to 150 characters for better display
- Removed prebuild cache system to simplify architecture
- Fixed markdown filtering in all excerpt generation functions
- Add cached markdown title extraction with @lru_cache(maxsize=1000)
- Replace expensive render_markdown_file() calls with fast regex title extraction
- Only read first 1000 chars instead of full file content for title extraction
- Essays directory and other large directories now load significantly faster
- First load: fast title extraction, subsequent loads: instant cache lookup
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add @lru_cache(maxsize=1000) to generate_unique_svg_icon() in svg_icon_generator.py
- Add @lru_cache(maxsize=500) to generate_folder_icon() in engine.py
- Import functools.lru_cache in both files
- Directory pages with many items (like /essays) now load much faster on repeat visits
- Icons generated once per unique title, then served from memory cache
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add reading progress bar for longer essays with smooth animation
- Implement search result snippets with highlighted query terms
- Tighten directory listing styles for better compactness
- Add back-to-parent navigation links in directory views
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>