Database Schema:
- Added meta_description TEXT field to pages table
- Added index on status_code for faster broken link queries
Backend Changes:
- Crawler now extracts meta descriptions from pages
- New API endpoint: broken-links (finds 404s and server errors)
- New API endpoint: seo-analysis (analyzes titles and meta descriptions)
SEO Analysis Features:
- Title length validation (optimal: 30-60 chars)
- Meta description length validation (optimal: 70-160 chars)
- Detection of missing titles/descriptions
- Duplicate content detection (titles and meta descriptions)
Frontend Changes:
- Added "Broken Links" tab showing pages with errors
- Added "SEO Analysis" tab with:
* Statistics overview
* Pages with SEO issues
* Duplicate content report
All quality checks pass:
- PHPStan Level 8: 0 errors
- PHPCS PSR-12: 0 warnings
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added "Recrawl" button in jobs table UI
- Implemented recrawl API endpoint that deletes all job data and restarts crawl
- Fixed PHPCS line length warnings in api.php and Crawler.php
All quality checks pass:
- PHPStan Level 8: 0 errors
- PHPCS PSR-12: 0 warnings
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added copyright headers to all PHP files in the application with proper author information (Martin Kiesewetter) and contact details.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Adjusted all references to match new config/ structure:
- docker/config/nginx/default.conf → config/nginx/default.conf
- docker/init.sql → config/docker/init.sql
- docker/start.sh → config/docker/start.sh
Updated files:
- docker-compose.yml: Updated volume mount paths
- README.md: Updated project structure documentation
New structure consolidates all configuration files under config/
for better organization and clarity.
Tested and verified all services running correctly.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The PHPStan fix inadvertently broke link extraction by using is_int()
on $pageId, which failed when lastInsertId() or fetchColumn() returned
a string instead of an int.
Changes:
- Convert $pageId to int explicitly after fetching
- Use $pageId > 0 instead of is_int($pageId) for validation
- Handle both 0 and '0' cases when fetching manually
This ensures link extraction works again while maintaining type safety.
Tests pass, PHPStan clean.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update Dockerfile to use inline CMD instead of external start.sh script to resolve execution issues with CRLF line endings
- Fix nginx fastcgi_pass configuration to use localhost:9000 for PHP-FPM communication
- Correct API endpoint paths in frontend from /src/api.php to /api.php to match nginx document root configuration
- Ensure Composer dependencies are properly installed with PHP 8.3 compatibility
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add PHPUnit 11.0 testing framework
- Create unit tests for Database and Crawler classes
- Create integration tests for Crawler
- Add phpunit.xml configuration
- Change UI background color to rose
- All 9 tests passing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>