ADR-005: Incremental static export with hash-based caching
Status: Accepted
Context
Static HTML export is used for deploying documentation to static hosting (Firebase, Netlify, GitHub Pages). Common approaches:
- Full rebuild: Regenerate all files on every export
- Timestamp-based: Compare file modification times
- Hash-based: Compare content hashes to detect changes
Full rebuild on every export is inefficient:
- Slow for large documentation sites
- Unnecessary regeneration of unchanged content
- Wasted computational resources (especially OG images)
- Longer deployment times
Timestamp-based comparison has issues:
- Doesn’t detect content changes if timestamp is modified
- Can miss changes from git operations
- Doesn’t handle settings changes properly
Decision
Implement hash-based incremental export. Only regenerate files when content or settings change.
Implementation
- Calculate SHA-256 hash for each source file
- Store hash in
_mdsvr/export-state.json - Compare current hash with stored hash
- Only regenerate files with changed hashes
- OG images use same hash-based caching
- Settings changes trigger full rebuild (settings hash stored separately)
- Export state includes: file hashes, OG image paths, settings hash
Hash Calculation
- Markdown/MDX files: Hash of file content
- Auto-index pages: Hash of directory contents (file names + sizes)
- Settings: Hash of
_mdsvr/settings.json - OG images: Hash of source file (or directory for auto-index)
Consequences
Positive
- Fast exports: Only changed files regenerated
- Efficient OG generation: OG images only regenerated when source changes
- Reliable: Hash-based detection is accurate (content-based, not time-based)
- Settings-aware: Settings changes trigger full rebuild automatically
- Orphan cleanup: Old files removed when source deleted
- Scalable: Handles large documentation sites efficiently
Negative
- State file dependency: Export state must be maintained
- Hash computation overhead: Must calculate hashes for all files
- State corruption risk: Corrupted state can cause issues
- Complexity: More complex than full rebuild
- Initial export: First export is slower (no state to compare)
Mitigations
- State file stored in
_mdsvr/(git-ignored, not served) - Hash computation is fast (SHA-256, streaming)
- State validation on load, fallback to full rebuild if corrupted
- Clear error messages for state issues
- Initial export is acceptable one-time cost