Famous.ai Config System
Centralized environment-based configuration
๐ฏ Why Centralized Config?
โ No hardcoded URLs - Switch environments instantly
โ Type-safe - TypeScript catches config errors
โ Single source of truth - Update URLs in one place
โ Environment-specific - Dev, staging, prod configs
โ Prevents redirect loops - Consistent URL usage
Step 1: Create src/lib/config.ts
Central configuration file
// src/lib/config.ts
// Centralized configuration for all environment-dependent URLs
interface AppConfig {
GAME_URL: string;
SNAPPY_LOGIN_URL: string;
SNAPPY_VERIFY_TOKEN_URL: string;
MOTHERSHIP_URL: string;
IS_PRODUCTION: boolean;
IS_DEVELOPMENT: boolean;
}
function getConfig(): AppConfig {
const mode = import.meta.env.MODE || 'development';
const IS_PRODUCTION = mode === 'production';
const IS_DEVELOPMENT = mode === 'development';
// Game URL (where this game is hosted)
const GAME_URL = import.meta.env.VITE_GAME_URL ||
(IS_PRODUCTION
? 'https://play.snappyidioms.com'
: 'http://localhost:5173');
// SnappyIdioms.com URLs
const SNAPPY_BASE = import.meta.env.VITE_SNAPPY_BASE_URL ||
'https://snappyidioms.com';
return {
GAME_URL,
SNAPPY_LOGIN_URL: `${SNAPPY_BASE}/login`,
SNAPPY_VERIFY_TOKEN_URL: `${SNAPPY_BASE}/api/verifyGameToken`,
MOTHERSHIP_URL: `${SNAPPY_BASE}/api`,
IS_PRODUCTION,
IS_DEVELOPMENT
};
}
export const config = getConfig();
// Type-safe access
export const {
GAME_URL,
SNAPPY_LOGIN_URL,
SNAPPY_VERIFY_TOKEN_URL,
MOTHERSHIP_URL,
IS_PRODUCTION,
IS_DEVELOPMENT
} = config;Step 2: Create .env Files
Environment-specific configuration
.env.example (commit to git)
# .env.example # Copy this to .env.local and fill in your values # Game URL (where this Scrabble game is hosted) VITE_GAME_URL=http://localhost:5173 # SnappyIdioms.com base URL VITE_SNAPPY_BASE_URL=https://snappyidioms.com # Environment VITE_MODE=development
.env.production (for build)
# .env.production # Production environment variables VITE_GAME_URL=https://play.snappyidioms.com VITE_SNAPPY_BASE_URL=https://snappyidioms.com VITE_MODE=production
Step 3: Update Usage Throughout Codebase
// BEFORE (hardcoded URLs - BAD)
const redirectUrl = 'https://play.snappyidioms.com';
const loginUrl = 'https://snappyidioms.com/login';
// AFTER (using centralized config - GOOD)
import { GAME_URL, SNAPPY_LOGIN_URL } from '@/lib/config';
const redirectUrl = GAME_URL;
const loginUrl = SNAPPY_LOGIN_URL;
// Usage in auth flow
const handleSignIn = () => {
const url = `${SNAPPY_LOGIN_URL}?redirect=${encodeURIComponent(GAME_URL)}`;
window.open(url, '_blank');
};
// Usage in token verification
const verifyToken = async (token: string) => {
const response = await fetch(SNAPPY_VERIFY_TOKEN_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token })
});
return response.json();
};Update platformAuth.ts
// src/lib/platformAuth.ts
// Update to use centralized config
import { SNAPPY_VERIFY_TOKEN_URL, GAME_URL } from './config';
async function validateTokenAsync(token: string, payload: any) {
try {
// Use config instead of hardcoded URL
const response = await fetch(SNAPPY_VERIFY_TOKEN_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token })
});
const result = await response.json();
// ... rest of validation logic
} catch (error) {
console.error('[Auth] Validation failed:', error);
}
}Update AuthModal.tsx
// src/components/game/AuthModal.tsx
// Update to use centralized config
import { SNAPPY_LOGIN_URL, GAME_URL } from '@/lib/config';
export function AuthModal() {
const handleSignIn = () => {
// Use config URLs
const redirectUrl = `${SNAPPY_LOGIN_URL}?redirect=${encodeURIComponent(GAME_URL)}`;
window.open(redirectUrl, '_blank');
};
// ... rest of component
}Step 4: Update vite.config.ts
// vite.config.ts
// Ensure environment variables are properly loaded
import { defineConfig, loadEnv } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');
return {
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
define: {
// Expose env vars to client
'import.meta.env.VITE_GAME_URL': JSON.stringify(env.VITE_GAME_URL),
'import.meta.env.VITE_SNAPPY_BASE_URL': JSON.stringify(env.VITE_SNAPPY_BASE_URL),
},
};
});Step 5: Update .gitignore
# Add to .gitignore .env .env.local .env.production.local .env.development.local
โ
Files to Update
- โ
src/lib/config.ts- Create this file - โ
.env.example- Create this file - โ
.env.production- Create this file - โ
.env.local- Create for local dev (not in git) - โ
src/lib/platformAuth.ts- Replace hardcoded URLs - โ
src/components/game/AuthModal.tsx- Replace hardcoded URLs - โ
src/components/game/LinkAccountPrompt.tsx- Replace hardcoded URLs - โ
src/components/AppLayout.tsx- Replace hardcoded URLs - โ
src/lib/mothership.ts- Replace hardcoded URLs - โ
vite.config.ts- Update config loader - โ
.gitignore- Add .env files
๐ Testing
Local Development:
npm run devShould use localhost URLs
Production Build:
npm run buildShould use play.snappyidioms.com
Verify Config:
console.log(config)Check config values in browser console