Externa documentation

Build and operate dynamic collections, files, RBAC, and an in-app AI assistant on Laravel + Inertia.

getting-started.sh
.env
# From externa-core
composer setup
php artisan db:seed
composer run dev

Getting started

Introduction

Externa is an admin application for managing structured content, hierarchical files, and team access — with an optional in-app AI assistant and a headless Public CMS API (/api/v1) for websites and integrations.

Quick Start

Herd .env, seed roles, and the minimal commands to run locally.

Architecture

How Laravel, Inertia, routes, services, and the React shell fit together.

Permissions

Spatie RBAC with group-inherited effective permissions and built-in roles.

Public CMS API

Headless /api/v1 — public role, collection access matrix, API keys, and setup.

Related packages

externa-core (app) · externa-bruno (runnable API + GraphQL collection) · this docs site. Endpoint request/response examples are in Public CMS API and GraphQL; Bruno is the companion to execute them.

What Externa is

Externa ships as the externa-core repository: a Laravel 13 backend with an Inertia + React 19 frontend. Operators use the full admin UI; external clients use the Public CMS API when you grant collection access:

  • Dynamic collections — define collections and fields, then create and edit items with typed, often translatable data.
  • Public CMS API — headless /api/v1 for anonymous (public role) and Bearer API-key access, gated by a per-collection create/read/update/delete matrix (guide); GraphQL at /api/graphql.
  • Hierarchical files — a tree of folders and files with upload, versioning-related flows, duplicate, and async zip download.
  • Access controlSpatie Laravel Permission roles and permissions for the admin UI, extended with user groups so effective permissions can be inherited.
  • Project settings — content locales, sidebar modules, registration/password policy, transform presets, outbound webhooks, and branding (guide).
  • In-app AI — an assistant built on laravel/ai that exposes tools (collections, files, users, imports, activity logs, and more) while respecting the signed-in user’s effective permissions.
  • Outbound webhooks — HMAC-signed domain events to a project URL (guide).
  • Auditability — activity logging (Spatie Activitylog) and in-app notifications for long-running work.

The default local minimal stack uses SQLite, database drivers for session / cache, and Vite for the React bundle. The documented full stack (Herd Redis) uses QUEUE_CONNECTION=redis + Horizon, Reverb, and Pulse — see Minimal vs full stack. Production can use MySQL/Postgres; async features always need a queue worker.

What's new (ops)

  • Horizon, Reverb & Echo, Pulse & Health, Minimal vs full
  • Dashboard Overview | Health tabs — native Pulse/Horizon cards (no primary Open Pulse/Horizon CTAs)
  • WebSockets: private notifications + presence online + avatar connection dot (not AI SSE / activity flood / public API)
  • Herd Pro Reverb on :8080; local workers: horizon + pulse:work

Who it is for

AudienceWhy Externa fits
Product / content operatorsManage collections and items without writing migrations for every schema change.
Internal platform teamsShip a branded admin with users, groups, roles, and a file tree out of the box.
Developers extending externa-coreClear split of Actions, Services, Jobs, AI tools, and Inertia pages under resources/js.
Teams experimenting with AI opsPoint LOCAL_AI_* at LM Studio, vLLM, or another OpenAI-compatible gateway and keep tools permission-gated.

Note

Externa assumes you control the deployment and the AI gateway. It is designed for trusted operators (admin users), not as a public multi-tenant SaaS shell without further hardening.

Feature overview

Collections and items

Collections are first-class models (Collection, CollectionField, CollectionItem, CollectionItemValue). Field behavior is driven by enums and validation on the server; the React UI under resources/js/pages/collections mirrors those capabilities. Content locales for translatable field data live in project settings (seeded from config/collections.php, defaults en / it), separate from the admin UI locale in config/i18n.php.

HTTP surface lives in routes/collections.php and controllers under App\Http\Controllers\Collections.

Hierarchical file manager

Files form a tree (File, related upload/version models). Controllers under App\Http\Controllers\Admin\FileController expose browse/upload/move/duplicate/zip flows. Large duplicates and multi-file zips are handled asynchronously:

  • DuplicateFilesJob
  • PrepareFilesZipJob

Thresholds and zip retention come from config/files.php / FILES_* environment variables. Public disk URLs require php artisan storage:link.

Users, groups, roles, and permissions

Built-in roles (from App\Enums\RoleEnum):

RoleSeeded meaning
super-adminAll permissions
adminAll permissions
readerOnly can-show-* permissions
publicSystem role for anonymous /api/v1 (not assignable to users)

Permissions are seeded from PermissionEnum via PermissionSeeder and attached in RoleSeeder. Beyond direct Spatie assignments, user groups contribute permissions; App\Services\Authorization\EffectivePermissionResolver computes the union used by the UI and AI tool checks. Headless API grants live in Collection access on each role (Public CMS API).

Admin CRUD routes live in routes/admin.php (users, groups, roles, permissions, activity logs, files, API keys).

AI assistant

The default agent is App\Ai\Agents\AppAssistant, with tools under app/Ai/Tools such as:

  • Collection and item management / query / export
  • CSV and remote JSON import (plus job status)
  • Files, users, groups, roles
  • Activity log query and rollback of the last AI turn
  • PDF text extraction and AI sync sources

Default provider is local (AI_DEFAULT_PROVIDER=local), talking to an OpenAI-compatible gateway at LOCAL_AI_URL (default http://127.0.0.1:1234/v1). Chat UI and API routes are under routes/ai.php and resources/js/pages/ai.

Imports that can take time use ImportCollectionJob and the database queue.

Activity and notifications

Spatie Activitylog records notable changes (ACTIVITYLOG_*). The admin activity log UI and notification endpoints (unread count, mark read) help operators follow async work without watching the queue terminal.

Technology stack (externa-core)

LayerChoice
PHP8.3+ (repo pin often 8.4)
FrameworkLaravel 13
AuthLaravel Fortify
SPA bridgeInertia Laravel 2 + React 19
Typed routesLaravel Wayfinder (generated TS under resources/js)
Permissionsspatie/laravel-permission
Activityspatie/laravel-activitylog
AIlaravel/ai
Frontend buildVite, Tailwind CSS 4
TestsPest 4 (Feature / Unit / Browser)

Repository layout at a glance

You will spend most of your time in:

  • app/ — Actions, Ai, Enums, Http, Jobs, Models, Services, …
  • routes/web.php, api.php (/api/v1), admin.php, settings.php, collections.php, ai.php, console.php
  • resources/js/pages, components, hooks, lib, Wayfinder output
  • config/ — notably ai.php, collections.php, files.php, super_admin.php, permission.php, fortify.php

Full directory guidance is on the Project layout page. Environment keys are listed under Environment variables.

Next steps

  1. Install locally — preferably with Laravel Herd. Start with Quick Start; deeper detail in Installation.
  2. Sign in — default super admin from config/super_admin.php is superadmin@example.com / password (override with INITIAL_SUPER_ADMIN_* before seeding).
  3. Keep a queue worker running — minimal: composer run dev (queue:listen). Full Redis stack: composer run dev:full (Horizon + Reverb + Pulse). Zip, duplicate, and import features need a worker.
  4. Optional: AI — start a local OpenAI-compatible server, confirm LOCAL_AI_URL / LOCAL_AI_MODEL, then open the AI chat in the admin.
  5. Learn the model — read Architecture, Effective permissions, and AI assistant model before extending tools or policies.

Warning

Do not use the default seeded password outside local development. Set INITIAL_SUPER_ADMIN_EMAIL and INITIAL_SUPER_ADMIN_PASSWORD (and related name fields) before php artisan db:seed in shared or production environments.