- Add cleanOldArticles() and cleanOldSections() to remove stale directories
- Add ADSENSE_IN_ARTICLE_SLOT constant (was missing, causing ReferenceError)
- Add renderInArticleAdUnit() using slot 9095112841 for article pages
- Add renderArticleJsonLd() for NewsArticle structured data
- Pass jsonLd through renderShell() into <head>
- Fix ads.txt to use ADSENSE_CLIENT env var instead of hardcoded pub-id
- Add sharp dependency for image format conversion
- Generate WebP (quality 80) and AVIF (quality 70) variants for all raster images
- Render <picture> elements with srcset fallbacks (AVIF > WebP > original)
- SVG images remain as <img> without picture wrapper
- Update Dockerfile to install libvips for sharp, copy from public/ dir
- Add nginx cache rules for .webp and .avif files
- Add .gitignore for node_modules, public, dist