Environment Variable Validation
Decision to validate backend and frontend environment variables at startup
SuperImpress validates environment variables in both the backend and frontend before runtime logic depends on them.
Why validate environment variables
- Fail Fast: Catch missing or malformed configuration immediately instead of failing during requests.
- Type Safety: Convert untyped string input into validated, typed config objects.
- Safer Deployments: Reduce config drift between local, Docker, and production environments.
- Clear Error Messages: Return actionable startup errors that identify the invalid key.
Backend implementation
Backend env validation lives in backend/src/env.ts.
- Loads values from
.envviadotenv/config. - Defines a TypeBox schema for required and optional variables.
- Builds a runtime object from
process.envwith defaults forFRONTEND_URLandPORT. - Validates with
Value.Errors(...)and throws a combined error message when invalid. - Applies explicit URL checks for
DATABASE_URL,BETTER_AUTH_URL, andFRONTEND_URL. - Exports a typed
envobject used by the rest of the backend.
Validated backend keys currently include:
DATABASE_URLBETTER_AUTH_SECRETBETTER_AUTH_URLLINKEDIN_CLIENT_IDLINKEDIN_CLIENT_SECRETFRONTEND_URLPORTRESEND_API_KEY(optional)RESEND_FROM_EMAIL(optional)
Frontend implementation
Frontend env validation lives in frontend/src/env.ts and frontend/src/env-schema.ts.
- Uses
@t3-oss/env-corecreateEnv(...)withimport.meta.env. - Uses a Zod client schema for
VITE_variables. - Restricts client-visible keys via
clientPrefix: 'VITE_'. - Uses
emptyStringAsUndefined: trueso blank values fail validation. - Exports a typed
envobject consumed by app constants and API configuration.
Validated frontend keys currently include:
VITE_API_BASEVITE_APP_URL
Tradeoffs and constraints
- Schema Maintenance: Env schemas must be kept in sync with
.env.examplefiles. - Format vs Reachability: URL checks validate shape, not whether the endpoint is reachable.
- Frontend Visibility:
VITE_values are public by design and must never contain secrets.