Skip to content

Initial Customization

Customize these settings before launching your application.


Super Administrators have full access to the application and bypass all authorization checks. These accounts are typically reserved for IT staff or core development team members.

This is a step for deployed environments. Locally you don’t need it: the seeded NUIT Administrator demo user is a Super Administrator, and the sign-in page offers it under Sign In As.

Add NetIDs to each deployed environment’s configuration, or to .env.example if they will be the same across environments:

.env
# Comma-separated list of NetIDs
SUPER_ADMIN_NETIDS=abc123,xyz789,def456

The StakeholderSeeder runs on deploy (the reference vapor.yml in Deployment runs php artisan db:seed --class=StakeholderSeeder) and:

  1. Looks up each NetID in the Northwestern Directory
  2. Creates or refreshes user accounts with their directory information (name, email, department, etc.)
  3. Assigns the Super Administrator role (full application access) to users who don’t already have it
  4. Safe to run multiple times - existing users are updated from the directory, not duplicated

Set SUPER_ADMIN_NETIDS and deploy; the seeder runs as part of the deploy. To add administrators between deploys, run it in that environment:

Terminal window
php artisan db:seed --class=StakeholderSeeder

Edit config/local-auth.php or set environment variables:

.env
# Enable/disable local authentication
LOCAL_AUTH_ENABLED=true
# Rate limit for login code requests per email (per hour)
LOCAL_AUTH_RATE_LIMIT_PER_HOUR=10
# Rate limit for login code requests per IP (per hour)
# Prevents a single IP from exhausting multiple accounts' per-email rate limits
LOCAL_AUTH_RATE_LIMIT_PER_IP_PER_HOUR=20

To change where users land after signing in, see Where Users Land After Signing In.

Enabled

When to enable:

  • Clients or partners without NetIDs
  • Testing accounts for non-Northwestern users

Disabled

When to disable:

  • Northwestern-only applications
  • No external user requirements

Edit config/local-auth.php to tune the OTP length, expiration, and lockout behavior.

'code' => [
'digits' => 6,
'expires_in_minutes' => 10,
'max_attempts' => 8,
'lock_minutes' => 15,
'resend_cooldown_seconds' => 30,
],
  1. Admin creates a local user account in the administration panel (/administration): Users → Add User → Add Local User
  2. Admin can trigger an immediate verification code, or the user can request one themselves
  3. User receives an email with a verification code valid for a limited time
  4. User enters the code and is authenticated (no password needed)
  5. Code expires and becomes invalid after use

.env
# Master on/off switch for all API functionality
API_ENABLED=true
.env
# Enable API request logging
API_REQUEST_LOGGING_ENABLED=true
# Slow request threshold for monitoring (milliseconds)
API_REQUEST_LOGGING_SLOW_THRESHOLD_MS=500

How long request logs are kept is set by API_REQUEST_LOG_RETENTION_DAYS; see Data Retention.

.env
# Enable probabilistic sampling
API_REQUEST_LOGGING_SAMPLING_ENABLED=true
# Sample rate (0.0 to 1.0) - 0.1 = 10% of successful requests
API_REQUEST_LOGGING_SAMPLE_RATE=0.1

The NetID Update webhook receives notifications when Northwestern users are deactivated, deprovisioned, or placed on security hold. This enables automatic role removal, or additional business logic, when users leave Northwestern.

If you have an EventHub subscription to the etidentity.ldap.netid.term topic:

  1. Open routes/api.php

  2. Uncomment the NetID Update webhook route:

    routes/api.php
    Route::middleware(['eventhub_hmac'])->prefix('eventhub')->group(function () {
    // Route::post('netid-update', App\Domains\User\Http\Controllers\Webhooks\NetIdUpdateController::class)->eventHubWebhook('etidentity.ldap.netid.term')->name('netid-update');
    Route::post('netid-update', App\Domains\User\Http\Controllers\Webhooks\NetIdUpdateController::class)->eventHubWebhook('etidentity.ldap.netid.term')->name('netid-update');
    });

If you don’t have an EventHub subscription, leave this route commented out.


The Environment Lockdown feature restricts application access to users who have been explicitly assigned application-specific roles. Users with only the default Northwestern User role (automatically assigned during SSO login), or no roles, are redirected to a lockdown page explaining they need to be granted access by an administrator.

This is most useful in non-production environments to prevent unauthorized users from accessing the application if they discover the URL.

By default, lockdown is enabled for non-production environments and disabled for production, local development, CI, and tests:

