softcortex / magic-installer
Professional WordPress-like installer wizard for Laravel applications with Envato purchase code verification. Perfect for CodeCanyon products and commercial Laravel applications.
Requires
- php: ^8.2
- illuminate/contracts: ^11.0||^12.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^10.0.0||^9.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- spatie/laravel-ray: ^1.35
README
A professional WordPress-like installer wizard for Laravel 11+ applications with built-in Envato purchase code verification. Perfect for CodeCanyon products and commercial Laravel applications.
โจ Features
- ๐จ Beautiful UI - Clean, modern interface with TailwindCSS
- ๐ Envato Integration - Real Envato API v3 purchase code verification with dev mode
- โ Requirements Check - Automatic PHP version, extensions, and permissions validation
- ๐๏ธ Database Setup - Interactive database configuration with real-time connection testing
- ๐ Auto Migration - Automatic database migration during installation
- ๐ค Admin Creation - Secure admin account setup with smart role assignment (supports Spatie Permission)
- ๐ Security First - Stateless forms, secure session handling, password hashing
- ๐ One-Click Install - Complete installation in 7 steps
- ๐ Recovery Command - Unlock installer if needed
- ๐งช Property Testing - 39,000+ assertions with property-based tests
- ๐ง Step Validation - Prevents accessing steps out of order
- ๐พ File-First Storage - Works before database setup
๐ Requirements
- PHP 8.2 or higher
- Laravel 11 or 12
- Composer
- Writable
storage/appdirectory - MySQL/PostgreSQL/SQLite database
๐ฆ Installation
Install the package via Composer:
composer require softcortex/magic-installer
Note: The installer uses file-based storage (
storage/app/.installedandstorage/app/installer-settings.json) and does NOT require database setup before running. This means it works immediately aftercomposer requirewithout any database configuration.
Publish Assets (Recommended Before Installation)
For developers distributing this as part of their product:
- Publish the
.env.examplefile (includes pre-configured Envato settings):
php artisan vendor:publish --tag="installer-env"
- Edit the published
.env.examplein your project root and add your Envato credentials:
LICENSE_ENABLED=true LICENSE_DEV_MODE=false ENVATO_PERSONAL_TOKEN=your-token-here ENVATO_ITEM_ID=12345678
- The installer will use your customized
.env.exampleas the template when creating.envduring installation.
Why publish
.env.example? The installer prioritizes the project's.env.exampleover the package's version. This allows you to pre-configure Envato tokens and other settings for your end users.
Optional: Publish other assets
Publish the configuration file:
php artisan vendor:publish --tag="installer-config"
Optionally, publish the views for customization:
php artisan vendor:publish --tag="installer-views"
Optionally, publish the settings table migration (if you want to customize it before installation):
php artisan vendor:publish --tag="installer-migrations"
Note: Publishing the migration is optional. The installer automatically creates the
settingstable during Step 4 (Database configuration) using Laravel's Schema builder.
Or publish everything at once:
php artisan vendor:publish --provider="SoftCortex\Installer\InstallerServiceProvider"
โ๏ธ Configuration
Storage
The installer uses file-based storage to avoid database dependency issues:
- Installation Status:
storage/app/.installed - Settings:
storage/app/installer-settings.json
This approach ensures the installer works before database configuration, eliminating the chicken-and-egg problem.
1. Envato Personal Token Setup
To enable Envato purchase code verification:
- Visit https://build.envato.com/create-token/
- Create a token with these permissions:
- โ View and search Envato sites
- โ View the user's account username
- Add to your
.envfile:
LICENSE_ENABLED=true LICENSE_DEV_MODE=false ENVATO_PERSONAL_TOKEN=your-personal-token-here ENVATO_ITEM_ID=12345678 # Optional: Your CodeCanyon item ID
Development Mode
For development/testing without real Envato API calls:
LICENSE_ENABLED=true LICENSE_DEV_MODE=true
Then use the test purchase code: dev-test-code-12345678-1234
Skip License Step
To completely skip license verification:
LICENSE_ENABLED=false
2. Middleware Setup
The installer automatically registers:
- Custom
installermiddleware group (no EncryptCookies/StartSession) - Allows installation beforeAPP_KEYexists - Global
EnsureInstalledmiddleware - Redirects all routes to/installuntil installation completes
Key Architecture:
- Installer routes use custom middleware without session/cookie encryption
- All forms are stateless (no CSRF tokens, no
old()helpers) - Database drivers (session, cache, queue) switch to
databaseautomatically after installation
No manual middleware configuration required - works out of the box!
3. Configuration Options
Customize config/installer.php:
return [ 'product' => [ 'name' => env('APP_NAME', 'Laravel Application'), 'version' => '1.0.0', ], 'requirements' => [ 'php' => '8.2', 'extensions' => ['pdo', 'openssl', 'mbstring', 'tokenizer', 'xml', 'ctype', 'json', 'bcmath'], 'directories' => ['storage/framework', 'storage/logs', 'bootstrap/cache'], ], 'license' => [ 'enabled' => env('LICENSE_ENABLED', true), 'dev_mode' => env('LICENSE_DEV_MODE', false), 'envato_personal_token' => env('ENVATO_PERSONAL_TOKEN', ''), 'envato_item_id' => env('ENVATO_ITEM_ID', null), ], 'admin' => [ 'role' => 'admin', 'create_role_if_missing' => true, ], 'routes' => [ 'prefix' => 'install', 'middleware' => 'installer', // Custom middleware group 'redirect_after_install' => 'dashboard', ], ];
๐ Usage
Installation Wizard
- Navigate to
/installin your browser - Follow the 7-step wizard:
- Step 1: Welcome - Introduction and getting started
- Step 2: App Config - Set application name, URL, timezone, locale (creates
.env+APP_KEY) - Step 3: Requirements - PHP version, extensions, directory permissions check
- Step 4: Database - Database configuration, connection test, runs migrations
- Step 5: License - Purchase code verification (optional, can be disabled)
- Step 6: Admin - Create administrator account with role assignment
- Step 7: Finalize - Switch to database drivers, sync data, lock installer
Step Validation:
- Each step validates that previous steps are completed
- Attempting to access
/install/adminbefore database setup redirects to/install/database - Ensures proper installation sequence and prevents errors
Real-Time Validation
- Database Test Connection - Verify credentials before saving
- License Verification - Validate purchase code against Envato API before continuing
- Requirements Check - Live status of PHP version, extensions, and permissions
Purchase Code Format
Envato purchase codes must be in UUID format:
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
The installer:
- โ Validates against Envato API in real-time
- โ Stores only SHA-256 hash (never the actual code)
- โ Retrieves license info: item name, buyer, dates, support expiry
Unlock Installer
Re-run the installer if needed:
php artisan installer:unlock
Force unlock without confirmation:
php artisan installer:unlock --force
๐จ Customization
Views
Publish and modify views:
php artisan vendor:publish --tag="installer-views"
Views location: resources/views/vendor/installer/
Routes
Change the installer URL prefix in config/installer.php:
'routes' => [ 'prefix' => 'setup', // URL becomes /setup ],
Styling
The installer uses TailwindCSS. Customize by:
- Publishing views
- Modifying Tailwind classes
- Adding custom CSS to the layout
๐ Security
Best Practices
- โ Always use HTTPS in production
- โ Keep Envato Personal Token secure (never commit to Git)
- โ Use strong admin passwords
- โ
Run
installer:unlockonly when necessary
Data Storage
File-based storage:
- โ
Installation status in
storage/app/.installed - โ
Settings in
storage/app/installer-settings.json - โ SHA-256 hash of purchase code
- โ License metadata (item name, buyer, dates)
Never stored:
- โ Envato Personal Token
- โ Plain text purchase codes
๐๏ธ Architecture
Stateless Forms
The installer uses stateless forms before APP_KEY generation:
- No CSRF tokens on installer routes
- No
old()helpers or$errorsvariables - Controllers return views directly with error messages
- Form values preserved via explicit
$credentialsor$formDatavariables
File-First Storage
Installation state stored in files, not database:
storage/app/.installed- Installation lock filestorage/app/installer-settings.json- Step progress and settings- Database sync happens in Step 7 (Finalize) to
settingstable
Why? Avoids chicken-and-egg problem - installer must work before database exists!
Migration Timing
Migrations run in Step 4 (Database), not Step 7:
- Creates
settingstable withcategoryandchangeablecolumns - Creates
userstable before Step 6 (Admin creation) - Uses Laravel Schema builder for database-agnostic compatibility
Smart Admin Role Assignment
Automatically detects and assigns admin role:
- Checks for
roleorrolescolumn inuserstable - Detects Spatie Permission package (
HasRolestrait) - Creates role if missing (when
create_role_if_missing=true) - Assigns appropriate role to admin user
๐ Troubleshooting
| Issue | Solution |
|---|---|
| "MissingAppKeyException" | Normal on first access - installer creates .env and generates APP_KEY in Step 2 |
| "Envato Personal Token not configured" | Add ENVATO_PERSONAL_TOKEN to .env or set LICENSE_ENABLED=false |
| "Invalid purchase code format" | Use UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
| "License verification failed: 401" | Token expired - create new one at build.envato.com |
| "Purchase code not found" | Verify code is correct in Envato or enable dev mode |
| Database connection failed | Check credentials, server status, firewall, ensure database exists |
| "Table 'users' doesn't exist" | Migrations run in Step 4 - ensure you complete database step before admin creation |
| Permission errors | Ensure storage/app directory is writable: chmod -R 775 storage |
| Form inputs lost after error | Fixed in v1.2.0+ - forms now preserve values on validation failure |
| Can't access step out of order | By design - each step validates previous steps are completed |
| Step validation not working | Clear browser cache, ensure you're not bypassing middleware |
๐งช Testing
Run the test suite:
composer test
Run specific test types:
vendor/bin/pest --group=property # Property-based tests vendor/bin/pest --group=unit # Unit tests
๐ API Reference
LicenseService
use SoftCortex\Installer\Services\LicenseService; $service = app(LicenseService::class); $result = $service->verify('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'); if ($result->isValid()) { echo $result->itemName; echo $result->buyerName; echo $result->licenseType; // 'regular' or 'extended' }
InstallerService
use SoftCortex\Installer\Services\InstallerService; $installer = app(InstallerService::class); if ($installer->isInstalled()) { // App is installed } $installer->setSetting('key', 'value'); $value = $installer->getSetting('key', 'default');
๐ Changelog
See CHANGELOG.md for recent changes.
๐ค Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
๐ Security
Report security vulnerabilities via our security policy.
๐ฅ Credits
๐ License
MIT License. See LICENSE.md for details.