Development
This guide covers the development workflow, tests, demo mode, project structure, and deployment process for the Web App Template.
Development Commands
Server & Assets
# PHP server, queue listener, Pail logs, and Vite together
composer dev
Database
php artisan migrate
Custom Artisan Commands
# Creates view/create/update/delete permissions for the models listed in the command
php artisan app:add-permissions-to-new-modules
Testing & Code Quality
The PHP suite uses Pest 4 on an in-memory SQLite database (phpunit.xml). Tests live in tests/Feature and tests/Unit.
composer test
composer test clears the config cache and runs php artisan test. GitHub Actions run Pint, the frontend format and lint scripts, and the test suite on pushes and pull requests to develop and main.
Debugging
php artisan pail
Demo Mode
Demo mode turns an instance into a public, resettable live demo. It exists on the feature/demo-mode branch and is off unless DEMO_MODE=true.
What It Does
- Banner — A bar at the top of the panel (login page included) reads "Live demo — data resets every night" and links to the product page set in
DEMO_PRODUCT_URL. - Demo accounts —
demo:seedcreates two accounts: an admin (admin@demo.omega-studio-software.com, role Super Admin) and a user (user@demo.omega-studio-software.com, no role). Their shared password is defined inconfig/demo.php. - Sample data — Tops up to 12 non-demo users and 20 email log records using factories, and seeds roles and permissions if missing.
- Guarded credentials — Demo accounts cannot have their password or email changed, from the profile page or from the Users resource, and cannot be deleted. Other fields such as the name stay editable.
- Mail — The mail driver is forced to
log, so no real email is sent. - Uploads —
Demo::uploadMaxKilobytes()caps uploads at 2 MB when demo mode is on. - Live Stripe key warning —
demo:seedwarns whenSTRIPE_SECRETstarts withsk_live_. Demo instances must use test keys.
Commands
# Seeds demo data and the demo accounts (idempotent)
php artisan demo:seed
Both commands fail when DEMO_MODE is off. They also refuse to run unless APP_URL has a host starting with demo-, or DEMO_ALLOW_RESET=true is set. This protects real databases from an accidental wipe. When demo mode is on and the host allows it, demo:reset is scheduled daily at 03:00.
Configuration
- Name
DEMO_MODE- Type
- boolean
- Description
Enable demo mode. Default:
false
- Name
DEMO_ALLOW_RESET- Type
- boolean
- Description
Override the
demo-host check. Default:false
- Name
DEMO_PRODUCT_URL- Type
- string
- Description
Link target in the banner.
The behaviour is covered by Pest tests in tests/Feature/Demo: banner, credential guards, mail, reset, schedule, seed, and the support class.
Project Structure
Application Core
app/Models/— User, Role, Permission, Activity, Email, Sms.app/Policies/— AbstractPolicy and per-model policies.app/Providers/— AppServiceProvider, AuthServiceProvider, EmailMessageServiceProvider, andFilament/AppPanelProvider.app/Support/— Demo and DemoSchedule.app/helpers.php— Global helpers, autoloaded through Composer.
Filament Admin Panel
app/Filament/Resources/— Users, Roles, Activities, Emails, Sms.app/Filament/Pages/— HealthCheckResults, ViewLog.app/Filament/Auth/— EditProfile.app/Filament/Helpers/— Shared pagination and search-limit helpers.
Background & Console
app/Jobs/— SendSmsJob.app/Listeners/— FilamentEmailLogger.app/Console/Commands/— Permission, demo seed, and demo reset commands.routes/console.php— Backup and heartbeat schedule.
Database & Config
database/migrations/,database/seeders/,database/factories/.config/— Includespermission.php,activitylog.php,backup.php,health.php,cashier.php,sentry.php,filament-email.php, anddemo.php.routes/web.php— Single redirect from/to the panel.
Frontend, Tests & CI
resources/css,resources/js,resources/views— Tailwind 4 and Vite assets.tests/— Pest feature and unit tests..github/workflows/—lint.ymlandtests.yml.Envoy.blade.php— Deployment tasks.
Deployment
Set APP_ENV=production and APP_DEBUG=false, change or remove the seeded Super Admin account, and never enable DEMO_MODE on a production database.
Using Laravel Envoy
Set DEPLOY_USER, DEPLOY_HOST, DEPLOY_REPOSITORY, and DEPLOY_APP_DIR (and optionally DEPLOY_BRANCH, default main) in the environment or .env, then run:
envoy run deploy
The deploy story runs three tasks over SSH on the target server: pull-repository (git fetch and git pull), run-composer (composer install, composer dump-autoload, php artisan migrate --force, php artisan optimize:clear), and run-node (npm install and npm run build).
Post-Deployment Steps
- Queue worker — Because
QUEUE_CONNECTION=database, run a worker such asphp artisan queue:workunder a process manager.SendSmsJobis a queued job. - Scheduler — Add the Laravel scheduler to cron so backups and the health heartbeat run:
* * * * * cd /path-to-project && php artisan schedule:run >> /dev/null 2>&1
- Web server — Point the document root to
public/, and makestorage/andbootstrap/cache/writable. - Verify — Run
php artisan health:checkand open Health Check Results in the panel.