Environment Variables
Managing environment variables, MANIC_PUBLIC_ prefix rules, and configuration in Manic.
Environment Variables
TL;DR
Manic uses environment variables for configuration. Variables prefixed with MANIC_PUBLIC_ are exposed to the client, while server-only variables remain protected. Use .env files for different environments.
What It Is
Environment variables in Manic follow a prefix-based visibility model:
| Prefix | Client Visible | Server Visible | Use Case |
|---|---|---|---|
MANIC_PUBLIC_ | ✓ Yes | ✓ Yes | Public config |
| None | ✗ No | ✓ Yes | Private keys |
Special files:
.env- All environments.env.local- Local only (not committed).env.development- Dev only.env.production- Production only
Prerequisites
- Getting Started - Initial setup
- Project Structure - File organization
Quick Start
1. Create .env file
# .env.local (never committed)
MANIC_PUBLIC_API_URL=https://api.example.com
API_SECRET=sk-12345678902. Use in code
import { getEnv } from 'manicjs/env';
// Client-safe (MANIC_PUBLIC_*)
console.log(getEnv('MANIC_PUBLIC_API_URL'));
// Server-only
// console.log(getEnv('API_SECRET')); // ✗ Undefined on clientHow It Works
Environment Loading Flow
Variable Visibility
Type Definitions
// Manic environment types
interface ManicEnv {
// Public (MANIC_PUBLIC_*)
MANIC_PUBLIC_API_URL?: string;
MANIC_PUBLIC_TITLE?: string;
// Private
API_SECRET?: string;
DATABASE_URL?: string;
}API Reference
getEnv(key: string)
Primary helper for accessing environment variables in both client and server code.
import { getEnv } from 'manicjs/env';
// Public variables (MANIC_PUBLIC_*) are available everywhere
const apiUrl = getEnv('MANIC_PUBLIC_API_URL');
// Private variables are ONLY available on the server
const secret = getEnv('API_SECRET');Accessing in Components
import { getEnv } from 'manicjs/env';
export function MyComponent() {
const apiUrl = getEnv('MANIC_PUBLIC_API_URL');
return <div>API: {apiUrl}</div>;
}Examples
Example 1: API Configuration
# .env
MANIC_PUBLIC_API_URL=https://api.example.com
# .env.local (local development)
MANIC_PUBLIC_API_URL=http://localhost:3001// app/routes/api/client.ts
import { getEnv } from 'manicjs/env';
export const apiClient = {
baseUrl: getEnv('MANIC_PUBLIC_API_URL') || 'https://api.example.com',
};Example 2: Feature Flags
# .env
MANIC_PUBLIC_ENABLE_BETA=false
# .env.local
MANIC_PUBLIC_ENABLE_BETA=trueimport { getEnv } from 'manicjs/env';
export function BetaFeature() {
if (getEnv('MANIC_PUBLIC_ENABLE_BETA') !== 'true') {
return null;
}
return <div>Beta feature enabled!</div>;
}Example 3: Third-Party Services
# .env.local
MANIC_PUBLIC_STRIPE_PUBLIC_KEY=pk_test_xxx
STRIPE_SECRET_KEY=sk_test_xxx// Stripe on client
import { loadStripe } from '@stripe/stripe-js';
import { getEnv } from 'manicjs/env';
const stripePromise = loadStripe(
getEnv('MANIC_PUBLIC_STRIPE_PUBLIC_KEY')
);// Stripe on server (API route)
// app/api/payment/index.ts
import { getEnv } from 'manicjs/env';
const stripe = require('stripe')(
getEnv('STRIPE_SECRET_KEY')
);Example 4: Database URL
# .env.local (not committed)
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb// app/api/db.ts
// Server-only access
import { getEnv } from 'manicjs/env';
const dbUrl = getEnv('DATABASE_URL');Never expose database URLs or other sensitive secrets in MANIC_PUBLIC_ prefixed variables. These are baked into the client bundle and visible to anyone.
Advanced Patterns
Pattern 1: Type-Safe Environment
// env.d.ts
interface Environment {
MANIC_PUBLIC_API_URL: string;
MANIC_PUBLIC_APP_NAME: string;
MANIC_PUBLIC_ENABLE_BETA: string;
}
declare module 'manicjs/env' {
export function getEnv<T extends keyof Environment>(key: T): Environment[T];
}Pattern 2: Validation
// app/routes/~lib/env.ts
import { getEnv } from 'manicjs/env';
function getRequiredEnv(key: string): string {
const value = getEnv(key);
if (!value) {
throw new Error(`Missing required env: ${key}`);
}
return value;
}
export const API_URL = getRequiredEnv('MANIC_PUBLIC_API_URL');Common Issues
Issue 1: Variable Undefined
Problem: getEnv('MANIC_PUBLIC_XXX') is undefined.
Checks:
- Variable is in
.envfile - File is in correct location
- Server was restarted after changes
Solution:
# .env must be in project root
# ✓ /my-app/.env
# ✗ /my-app/app/.envIssue 2: Variables Exposed to Client
Problem: Private variables visible in browser.
Solution: Remove MANIC_PUBLIC_ prefix:
# ✗ BAD: Exposed to client
MANIC_PUBLIC_SECRET=xxx
# ✓ GOOD: Server-only
SECRET=xxxSecurity Best Practices
Never commit secrets — always add .env.local and other sensitive environment files to your .gitignore.
Use MANIC_PUBLIC_ prefix only for variables that are safe to expose to the client.
Validate required variables at startup to ensure your application doesn't fail silently at runtime.
Use different files for different environments.
File Precedence
When multiple files define the same variable:
Higher priority (overrides):
1. .env.local
2. .env.development / .env.production
3. .env
Lower priority:See also: