Skip to content

Environments ​

EnvironmentBranchEnv fileSSRNotes
Localfeature branches.env from .env.exampleOptional via Vitenpm run dev + @inertiajs/vite — no separate Node process
Stagingstaging.env on server (from .env.staging.example / CI secrets)OffClient-only on cPanel (INERTIA_SSR_ENABLED=false)
Productionmainserver .envOffClient-only npm run build; APP_DEBUG=false

Staging and production on cPanel stay client-rendered. Local Vite may still use Inertia’s built-in SSR during npm run dev only.

Staging checklist ​

  1. Subdomain e.g. staging.sawtee.org → document root public/
  2. Separate MySQL database
  3. GitHub Environment staging + STAGING_* secrets for app/DB/target dir; reuse prod SSH_*, MAIL_*, and DB_PASSWORD (see main README)
  4. Push to staging → .github/workflows/deploy-staging.yml (no cPanel Node.js App required)

TEMPORARY: responsive-image backfill ​

Staging and production deploys currently run php artisan sawtee:backfill-responsive-images after migrate so existing uploads get Spatie width variants and tiny placeholders. The command isolates each small batch in its own PHP process so cPanel’s 128MB CLI limit cannot accumulate across 1,000+ images.

Remove those TEMPORARY workflow steps from .github/workflows/deploy-staging.yml and .github/workflows/deploy.yml after the command has succeeded once on each environment. New uploads generate variants on their own; leaving the step in place is cheap (it skips items that already have variants) but still unnecessary.

Env files in the repo ​

FileCommitted?Role
.env.exampleYesFresh Laravel-style defaults for new installs
.env.staging.exampleYesStaging template (no secrets)
.env / .env.stagingNoReal secrets; never commit

Copy templates:

bash
cp .env.example .env
cp .env.staging.example .env.staging

Analytics (optional) ​

First-party page views are controlled in config/analytics.php. Staging checklist keys (also in .env.staging.example):

VariableDefaultPurpose
ANALYTICS_ENABLEDtrueRecord public page views
ANALYTICS_DEDUPE_MINUTES30Same session + path not counted again within this window
ANALYTICS_HASH_SALTfalls back to APP_KEYSalt for IP / user-agent hashes — set a dedicated value in production

Admin paths are never recorded. Dashboard analytics load as a deferred Inertia prop.

Branded errors vs debug ​

With APP_DEBUG=true in local or development, Laravel’s detailed exception UI is kept (branded Inertia error pages are skipped). Staging/production should run APP_DEBUG=false so visitors see the branded Errors/Error page for common statuses (403, 404, 500, 503). Visitor-facing strings on that page are edited in Site Settings → Error pages.

Session cookies on HTTPS ​

Set SESSION_SECURE_COOKIE=true on Herd, staging, and production so the session cookie is only sent over HTTPS (required for a trustworthy PWA install surface). Leave unset only if you deliberately run plain HTTP locally.

Progressive Web App ​

Production client builds emit a service worker and web manifest (npm run build). Deploy health checks should confirm public/sw.js and public/manifest.webmanifest exist after build. The PWA is public-site only — it does not extend admin sessions or cache /admin.

Documentation for the SAWTEE CMS and public website.