InvoicePlane v2 is a modern, open-source invoicing and billing application built with Laravel, Filament, and Livewire. It features a modular architecture and multi-tenancy support. Peppol e-invoicing is a planned feature (see Peppol E-Invoicing below) but is not yet implemented on the develop branch.
- Features
- Requirements
- Quick Start
- Full Installation
- Configuration
- Development
- Module Structure
- Testing
- Peppol E-Invoicing
- Deployment
- Documentation
- Contributing
- Support
- License
- Invoice & Quote Management - Create, send, and track invoices and quotes
- Customer & Contact Handling - Manage customers and relationships
- Payment Tracking & Reminders - Track payments and send automated reminders
- Modular Architecture - Laravel + Filament with clean module separation
- Multi-Tenant Support - Via Filament Companies with company isolation
- Realtime UI - Built with Livewire for reactive interfaces
- Asynchronous Export System - Requires queue workers for background processing
- Comprehensive Testing - PHPUnit tests with high coverage
- Internationalization - Full translation support via Crowdin
- PHP 8.3 or higher
- Composer 2.x
- Node.js 20+ and Yarn
- Database MariaDB 10.11+ (recommended), MySQL 8.0+, or SQLite (dev only)
- Redis (recommended for queue/cache in production)
- Queue Worker (required for export functionality)
Get InvoicePlane v2 running in under 5 minutes:
# Clone the repository
git clone https://github.com/InvoicePlane/InvoicePlane-v2.git
cd InvoicePlane-v2
# Install dependencies
composer install
yarn install
# Setup environment
cp .env.example .env
php artisan key:generate
# Configure your database in .env, then:
php artisan migrate --seed
# Build frontend assets
yarn build
# Start development server
php artisan serve
# In a separate terminal, start queue worker (required for exports)
php artisan queue:workDefault Login:
- Admin Panel:
http://localhost:8000/admin - Company Panel:
http://localhost:8000/{search_code}(tenant-scoped root path, e.g.http://localhost:8000/ivplv2for the seeded default company) - Email:
admin@invoiceplane.com/ Password:password
Note: For production deployment, see the Deployment section.
git clone https://github.com/InvoicePlane/InvoicePlane-v2.git
cd InvoicePlane-v2# PHP dependencies
composer install
# JavaScript dependencies
yarn installcp .env.example .env
php artisan key:generateEdit .env and configure:
APP_NAME="InvoicePlane"
APP_URL=http://localhost:8000
DB_CONNECTION=mysql
DB_DATABASE=invoiceplane_v2
DB_USERNAME=your_username
DB_PASSWORD=your_password
# Queue Configuration (required for exports)
QUEUE_CONNECTION=redis # or 'database' or 'sync' for local dev
# Redis Configuration (recommended)
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
# Mail Configuration
MAIL_MAILER=smtp
MAIL_HOST=your-smtp-host
MAIL_PORT=587
MAIL_USERNAME=your-email
MAIL_PASSWORD=your-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@yourdomain.com# Run migrations and seed database
php artisan migrate --seedThis creates:
- Default admin user
- Sample data (invoices, customers, products)
- Default roles and permissions
# Development build
yarn dev
# Production build
yarn build# Development server
php artisan serve
# Queue worker (required for export functionality)
php artisan queue:workFor production setup with Nginx/Apache, see INSTALLATION.md.
Export functionality requires a queue worker to be running:
# Local development (sync queue)
QUEUE_CONNECTION=sync
# Production (Redis recommended)
QUEUE_CONNECTION=redisFor production, use a process manager like Supervisor:
[program:invoiceplane-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=8
redirect_stderr=true
stdout_logfile=/path/to/worker.log
stopwaitsecs=3600Peppol e-invoicing is not yet implemented on develop โ see the Peppol E-Invoicing section below for details and tracking issue.
Tests run inside the Docker workspace container โ the database is only reachable there:
# Run all tests
docker exec ivpldock-workspace-1 bash -c "cd /var/www/projects/ip2 && php artisan test"
# Run specific test file
docker exec ivpldock-workspace-1 bash -c "cd /var/www/projects/ip2 && php artisan test Modules/Invoices/Tests/Feature/InvoicesTest.php"
# Fall back to phpunit for full exception traces on failure
docker exec ivpldock-workspace-1 bash -c "cd /var/www/projects/ip2 && vendor/bin/phpunit Modules/Invoices/Tests/Feature/InvoicesTest.php"Or use the Makefile shorthand (see Makefile for available targets).
Without Docker: if you don't have the Docker workspace set up, you can run the suite locally against an in-memory SQLite database instead. Create/edit .env.testing:
DB_CONNECTION=sqlite
DB_DATABASE=:memory:Then run tests normally:
php artisan testSee RUNNING_TESTS.md for advanced testing.
# Format code with Laravel Pint
vendor/bin/pint
# Run static analysis
vendor/bin/phpstan analyse
# Run Rector for automated refactoring
vendor/bin/rector process --dry-run# Development build with hot reload
yarn dev
# Production build
yarn build
# Watch for changes
yarn dev --watch# Seed all seeders
php artisan db:seed
# Seed specific seeder
php artisan db:seed --class=InvoiceSeeder
# Fresh migration with seeding
php artisan migrate:fresh --seedSee SEEDING.md for custom seeding.
All business logic lives under Modules/ (via nwidart/laravel-modules), not in app/. The root app/ directory is intentionally thin โ it exists only for framework bootstrapping (app/Providers/AppServiceProvider.php); app/Http/Controllers/ is empty because routing is handled entirely by Filament panel providers.
There are 8 modules today: Core, Clients, Invoices, Quotes, Payments, Products, Projects, and Expenses. Every module follows the same internal layout:
Modules/<Name>/
Database/{Factories,Migrations,Seeders}/
Models/
Filament/{Admin,Company}/Resources/<Resource>/{Pages,Tables,Schemas}/
Services/
Enums/
Events/ Listeners/ Observers/
Traits/ Helpers/
Http/{Controllers,Requests,Middleware}/
Providers/
Tests/{Unit,Feature}/
Filament/Admin/...andFilament/Company/...hold the resources/pages registered on the two main Filament panels (see Panel Access below).Services/hold the business-logic layer โ services extendModules\Core\Services\BaseServiceand accept/return plain arrays and Eloquent models (there is no separate DTO layer).Tests/UnitandTests/Featureare discovered automatically by PHPUnit across all modules (seephpunit.xml); there's no centraltests/directory at the project root.
Before adding a new resource/model/service, check the Module Checklist to avoid duplicating something that already exists in another module.
InvoicePlane v2 registers three Filament panels:
| Panel | URL path | Tenanted | Typical users |
|---|---|---|---|
| Admin | /admin |
No | Super admins, admins, assistants |
| Company | /{search_code} (root) |
Yes โ scoped to Company by search_code |
Company admins and customers |
| User | /user |
No | Reserved for future use |
The company panel has no fixed /company path โ it is tenant-scoped and the tenant's search_code (lowercased) is the first URL segment, e.g. /ivplv2/dashboard for the seeded default company.
InvoicePlane v2 includes comprehensive PHPUnit tests:
Modules/
โโโ Invoices/Tests/
โ โโโ Unit/ # Unit tests
โ โโโ Feature/ # Feature tests
โ โโโ Integration/ # Integration tests
โโโ Quotes/Tests/
โโโ ...
All tests follow these conventions:
- Test methods start with
it_(e.g.,it_creates_invoice) - Use
#[Test]attribute - Follow Arrange-Act-Assert pattern
- Extend appropriate base test case
Example:
#[Test]
public function it_creates_invoice(): void
{
/* Arrange */
$customer = Customer::factory()->create();
/* Act */
$invoice = Invoice::factory()->create(['customer_id' => $customer->id]);
/* Assert */
$this->assertDatabaseHas('invoices', ['id' => $invoice->id]);
}Status: not yet implemented on develop. Modules/Invoices/Config/config.php defines an extensive configuration tree for a planned multi-format Peppol integration, but there is currently no consuming PHP code anywhere in the repository โ no PeppolService, no provider adapters, nothing wired into the invoice send flow. The real implementation work lives on the unmerged branch feature/126-implement-peppol, tracked by issue #126.
If you're looking to contribute Peppol support, start with that issue and branch rather than the config file alone โ the config schema exists, but the format handlers, access-point client, and UI wiring described in earlier drafts of this README were aspirational and have been removed here until they actually ship.
- Set
APP_ENV=production - Set
APP_DEBUG=false - Configure proper
APP_URL - Use strong
APP_KEY(never share) - Configure production database (MySQL/PostgreSQL)
- Set up Redis for cache and queue
- Configure queue workers with Supervisor
- Set up proper mail configuration
- Configure backups
- Set up SSL/TLS certificates
- Configure firewall rules
- Set up monitoring and logging
server {
listen 80;
server_name invoiceplane.example.com;
root /var/www/invoiceplane/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}<VirtualHost *:80>
ServerName invoiceplane.example.com
DocumentRoot /var/www/invoiceplane/public
<Directory /var/www/invoiceplane/public>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/invoiceplane_error.log
CustomLog ${APACHE_LOG_DIR}/invoiceplane_access.log combined
</VirtualHost>See DOCKER.md for containerized deployment.
- Quick Start - 5-minute setup guide
- Installation Guide - Complete setup instructions
- Docker Setup - Run with Docker containers
- Contributing Guide - How to contribute code
- Module Checklist - Avoid duplication when creating modules
- Running Tests - Testing guide
- Seeding Guide - Database seeding instructions
- Peppol Architecture - E-invoicing system details
- Maintenance Guide - Dependency management and security
- Theme Customization - Customize the UI
- Data Import - Import from other systems
- Translations - Internationalization
- Upgrade Guide - Upgrading between versions
- GitHub Actions Setup - CI/CD automation
- Security Policy - Reporting vulnerabilities
We welcome contributions from the community!
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes following our coding standards
- Write/update tests for your changes
- Run tests (
php artisan test) - Format code (
vendor/bin/pint) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow the Contributing Guide
- Review the Module Checklist before creating modules
- Follow PSR-12 coding standards
- Write meaningful commit messages (see git-commit-instructions.md)
- All tests must pass
- Maintain test coverage above 80%
- Update documentation for new features
- Be respectful and inclusive
- Welcome newcomers
- Focus on what's best for the community
- Show empathy towards other community members
Help translate InvoicePlane v2 into your language!
Join Translation Project on Crowdin โ
- ๐ฌ๐ง English (default)
- ๐ณ๐ฑ Dutch
- ๐ฉ๐ช German
- ๐ช๐ธ Spanish
- ๐ซ๐ท French
- ๐ฎ๐น Italian
- ๐ต๐น Portuguese
- And more...
See TRANSLATIONS.md for translation guidelines.
- Discord - Join our Discord server for real-time chat
- Forums - Community discussions
- Documentation - Official wiki
- Issue Tracker - Report bugs
When reporting bugs, please include:
- InvoicePlane version
- PHP version
- Laravel version
- Steps to reproduce
- Expected vs actual behavior
- Screenshots if applicable
Do not report security vulnerabilities through public GitHub issues.
Instead, follow our Security Policy for responsible disclosure.
InvoicePlane v2 is open-source software licensed under the MIT License.
See LICENSE file for details.
The InvoicePlane name and logo are protected trademarks of Kovah.de.
- Laravel - The PHP Framework for Web Artisans
- Filament - Beautiful admin panels
- Livewire - A magical front-end framework
- Tailwind CSS - Utility-first CSS framework
- Alpine.js - Lightweight JavaScript framework
- PHPUnit - Testing framework
- All our amazing contributors
- The Laravel community
- The Filament team
- Everyone who reports bugs and suggests features
- Translation contributors on Crowdin
Made with โค๏ธ by the InvoicePlane Community