Configuration¶
Environment variables and configuration files.
Environment Variables¶
Required Variables¶
| Variable | Description | Example |
|---|---|---|
NEXT_PUBLIC_AUTH_API_URL |
BetterAuth service URL | https://auth.example.com |
NEXT_PUBLIC_API_BASE_URL |
Core API URL | https://api.example.com |
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY |
Stripe public key | pk_live_xxx |
Optional Variables¶
| Variable | Description | Default |
|---|---|---|
NEXT_PUBLIC_WS_PORT |
WebSocket streaming port | 7103 |
LOKI_URL |
Loki logging endpoint | (console only) |
LOG_LEVEL |
Minimum log level | info |
NODE_ENV |
Environment name | development |
Example .env.local¶
# Authentication
NEXT_PUBLIC_AUTH_API_URL=http://localhost:8787
# Core API
NEXT_PUBLIC_API_BASE_URL=http://localhost:8080
# Stripe
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_xxx
# Streaming
NEXT_PUBLIC_WS_PORT=7103
# Logging (optional)
LOKI_URL=http://localhost:3100
# Environment
NODE_ENV=development
Production Environment¶
# Authentication
NEXT_PUBLIC_AUTH_API_URL=https://auth.getcoordinator.ai
# Core API
NEXT_PUBLIC_API_BASE_URL=https://api.getcoordinator.ai
# Stripe
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_xxx
# Streaming
NEXT_PUBLIC_WS_PORT=7103
# Logging
LOKI_URL=https://loki.getcoordinator.ai
# Environment
NODE_ENV=production
Configuration Files¶
next.config.ts¶
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
// External packages for server-side only
serverExternalPackages: ["winston", "winston-loki", "snappy"]
};
export default nextConfig;
tsconfig.json¶
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{ "name": "next" }
],
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
components.json (shadcn/ui)¶
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "app/globals.css",
"baseColor": "slate",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}
eslint.config.mjs¶
import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname
});
const eslintConfig = [
...compat.extends("next/core-web-vitals", "next/typescript")
];
export default eslintConfig;
postcss.config.mjs¶
Path Aliases¶
Configured in tsconfig.json:
Usage:
import { Button } from "@/components/ui/button";
import { useAuth } from "@/hooks/use-auth";
import { fetchJSON } from "@/lib/utils";
Runtime Configuration¶
API Base URL¶
Computed at runtime in hooks:
const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || "http://localhost:8080";
const basePath = `${API_BASE_URL}/api/v1/actions`;
Auth URL¶
Configured in auth client:
export const authClient = createAuthClient({
baseURL: process.env.NEXT_PUBLIC_AUTH_API_URL || "http://localhost:8787"
});
WebSocket URL¶
Computed with organization metadata:
const serverHostURL = organization.metadata?.serverHostURL;
const wsPort = process.env.NEXT_PUBLIC_WS_PORT || "7103";
const wsUrl = `ws://${serverHostURL}:${wsPort}/ws/stream/${cameraId}`;
Feature Flags¶
Currently no feature flag system. Consider implementing:
// Example future implementation
const FEATURES = {
training: process.env.NEXT_PUBLIC_ENABLE_TRAINING === "true",
passkeys: process.env.NEXT_PUBLIC_ENABLE_PASSKEYS === "true"
};
Validation¶
Environment variables are accessed directly. For validation, consider:
// lib/env.ts
import { z } from "zod";
const envSchema = z.object({
NEXT_PUBLIC_AUTH_API_URL: z.string().url(),
NEXT_PUBLIC_API_BASE_URL: z.string().url(),
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: z.string().startsWith("pk_")
});
export const env = envSchema.parse({
NEXT_PUBLIC_AUTH_API_URL: process.env.NEXT_PUBLIC_AUTH_API_URL,
NEXT_PUBLIC_API_BASE_URL: process.env.NEXT_PUBLIC_API_BASE_URL,
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
});
Secrets Management¶
Never Commit¶
.env.local- API keys
- Stripe secret keys
- Database credentials
.gitignore¶
Production Secrets¶
Use environment variable injection in deployment:
- Docker: -e flags or .env file
- Kubernetes: ConfigMaps/Secrets
- Vercel: Environment Variables UI
- Railway/Render: Environment settings