All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- SPA health indicator in navbar with real-time backend status polling (green/yellow/red dot)
- Service availability graph on home page showing 3-day uptime history from Prometheus
/api/v1/health-light/lightweight health endpoint for SPA polling/api/v1/availability/endpoint returning historical availability dataCORS_ALLOW_PRIVATE_NETWORKsetting for browser Private Network Access support (needed when SPA is Cloudflare-proxied but API resolves to private IP)- Canary cleanup service that removes failed canary images and reports impact in metrics
SPA_PORTenvironment variable for configurable SPA container port
- Health indicator permanently stuck on "Checking..." —
HealthProvidernow wraps entire body layout including navbar - CORS Private Network Access blocked when frontend is public (Cloudflare) but API resolves to private IP
- APScheduler running under
manage.pycommands (now gated to only run under Gunicorn) - SPA container health check failing in Alpine-based images (
127.0.0.1instead oflocalhost) CORS_ALLOWED_ORIGINSmissing from docker-compose environment
- Docker Compose passes
CORS_ALLOWED_ORIGINSto both SPA and Django containers - Live demo URL updated to
openlpr.computedsynergy.com
- Runtime backend API configuration via
BACKEND_API_URLenvironment variable (no rebuild needed) /api/configserver-side endpoint that returns the backend URL to the SPA client/healthroute on SPA that redirects to the Django backend health endpointAppInitializercomponent with spinner during config loading and error/retry state on failure
- SPA now resolves backend API URL at runtime instead of build time
spa-dev.pyusesBACKEND_API_URLinstead ofNEXT_PUBLIC_API_BASE_URL- Docker Compose SPA service passes
BACKEND_API_URLviaenvironment: getImageUrlandgetDownloadUrlare now async (runtime-resolved base URL)- Recent uploads on home page use shared
ImageCardcomponent - Health nav link uses
/health(SPA proxy) instead of direct backend URL - Removed
NEXT_PUBLIC_API_BASE_URLbuild arg from SPA Dockerfile (replaced by runtimeBACKEND_API_URL)
- Dead
NEXT_PUBLIC_MAX_UPLOAD_SIZEbuild arg from SPA Dockerfile
- SPA frontend env vars (
NEXT_PUBLIC_API_BASE_URL,NEXT_PUBLIC_UPLOAD_TIMEOUT) to.env.exampleand.env.llamacpp.example - SPA vars documented in AGENTS.md Environment Variables section
- Conventions section in AGENTS.md: env var documentation requirement, no
build:in compose files
- Docker image convention documented in AGENTS.md: all images built by CI, compose only references GHCR
- Dead
NEXT_PUBLIC_MAX_UPLOAD_SIZEbuild arg from SPA Dockerfile (max upload size fetched at runtime via/api/v1/config/)
- Add path filters to Django backend CI workflow to reduce CI noise on docs-only changes
- Grant
contents:writepermission to Docker publish workflows for SBOM release attachment
- Deleted
.roo/directory (Roo Code IDE config artifacts) - Deleted
nginx/directory (unused — Traefik is the active reverse proxy)
- Next.js 16 SPA frontend with React 19 and Tailwind CSS 4
- Storybook 10 with component stories for all UI components
- Dark mode support with system preference detection in SPA
- REST API endpoints:
/api/v1/images/,/api/v1/images/<id>/,/api/v1/download/<id>/<type>/,/api/v1/config/ - CORS support via
django-cors-headersfor SPA cross-origin requests - Configurable fixed-pixel padding for OCR crop regions
- Disclaimer banner in SPA with no-liability and data usage notice
- SPA pages: Home (upload), Images (history with search/filter/pagination), Image Detail (detection results, logs, raw API response)
- Breaking: Django backend is now API-only — all server-rendered templates removed
- Django upgraded from 4.2.30 to 5.2 LTS (supported through April 2028)
- Python minimum version raised from 3.8+ to 3.10+
- Frontend migrated from Bootstrap 5 / Django templates to Next.js SPA
- Removed all Django HTML templates, forms, template tags, and web views
- Removed legacy monolithic
views.pyandviews_refactored.py - Removed
nginx/directory (Traefik is the active reverse proxy) - File upload accepts WEBP in addition to JPEG and PNG
- README updated: tech stack badges, API endpoints, file structure, acknowledgments
- AGENTS.md updated to reflect API-only Django + Next.js SPA architecture
- Hydration mismatch in Next.js SPA disclaimer banner (extracted to
"use client"component) .gitignorelib/pattern fixed to/lib/(was matchingsingle-page-ui/src/lib/)
templates/directory (all HTML templates)lpr_app/forms.py(Django forms — only used by removed web views)lpr_app/templatetags/(template tag libraries)lpr_app/views/web_views.py(template-rendering views)lpr_app/views.py(legacy monolithic views)lpr_app/views_refactored.py(unused leftover)lpr_app/utils/response_helpers.pyWebResponseHelperclassnginx/directory (unused — Traefik is the active reverse proxy)
- Two-phase LPR pipeline with dynamic detection scaling for improved accuracy
- Comprehensive canary monitoring system with automated health checks
- Profile-based Docker Compose with merge design pattern (replaces individual compose files)
- Custom monitoring Docker images (Prometheus, Grafana, Blackbox Exporter) with embedded configs
- GitHub Actions workflow for building and publishing monitoring images
- NVIDIA CUDA GPU support for local LlamaCpp inference
- AMD Vulkan GPU support for local LlamaCpp inference
- Dark mode support with system theme detection and automatic switching
- Dynamic font scaling for OCR text visualization
- Favicon for the LPR application
- Star History chart in README
- Coolify deployment support with custom Docker images
- Configurable Traefik router rules via environment variables
- Configurable service ports to avoid conflicts
- CSRF trusted origins configuration for cross-origin requests
- Prometheus monitoring with LPR app dashboard
- Grafana dashboards for both LPR app and canary service
- Blackbox exporter for HTTP probing
- Simplified mobile pagination
- Liability disclaimer in application header
- Live demo link in README
- Split monolithic
views.pyinto modular view components (views/subpackage) - Django upgraded from 4.2.7 to 4.2.30
- Pillow upgraded from 10.1.0 to 12.2.0
- Gunicorn upgraded from 21.2.0 to 22.0.0
- Maximum image upload size reduced from 10MB to 250KB for optimized processing
- Homepage updated to show 9 processed images with annotations
- UI condensed for better screen utilization
- Image list page now shows annotated images with OCR text and plate count
- README reorganized with collapsible sections and compact navigation
- Fixed
django.logstatictypo in docker-entrypoint.sh causing chown error on startup - Fixed metrics directory permissions by adding
/app/metricsto Dockerfile - Fixed metrics state file (
metrics_state.json) creation and permissions in entrypoint - Fixed canary service HTTP 502 error and connectivity issues
- Fixed canary image cleanup functionality
- Fixed canary dashboard configuration and connectivity
- Fixed Prometheus and Blackbox Exporter duplicate binary names in CMD
- Fixed Grafana provisioning duplicate UID warnings
- Fixed metrics endpoint errors
- Fixed multi-platform Docker build issue
- Fixed Traefik Docker API compatibility issue
- Fixed database file ownership to prevent readonly database errors
- Fixed hardcoded API response data in LPR processing
- Fixed KeyError in
get_first_ocr_text()method - Fixed OCR results display in dark mode
- Fixed pagination URL encoding and error handling
- Fixed reverse pagination on image list page
- Fixed duplicate timestamps (removed redundant ones)
- Fixed display of correct max file size on upload page
- Eliminated duplicate Traefik configuration
- Fixed navigation links in README.md
- Individual Docker Compose files (
docker-compose-llamacpp-cpu.yml,docker-compose-llamacpp-amd-vulcan.yml) - Use profile-based approach with main
docker-compose.ymlinstead
- Django security patches included in upgrade to 4.2.30
- Pillow security patches included in upgrade to 12.2.0
- Non-root Docker user maintained
- Input validation and sanitization maintained
- CSRF protection with trusted origins support
- Initial release of Open LPR - License Plate Recognition System
- Django-based web application with license plate recognition capabilities
- RESTful API with comprehensive endpoints for image processing
- User-friendly web interface with drag-and-drop upload functionality
- Image processing pipeline with bounding box visualization
- Search and filter functionality for processed images
- Responsive design that works across all devices
- Docker deployment support with optimized multi-stage Dockerfile
- Automated CI/CD pipeline with GitHub Actions
- Multi-architecture support (linux/amd64, linux/arm64)
- Automatic publishing to GitHub Container Registry
- Software Bill of Materials (SBOM) generation for security scanning
- Local inference support with LlamaCpp server
- CPU and GPU deployment options for LlamaCpp
- Comprehensive documentation for local deployment
- Environment configuration templates
- Model download automation
- Visual showcase with screenshots in documentation
- API documentation with detailed endpoint descriptions
- Docker deployment guide with multiple deployment options
- LlamaCpp and ROCm resources collection
- Troubleshooting guides and best practices
- AI-powered detection using qwen3-vl-4b-instruct vision-language model
- Advanced OCR integration with confidence scores
- Bounding box visualization for detected plates and OCR text
- Permanent storage of uploaded and processed images
- Side-by-side comparison of original and processed images
- Health check endpoint for monitoring
- Download functionality for original and processed images
- Processing status tracking with AJAX endpoints
- Comprehensive error handling and logging
- Security best practices including non-root Docker user
- Environment-based configuration management
- Input validation and sanitization
- Comprehensive README with visual showcase
- Detailed API documentation
- Docker deployment guide
- LlamaCpp deployment guide
- LlamaCpp and ROCm resources collection
- Contributing guidelines
- Code style guidelines
- Django 4.x web framework
- Bootstrap 5 for responsive UI
- Gunicorn WSGI server for production
- SQLite database with migration support
- Docker containerization with multi-stage builds
- GitHub Actions for CI/CD
- Semantic versioning with automated tagging
- SBOM generation for security scanning
- Non-root Docker user for security
- Environment-based configuration
- Secure file upload handling
- Input validation and sanitization
- CSRF protection
- Security headers configuration
- Optimized Docker image for production use
- Gunicorn WSGI server with 3 workers
- Efficient image processing pipeline
- Configurable batch processing
- Multi-architecture Docker images
- Well-structured codebase following Django best practices
- Comprehensive documentation
- Environment configuration templates
- Management commands for project setup
- Clear code organization with separation of concerns
- Standard Docker deployment with cloud-based AI services
- LlamaCpp CPU deployment for local inference
- LlamaCpp GPU deployment with AMD Vulkan support
- Environment configuration templates
- Automated model download
- Health checks and monitoring
- Web endpoints for user interface
- REST API endpoints for programmatic access
- Health check endpoint
- File upload and processing endpoints
- Image download endpoints
- Search and filtering endpoints
- Large images (>10MB) may require increased memory allocation
- GPU acceleration is currently limited to AMD GPUs with Vulkan support
- Concurrent processing is limited by Django's development server (use Gunicorn in production)
- Django 4.x
- Bootstrap 5
- Gunicorn
- Docker
- LlamaCpp (for local inference)
- Qwen3-VL model
- MIT License
- Batch processing capabilities
- Real-time video stream processing
- Additional language support for license plates
- Performance optimizations
- Mobile application