Skip to content

Admin Workflows ​

This page covers the development workflows for the Laravel 13 admin app — running the local Docker stack, bootstrapping users, and working with ingestion.

Prerequisites ​

  • Docker (for the full local stack)
  • PHP 8.4+ and Composer (if running outside Docker)
  • pnpm (for JS assets)

Starting the local stack ​

The admin app uses compose.production.yaml as the base with a compose.local.yaml overlay for local-only services.

Full Docker stack ​

bash
cd apps/admin
docker compose -f compose.production.yaml -f compose.local.yaml up -d

Or from the monorepo root:

bash
pnpm run docker:admin:local:up

This starts the local admin stack, including FrankenPHP, PostgreSQL, Redis, Horizon, Traefik, and the supporting services defined by the compose files.

Local URL: https://localhost/admin

The local stack runs over HTTPS with a self-signed certificate. Accept the browser warning or add it to your trusted certs.

App process only ​

If PostgreSQL, Redis, and the rest of the stack are already running, you can start just the Laravel app and Vite watcher:

bash
cd apps/admin
composer install
composer dev

This path does not provision PostgreSQL, Redis, Horizon, or Traefik. In the checked-in local admin setup, this mode typically runs from http://localhost:8000.

Running migrations ​

Run migrations before seeding roles or bootstrapping users:

bash
# Inside the container
docker compose -f compose.production.yaml -f compose.local.yaml exec -T app php artisan migrate

# Locally (without Docker)
cd apps/admin && php artisan migrate

Bootstrapping the first admin user ​

The Filament panel does not seed a default user. After migrations complete, bootstrap your first admin from the running container:

bash
cd apps/admin
docker compose -f compose.production.yaml -f compose.local.yaml exec -T app php artisan db:seed --class=AdminRoleSeeder

docker compose -f compose.production.yaml -f compose.local.yaml exec -T app php artisan tinker --execute="\$user = \App\Models\User::updateOrCreate(['email' => '[email protected]'], ['name' => 'Kubuli Admin', 'password' => 'kubuli_admin_password']); \$user->syncRoles(['admin']);"

Sign in at https://localhost/admin/login with [email protected] / kubuli_admin_password.

To test curator-only flows:

bash
docker compose -f compose.production.yaml -f compose.local.yaml exec -T app php artisan tinker --execute="\$user = \App\Models\User::updateOrCreate(['email' => '[email protected]'], ['name' => 'Kubuli Curator', 'password' => 'kubuli_curator_password']); \$user->syncRoles(['curator']);"

Queue workers (Horizon) ​

The Docker stack includes a dedicated Horizon container. If you are running only the Laravel app process locally, start Horizon separately:

bash
php artisan horizon

Environment variables ​

bash
cp apps/admin/.env.example apps/admin/.env
php artisan key:generate

Key variables for local development:

bash
APP_URL=https://localhost
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=kubuli
DB_USERNAME=postgres
DB_PASSWORD=password
QUEUE_CONNECTION=redis
N8N_API_URL=http://n8n:25678
N8N_API_KEY=       # Set from your local n8n instance before provisioning workflows

The checked-in .env.example uses host-reachable values for local host-run commands. When you exec into the Dockerized app, the compose stack provides the container-side database and service networking automatically.

n8n in development ​

The local Docker stack exposes n8n at http://localhost:25678. If you are using the full Docker stack above, no extra compose profile is required.

→ Full ingestion reference: Ingestion & Review

Running admin tests ​

bash
# From apps/admin
php artisan test

# With coverage
php artisan test --coverage

Built with VitePress