Configuration

Configuration

Externa’s runtime settings live in externa-core/config/*.php and are driven by .env (see Environment variables). This page covers the application defaults you should understand before going to production.

Related pages

Application (config/app.php)

Key / envDefaultNotes
APP_NAMELaravelDisplay name in mail/UI strings that read config('app.name'). Shared to Inertia as name.
APP_ENVproduction in config; .env.example uses localEnvironment label.
APP_DEBUGfalse in config; true in .env.exampleDisable in production.
APP_URLhttp://localhostCanonical URL for Artisan, mail links, public disk URLs, and Fortify passkeys RP. Must match how browsers reach the app. App works on HTTP; passkeys need HTTPS / localhost — Passkeys.
APP_KEY(required)Encryption key; generated by composer setup / key:generate.
APP_LOCALEenDefault Laravel locale.
APP_FALLBACK_LOCALEenFallback when a translation key is missing.
APP_FAKER_LOCALEen_USFaker locale for factories/seed demos.
timezoneUTCHard-coded in config (not env-driven).
MaintenanceAPP_MAINTENANCE_DRIVER=file, store default databaseStandard Laravel maintenance mode.
APP_NAME=Laravel
APP_ENV=local
APP_DEBUG=true
APP_URL=http://localhost
APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US

Three locale systems

  1. Admin UI localeconfig/i18n.php + user preference / cookie (APP_LOCALE is the default). Controls the shell language (en/it/de).
  2. Content localesproject settings (content_locales, default_content_locale, fallback_content_locales). Source of truth for translatable collection field values and labels. Seeded from config/collections.php until saved. UI: Project settings.
  3. Laravel APP_LOCALE / APP_FALLBACK_LOCALE — framework translator defaults; also used as a last-resort content resolve hint when nothing else matches.

Changing the admin UI language does not change which content locales are enabled.

Fortify (config/fortify.php)

Laravel Fortify provides session authentication for the Inertia SPA.

SettingValue
Guardweb
Password brokerusers
Username / email fieldemail
lowercase_usernamestrue
Home path/dashboard
Route prefix / domainempty / null
Middleware['web']
Viewsenabled (true) — Inertia auth pages under resources/js/pages/auth/*
Login throttlelimiter login (5/min)
Two-factor throttlelimiter two-factor (5/min)
Passkeys throttlelimiter passkeys

Enabled features

Features::registration(),
Features::resetPasswords(),
Features::emailVerification(),
Features::twoFactorAuthentication([
    'confirm' => true,
    'confirmPassword' => true,
    'window' => 1, // ±30s TOTP skew
]),
Features::passkeys([
    'confirmPassword' => true,
]),

Passkeys also use the passkeys config block (relying_party_id, allowed_origins, user_handle_secret, timeout) derived from APP_URL / APP_KEY. Operator guide: Passkeys.

To disable a feature, remove it from the features array in config/fortify.php and adjust the UI accordingly.

Authenticated product routes also require the verified middleware (see Routing overview).

Session, cache, and queue defaults

Externa’s .env.example uses database drivers for all three. That keeps local setup simple and matches the queue-backed file zip/duplicate and AI import jobs.

ConcernConfig fileEnvDefault
Session driverconfig/session.phpSESSION_DRIVERdatabase
Session lifetimeSESSION_LIFETIME120 minutes
Session encryptSESSION_ENCRYPTfalse
Cache storeconfig/cache.phpCACHE_STOREdatabase
Queue connectionconfig/queue.phpQUEUE_CONNECTIONdatabase
Default filesystem diskconfig/filesystems.phpFILESYSTEM_DISKlocal
SESSION_DRIVER=database
SESSION_LIFETIME=120
CACHE_STORE=database
QUEUE_CONNECTION=database
FILESYSTEM_DISK=local

Queue worker required

With QUEUE_CONNECTION=database (or Redis/etc.), you must run a worker. composer run dev starts php artisan queue:listen. Production needs a supervised worker plus the scheduler — see Operations and Deployment.

Optional Redis variables are present in .env.example if you switch drivers later (REDIS_*, MEMCACHED_HOST).

Super-admin seeding (config/super_admin.php)

Used only by CreateSuperAdminSeeder when you run php artisan db:seed (via DatabaseSeeder).

Config keyEnvDefault
first_nameINITIAL_SUPER_ADMIN_FIRST_NAMESuper
last_nameINITIAL_SUPER_ADMIN_LAST_NAMEAdmin
emailINITIAL_SUPER_ADMIN_EMAILsuperadmin@example.com
passwordINITIAL_SUPER_ADMIN_PASSWORDpassword

DatabaseSeeder order:

  1. PermissionSeederphp artisan permissions:sync
  2. RoleSeeder → built-in roles (super-admin, admin, reader, public) and permission assignments
  3. CreateSuperAdminSeeder → upserts the user by email and assigns the super-admin role

Production

Override INITIAL_SUPER_ADMIN_* before seeding shared or production environments. Never leave the default password outside local development.

Permission configuration overview

PieceLocation
Spatie package configconfig/permission.php
Canonical permission namesApp\Enums\PermissionEnum
Sync commandphp artisan permissions:sync (--prune removes DB rows no longer in the enum)
TS mirrorRegenerated at resources/js/enums/permission-enum.ts
Teamsdisabled (teams => false)
Permission cache24 hours, key spatie.permission.cache, store default
Effective resolutionApp\Services\Authorization\EffectivePermissionResolver
Middleware aliasespermission, can.manage.files in bootstrap/app.php

Key Spatie settings that matter for Externa:

  • Models: default Spatie Permission / Role
  • register_permission_check_methodtrue
  • display_permission_in_exception / display_role_in_exceptionfalse (avoid leaking names)
  • Wildcard permissions → disabled

Full authorization walkthrough: Effective permissions.

After deploying enum changes, run:

php artisan permissions:sync
# optional: php artisan permissions:sync --prune

Content locales (project settings)

Source of truth: Project settings → content_locales (ordered, min 1), default_content_locale, optional fallback_content_locales.

config/collections.php (locales / fallback_locales) is only the seed / fallback when settings have not been saved yet (defaults ['en', 'it']).

KeyRole
content_localesEnabled BCP-47 (or language-only) codes for item data translations and field labels
default_content_localeMust be ∈ content_locales; used when no ?locale= / Accept-Language match
fallback_content_localesOrdered chain when a translation is missing

Configure under Settings → Project → Content languages (searchable catalog + sortable list). Catalog codes/names/flags live in resources/data/content-locales-catalog.json (ContentLocaleCatalog). Disabling a locale does not delete existing translation rows in the DB (orphans stay until rewritten).

Shared to the frontend as Inertia props collectionLocales, collectionLocaleMeta, and defaultContentLocale (see Routing overview).

Admin UI language remains separate (config/i18n.php).

Mail and logging (brief)

AreaDefault in .env.example
MailerMAIL_MAILER=log (no SMTP required locally)
LogLOG_CHANNEL=stack, LOG_LEVEL=debug

Configure real SMTP (or another mailer) before relying on password-reset or verification email in non-local environments.

Checklist after changing config

  1. Update .env (and secrets store in production).
  2. php artisan config:clear or rebuild config:cache in production.
  3. If permissions/enums changed: permissions:sync (+ seed roles if needed).
  4. If content locales changed: smoke-test item forms and API ?locale= for each enabled locale.
  5. Confirm APP_URL matches the public host (affects storage URLs and redirects).
Previous
Project settings