config/platform.php
'lockdown' => [
'enabled' => env('ENVIRONMENT_LOCKDOWN_ENABLED', match (env('APP_ENV')) {
'production', 'local', 'testing', 'ci' => false,
default => true,
}),
],

To disable lockdown for a specific environment, add this to your .env file:

.env
ENVIRONMENT_LOCKDOWN_ENABLED=false

Set PRODUCTION_URL in .env.example so every environment inherits it:

.env.example
PRODUCTION_URL=https://your-app.northwestern.edu

Changing the default in config/platform.php has no effect while .env.example ships PRODUCTION_URL= empty, because an empty environment value overrides the config default.

The following routes are always accessible, regardless of lockdown status:

  • Sign-in and sign-out: the sign-in page, verification codes, Entra ID’s sign-in and sign-out, WebSSO’s sign-out, and logout
  • Impersonation routes (take/leave impersonation)
  • The lockdown page itself

These exemptions ensure people can sign in and out and administrators can manage impersonation. The OAuth consent screen is not exempt: a locked-out person can’t connect an application. If you create additional routes that should be exempt, add them to the exempted_routes array in config/platform.php.


The university’s Web Style Guide requires every page to show the responsible unit’s address, phone, fax (if any) and email. The footer on every page and every email reads them from config/northwestern-filament-theme.php. Until you set them, they show Information Technology’s details.

.env
NU_UNIT_NAME="Your Office"
NU_UNIT_ADDRESS="633 Clark Street"
NU_UNIT_CITY="Evanston, IL 60208"
NU_UNIT_PHONE="847-555-0100"
NU_UNIT_FAX=
NU_UNIT_EMAIL="your-office@northwestern.edu"
# Optional: a unit lockup (URL or public path) instead of the Northwestern wordmark
NU_LOCKUP=

Quick links and the “Connect” social accounts are set in the same config file, under footer.links and footer.social.

The scheduler runs model:prune daily, which deletes records older than their retention period. Every period is set in days under retention in config/platform.php, and null keeps records forever.

RecordsSettingDefault
Audit logsAUDIT_RETENTION_DAYSnull (kept)
Sign-in recordsLOGIN_RECORD_RETENTION_DAYS365
Impersonation logsIMPERSONATION_LOG_RETENTION_DAYSnull (kept)
Login code challengesLOGIN_CHALLENGE_RETENTION_DAYS30
API request logsAPI_REQUEST_LOG_RETENTION_DAYS90
Table exports and their files, from when they finishEXPORT_RETENTION_DAYS7

A few records are cleaned up on fixed schedules of their own: OAuth tokens and codes 31 days after they expire, and unused self-registered MCP clients. See Cleanup and Revocation.

To give another model a retention period, use Chassis’s Northwestern\SysDev\Chassis\Models\Concerns\PrunesAfterRetentionPeriod trait, return its setting from retentionConfigKey(), and add the setting under platform.retention. Override retentionColumn() when the record’s date isn’t created_at, and prefer an indexed column.

  1. Application Name

    Find: Northwestern Laravel Starter

    Replace: Your Application Name

  2. Package/Project Identifier

    Find: northwestern-laravel-starter

    Replace: your-project-slug

Leave this reference to the upstream starter out of both replacements:

  • The Coveralls upload’s if: github.repository == ... guard in .github/workflows/check-pr.yml; remove the step or the condition instead, as its comment explains

By default, the docs/ directory contains documentation for the starter kit itself. This can be removed entirely or modified to host your project’s documentation.

If you want to remove the documentation module, follow these steps:

Terminal window
rm .github/workflows/deploy-docs.yml
rm -rf docs/

If you keep it, update the DOCS_CNAME env var at the top of .github/workflows/deploy-docs.yml to point to your own domain.

.github/workflows/release.yml and .github/workflows/smoke-test.yml release and test the starter itself. Delete them unless you adapt them for your project.

Replace the pages the starter ships as placeholders:

  • Landing page: resources/views/public/landing.blade.php, which guests see at /
  • Component gallery: delete app/Filament/App/Starter/Pages/ComponentGallery.php when you no longer need it
  • Where signed-in users land: destinationFor() in app/Http/Controllers/HomeController.php sends everyone to the app panel

Keep AGENTS.md up to date as the application grows; coding agents read it.

Contact Support (SUPPORT_ENABLED, SUPPORT_MAIL_TO) and the public changelog (CHANGELOG_ENABLED) are off by default. Turn them on in .env.example if your application uses them.