Environment variables and configuration options for the MemexLLM frontend.
Configuration is managed through environment variables. Next.js automatically loads .env.local in development and production.
| Variable | Description | Example |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Supabase project URL | https://xxx.supabase.co |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY |
Supabase anon/public key | eyJhbG... |
NEXT_PUBLIC_API_URL |
Backend API URL | http://localhost:8000 |
| Variable | Description | Default |
|---|---|---|
NEXT_PUBLIC_APP_URL |
Frontend app URL | http://localhost:3000 |
NEXT_PUBLIC_SENTRY_DSN |
Sentry error tracking DSN | - |
NEXT_PUBLIC_POSTHOG_KEY |
PostHog analytics key | - |
NEXT_PUBLIC_POSTHOG_HOST |
PostHog host URL | https://us.i.posthog.com |
NEXT_PUBLIC_LANGFUSE_HOST |
Langfuse host URL | https://cloud.langfuse.com |
NEXT_PUBLIC_GOOGLE_ANALYTICS_ID |
Google Analytics ID | - |
File: next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
// Configuration options
};
export default nextConfig;File: tailwind.config.ts
import type { Config } from "tailwindcss";
const config: Config = {
darkMode: ["class"],
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
colors: {
// Brand colors
synapse: {
50: "#fff8f0",
100: "#ffeed6",
200: "#ffdaa8",
300: "#ffc06a",
400: "#ff9c2a",
500: "#ff8200",
600: "#f06300",
700: "#c74a00",
800: "#9e3a08",
900: "#7f320d",
950: "#451705",
},
// Surface colors for dark theme
surface: {
0: "#0a0a0a",
1: "#141414",
2: "#1f1f1f",
3: "#2a2a2a",
},
},
fontFamily: {
sans: ["var(--font-sans)", "system-ui", "sans-serif"],
display: ["var(--font-display)", "Georgia", "serif"],
mono: ["var(--font-mono)", "Consolas", "monospace"],
},
},
},
plugins: [require("tailwindcss-animate")],
};
export default config;File: tsconfig.json
{
"compilerOptions": {
"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"]
}File: jest.config.ts
import type { Config } from "jest";
import nextJest from "next/jest.js";
const createJestConfig = nextJest({
dir: "./",
});
const config: Config = {
coverageProvider: "v8",
testEnvironment: "jsdom",
setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
moduleNameMapping: {
"^@/(.*)$": "<rootDir>/$1",
},
};
export default createJestConfig(config);File: 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;Create .env.local:
# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your-anon-key
# Backend API
NEXT_PUBLIC_API_URL=http://localhost:8000
# App URL
NEXT_PUBLIC_APP_URL=http://localhost:3000
# Optional: Analytics
NEXT_PUBLIC_SENTRY_DSN=
NEXT_PUBLIC_POSTHOG_KEY=phc_...
NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
NEXT_PUBLIC_LANGFUSE_HOST=https://cloud.langfuse.com
NEXT_PUBLIC_GOOGLE_ANALYTICS_ID=Set environment variables in your hosting platform:
Vercel:
vercel env add NEXT_PUBLIC_SUPABASE_URL
vercel env add NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY
vercel env add NEXT_PUBLIC_API_URLEnvironment-specific values:
| Environment | NEXT_PUBLIC_API_URL |
|---|---|
| Development | http://localhost:8000 |
| Staging | https://api-staging.memexllm.app |
| Production | https://api.memexllm.app |
Feature flags can be implemented via environment variables:
NEXT_PUBLIC_ENABLE_FEEDBACK=true
NEXT_PUBLIC_ENABLE_ANALYTICS=true
NEXT_PUBLIC_ENABLE_STREAMING=trueUsage in code:
const enableFeedback = process.env.NEXT_PUBLIC_ENABLE_FEEDBACK === "true";
{enableFeedback && <FeedbackButton />}- Public Variables Only: Only use
NEXT_PUBLIC_prefix for variables needed in browser - Server Variables: Without prefix = server-only (API routes, Server Components)
- Secrets: Never commit secrets to version control
- Validation: Validate env vars at startup
// lib/config.ts
export function validateEnv() {
const required = [
"NEXT_PUBLIC_SUPABASE_URL",
"NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY",
"NEXT_PUBLIC_API_URL",
];
for (const key of required) {
if (!process.env[key]) {
throw new Error(`Missing required environment variable: ${key}`);
}
}
}// next.config.ts
const nextConfig: NextConfig = {
output: "standalone", // For Docker deployment
// or
output: "export", // For static export
};// next.config.ts
const nextConfig: NextConfig = {
images: {
domains: ["supabase.co", "localhost"],
remotePatterns: [
{
protocol: "https",
hostname: "*.supabase.co",
},
],
},
};// next.config.ts
const nextConfig: NextConfig = {
async rewrites() {
return [
{
source: "/api/:path*",
destination: `${process.env.NEXT_PUBLIC_API_URL}/api/:path*`,
},
];
},
};Enabled by default in development. For production:
// next.config.ts
const nextConfig: NextConfig = {
productionBrowserSourceMaps: true,
};// next.config.ts
const nextConfig: NextConfig = {
reactStrictMode: true,
};# Install
npm install -D @next/bundle-analyzer
# Run
ANALYZE=true npm run build// next.config.ts
const nextConfig: NextConfig = {
compress: true,
};- Check variable names start with
NEXT_PUBLIC_for client access - Restart dev server after changing
.env.local - Clear
.nextcache:rm -rf .next
Ensure tsconfig.json includes:
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}Configure backend CORS to allow frontend origin:
# Backend .env
CORS_ORIGINS=http://localhost:3000,https://your-frontend.com