Enabled
When to enable:
- Clients or partners without NetIDs
- Testing accounts for non-Northwestern users
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:
# Comma-separated list of NetIDsSUPER_ADMIN_NETIDS=abc123,xyz789,def456The StakeholderSeeder runs on deploy (the reference vapor.yml in Deployment runs php artisan db:seed --class=StakeholderSeeder) and:
Set SUPER_ADMIN_NETIDS and deploy; the seeder runs as part of the deploy. To add administrators between deploys, run it in that environment:
php artisan db:seed --class=StakeholderSeederdb:rebuild doesn’t run the seeder, so it needs no network. To sign in locally as yourself with NetID, configure SSO and Directory Search, set SUPER_ADMIN_NETIDS, and run the seeder after a rebuild:
php artisan db:seed --class=StakeholderSeederEdit config/local-auth.php or set environment variables:
# Enable/disable local authenticationLOCAL_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 limitsLOCAL_AUTH_RATE_LIMIT_PER_IP_PER_HOUR=20To change where users land after signing in, see Where Users Land After Signing In.
Enabled
When to enable:
Disabled
When to disable:
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,],/administration): Users → Add User → Add Local User# Master on/off switch for all API functionalityAPI_ENABLED=true# Enable API request loggingAPI_REQUEST_LOGGING_ENABLED=true
# Slow request threshold for monitoring (milliseconds)API_REQUEST_LOGGING_SLOW_THRESHOLD_MS=500How long request logs are kept is set by API_REQUEST_LOG_RETENTION_DAYS; see Data Retention.
# Enable probabilistic samplingAPI_REQUEST_LOGGING_SAMPLING_ENABLED=true
# Sample rate (0.0 to 1.0) - 0.1 = 10% of successful requestsAPI_REQUEST_LOGGING_SAMPLE_RATE=0.1The 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:
Open routes/api.php
Uncomment the NetID Update webhook route:
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:
'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:
ENVIRONMENT_LOCKDOWN_ENABLED=falseSet PRODUCTION_URL in .env.example so every environment inherits it:
PRODUCTION_URL=https://your-app.northwestern.eduChanging 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:
logoutThese 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.
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 wordmarkNU_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.
| Records | Setting | Default |
|---|---|---|
| Audit logs | AUDIT_RETENTION_DAYS | null (kept) |
| Sign-in records | LOGIN_RECORD_RETENTION_DAYS | 365 |
| Impersonation logs | IMPERSONATION_LOG_RETENTION_DAYS | null (kept) |
| Login code challenges | LOGIN_CHALLENGE_RETENTION_DAYS | 30 |
| API request logs | API_REQUEST_LOG_RETENTION_DAYS | 90 |
| Table exports and their files, from when they finish | EXPORT_RETENTION_DAYS | 7 |
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.
Application Name
Find: Northwestern Laravel Starter
Replace: Your Application Name
Package/Project Identifier
Find: northwestern-laravel-starter
Replace: your-project-slug
Leave this reference to the upstream starter out of both replacements:
if: github.repository == ... guard in .github/workflows/check-pr.yml; remove the step or the condition instead, as its comment explainsBy 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:
rm .github/workflows/deploy-docs.ymlrm -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:
resources/views/public/landing.blade.php, which guests see at /app/Filament/App/Starter/Pages/ComponentGallery.php when you no longer need itdestinationFor() in app/Http/Controllers/HomeController.php sends everyone to the app panelKeep 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.