Sentry
The starter integrates Sentry for both PHP and JavaScript error tracking. The PHP SDK (sentry/sentry-laravel) captures server-side exceptions, queue failures, and performance traces. The JavaScript SDK (@sentry/browser) captures client-side errors and is initialized by northwestern-laravel-ui.
How JavaScript Initialization Works
Section titled “How JavaScript Initialization Works”The Blade layout in northwestern-laravel-ui (purple-chrome.blade.php) initializes the Sentry JS SDK after the page loads:
<script type="text/javascript"> document.addEventListener('DOMContentLoaded', function () { Sentry.setUser(/* user context from PHP */);
const sentryConfig = /* config from PHP */; sentryConfig.integrations.push(Sentry.browserTracingIntegration());
Sentry.init(sentryConfig); });</script>The template reads a $sentry_config array from the PHP side (populated by the northwestern-laravel-ui service provider) and calls Sentry.init(), Sentry.setUser(), and Sentry.browserTracingIntegration() on the global window.Sentry object. The custom 500 error page calls Sentry.captureFeedback() to submit user feedback, and Sentry.captureException() is available for inline scripts and console debugging.
Selective Imports
Section titled “Selective Imports”The starter does not use import * as Sentry. A namespace import pulls the entire SDK into the bundle, including Session Replay, User Feedback UI, and Canvas integrations that most applications never use. That adds roughly 300 KB to the minified output.
Instead, resources/js/bootstrap.js imports only the methods the blade template and error page need:
import { browserTracingIntegration, captureException, captureFeedback, init as sentryInit, setUser as sentrySetUser,} from "@sentry/browser";
window.Sentry = { browserTracingIntegration, captureException, captureFeedback, init: sentryInit, setUser: sentrySetUser,};The window.Sentry object acts as the bridge between the Vite-bundled JS and the inline <script> in the blade template.
Adding SDK Features
Section titled “Adding SDK Features”If your application needs a Sentry feature beyond these, add it to the import and the window.Sentry object.
For example, to enable Session Replay:
-
Add the import in
resources/js/bootstrap.js:import {browserTracingIntegration,captureException,captureFeedback,init as sentryInit,replayIntegration,setUser as sentrySetUser,} from "@sentry/browser"; -
Export it on
window.Sentry:window.Sentry = {browserTracingIntegration,captureException,captureFeedback,replayIntegration,init: sentryInit,setUser: sentrySetUser,}; -
Push the integration in your Sentry init script (in a blade view or
@stack('scripts')block):<script>document.addEventListener('DOMContentLoaded', function () {const sentryConfig = /* existing config */;sentryConfig.integrations.push(Sentry.replayIntegration());Sentry.init(sentryConfig);});</script>
The same pattern applies to any other Sentry integration: feedbackIntegration, replayCanvasIntegration, httpClientIntegration, etc. Import it, export it, use it.
PHP Configuration
Section titled “PHP Configuration”The starter ships config/sentry.php with sensible defaults:
| Setting | Default | Description |
|---|---|---|
dsn | env('SENTRY_LARAVEL_DSN') | Project DSN from Sentry |
release | env('VAPOR_COMMIT_HASH') | Git SHA, set automatically by Vapor’s --commit flag |
environment | env('SENTRY_ENVIRONMENT') | Falls back to APP_ENV |
sample_rate | 1.0 | Error sampling rate |
traces_sample_rate | null (disabled) | Performance trace sampling |
send_default_pii | false | Whether to send PII by default |
Breadcrumbs capture Laravel logs, cache events, Livewire components, SQL queries, queue jobs, commands, HTTP client requests, and notifications. Performance tracing captures SQL queries (with origin detection), views, Livewire, HTTP clients, cache, and queue jobs.
All settings are overridable via environment variables. See Sentry’s Laravel configuration docs for the full list.
Source Maps & Release Tracking
Section titled “Source Maps & Release Tracking”JS errors in Sentry show minified stack traces by default. The starter ships @sentry/vite-plugin in vite.config.js to upload source maps during CI builds. The plugin also creates a Sentry release and associates git commits, enabling “Suspect Commits” on both JS and PHP errors.
What the Starter Provides
Section titled “What the Starter Provides”vite.config.js includes the plugin pre-configured:
sentryVitePlugin({ org: process.env.SENTRY_ORG, project: process.env.SENTRY_PROJECT, disable: !process.env.SENTRY_AUTH_TOKEN, telemetry: false, release: { name: process.env.SENTRY_RELEASE, setCommits: { auto: true, }, }, sourcemaps: { filesToDeleteAfterUpload: "public/build/assets/*.map", },}),| Option | Purpose |
|---|---|
sourcemap: true | Generates .map files for the plugin to upload. |
disable | Skips the plugin in local dev where no auth token exists. |
telemetry: false | Prevents the plugin from sending its own diagnostics to Sentry. |
release.name | Ties source maps to the same git SHA the PHP SDK uses. |
release.setCommits.auto | Associates git commits with the release for “Suspect Commits.” |
filesToDeleteAfterUpload | Removes .map files before they reach production. |
The plugin reads SENTRY_AUTH_TOKEN from the environment automatically and creates/finalizes the release by default.
Prerequisites
Section titled “Prerequisites”These are configured at the org level and should already exist:
SENTRY_AUTH_TOKENas a GitHub org-level secret andSENTRY_ORG(northwestern-university) as an org-level variableSENTRY_AUTH_TOKENgranted to the repository (request access from an org admin)- The Sentry GitHub integration connected to the Northwestern GitHub org
Enabling Source Maps in Your App
Section titled “Enabling Source Maps in Your App”-
Set
SENTRY_PROJECTas a GitHub repo variableIn GitHub: Repo Settings > Secrets and variables > Actions > Variables
Variable Example Value SENTRY_PROJECTgraduate-student-trackingUse a variable, not a secret. The project slug is not sensitive.
-
Add a frontend build step to
deploy.ymlAfter dependency install, before
vapor deploy:- name: Build Frontend & Upload Source Mapsenv:SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}SENTRY_ORG: ${{ vars.SENTRY_ORG }}SENTRY_PROJECT: ${{ vars.SENTRY_PROJECT }}SENTRY_RELEASE: ${{ github.sha }}run: pnpm build -
Move the frontend build out of
vapor.ymlRemove
pnpm install && pnpm build && rm -rf node_modulesfrom the build commands in every environment:# Beforebuild:- 'COMPOSER_MIRROR_PATH_REPOS=1 composer install --no-dev'- 'php artisan event:cache'- 'pnpm install && pnpm build && rm -rf node_modules'# Afterbuild:- 'COMPOSER_MIRROR_PATH_REPOS=1 composer install --no-dev'- 'php artisan event:cache'Add
node_modulesto the ignore list:ignore:- node_modules/# ... existing ignores ... -
Deploy and verify
Trigger a test error after deploying and confirm in Sentry:
- JS errors show readable (un-minified) source code
- PHP errors show inline source context linking to GitHub
- The release matches the deployed git SHA
- “Suspect Commits” appear on error details
How the Release Identifier Works
Section titled “How the Release Identifier Works”The git SHA (${{ github.sha }}) reaches two consumers through different paths:
- JS (build time): The
pnpm buildstep passesSENTRY_RELEASEas an env var. The Vite plugin reads it during build, uploads source maps tagged with that release, and injects it into the JS bundle. The browser SDK picks it up automatically at runtime. - PHP (runtime): Vapor’s
--commitflag (already in deploy workflows) setsVAPOR_COMMIT_HASHas an env var on Lambda.config/sentry.phpreads it viaenv('VAPOR_COMMIT_HASH'). No additional Vapor secret is needed.
Both point to the same git SHA, so JS and PHP errors land under the same release in Sentry.
Local Development
Section titled “Local Development”The disable option turns off the plugin when SENTRY_AUTH_TOKEN is absent. pnpm build and pnpm dev work as before with zero plugin overhead. Source maps generate locally for browser DevTools but are not uploaded.