Major changes:
- New ThemeManager with Twig templating and SCSS compilation
- Dynamic themes system (themes/default, themes/demo)
- LogManager with SQLite storage and syslog forwarding
- RequestLogger with static helper methods
- Admin UI overhaul (Bootstrap 5, dark mode)
- Admin config page with logging and theme settings
- Admin logs page with filters and search
- Removed legacy Mustache templates
- Removed test plugin and theme
- Composer dependencies: Twig, scssphp, CommonMark, MaxMind GeoIP
- Add GeoIP class with provider chain: local DB-IP Lite, MaxMind .mmdb, external API
- Add built-in pure-PHP MMDBReader so .mmdb works without Composer
- Add cli/geoip-update.php to download DB-IP Lite and build a compact binary index
- Add cli/generate-world-map.php to generate the world map SVG from Natural Earth TopoJSON
- Add Analytics class aggregating stats in admin/storage/stats.json with LOCK_EX
- Add admin statistics page with choropleth world map, country list, top pages,
daily chart, referrers and a period filter
- Add GeoIP and privacy settings with database update and stats reset buttons
- Add optional IP anonymization and configurable retention period
- Add country field to requests.log (parser accepts 7, 8 or 9 fields)
- Add country column to request log and KPI cards to the dashboard
- Ignore GeoIP binaries and stats.json in Git
- Update TODO.md, guides and version to 1.9.0
- Exclude config.json and admin.json in .gitignore so live settings/passwords are never overwritten by git
- Auto-generate config.json and admin.json with defaults if missing
- Add config.json.example and admin.json.example reference templates
- Add System Update page (/admin/update) in Admin Console to pull updates via Git with 1 click
- Log effective page name in index.php instead of literal 'auto'
- Add extra HAProxy/PFSense proxy headers to RequestLogger::getClientIp()
- Fix detectNewestPage() to search subdirectories recursively and handle language prefixes
- Fix getFileInfo() to preserve frontmatter created date or ctime instead of overwriting with mtime
- Automatically store created date in frontmatter when creating/editing files
- Add RequestLogger::getClientIp() with proxy and Cloudflare header support
- Replace domain column in request log with visitor/bot type badges (Human, AI, Search, Scraper)
- Update 'Activiteitenlog' to 'Activiteiten log' in UI and guide
- handleMediaList() now scans content/ recursively for all media files
- URLs use /-media/ prefix mapping directly to content/ (no special cases)
- index.php: added /-media/ route, kept /-assets/ for backward compat
- editor-toolbar.js: fixed editor.on('change') placement (was inside switchMode)
- content-edit.php and content-new.php: back-btn unsaved-changes detection
- Removed unused __editorCleanup global
- Remove sidebar and toggle functionality
- Add Bootstrap navbar with dropdown menus
- Move navigation to top between header and content
- Update menu rendering for Bootstrap dropdowns
- Clean up unused files (header.mustache, sidebar.mustache, sidebar.js)
- Add guide link with book icon in footer
- Simplify layout structure
- Remove duplicate code and fix syntax errors
- Add .gitignore for node_modules and other temp files
- Move content outside public web root for security
- Consolidate all code and assets in engine/ directory
- Download Bootstrap locally for offline functionality
- Update public/ to contain only entry point files
- Add router.php for PHP development server security
- Update README.md with new structure and setup instructions
- Block direct access to content files via URL
- Maintain clean separation between content and code
- Made all breadcrumb items clickable
- Added automatic directory listing generation for folders without index files
- Folders now show a list of their contents instead of 404
- Improved navigation UX by allowing browsing through folder structure
- Breadcrumb items for directories are now only clickable if an index file exists
- Prevents 404 errors when clicking on folder names in breadcrumb
- Non-clickable directory items are shown as active text
- Improves navigation UX and prevents broken links
- Copied index.php, config.php, and templates to public/
- e.noorlander branch now works correctly
- Personal blog content accessible again
- All branches now have proper public directory structure