Skip to content

Commit 45f20df

Browse files
author
apex-ai-net
committed
fix: optimize environment variables for Netlify deployment
- Move Stripe price IDs to centralized config (lib/stripe/pricing-config.ts) - Add SOCIAL_URLS and FEATURE_FLAGS constants with smart defaults - Update payment API to use centralized pricing config - Create comprehensive deployment guide (docs/NETLIFY_ENV_VARS.md) - Add environment variable size validation script (npm run validate:env-size) - Update .env.example with production categorization - Enhance netlify.toml with deployment documentation - Reduce Lambda env vars from 88 to 27 (~2.8KB) Resolves AWS Lambda 4KB environment variable limit issue. All 9 Stripe price IDs maintained (including ONECENT/PENNY discount codes). Keeps Twilio, SendGrid, and Sentry services enabled. See docs/NETLIFY_ENV_VARS.md for complete deployment instructions.
1 parent 0374512 commit 45f20df

10 files changed

Lines changed: 1133 additions & 264 deletions

File tree

β€Ž.env.exampleβ€Ž

Lines changed: 126 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,34 @@
11
# MentoLoop Environment Variables Template
22
# Copy this file to .env.local for development
3-
# Use these variable names in Netlify Dashboard for production
3+
#
4+
# ============================================
5+
# PRODUCTION DEPLOYMENT NOTES
6+
# ============================================
7+
# βœ… = Required in Netlify production environment
8+
# βš™οΈ = Optional (has defaults, can be omitted)
9+
# πŸ§ͺ = Development/Testing only (DO NOT set in production)
10+
# πŸ“¦ = Build-time only (set in Netlify Build scope, not runtime)
11+
#
12+
# See docs/NETLIFY_ENV_VARS.md for complete deployment guide
13+
#
14+
# AWS Lambda has 4KB env var limit. We've optimized by:
15+
# - Moving Stripe price IDs to lib/stripe/pricing-config.ts
16+
# - NEXT_PUBLIC_* vars are baked into build, not needed at runtime
17+
# - Removed test/dev variables from production
18+
#
19+
# Target: ~27 runtime variables in production
420

521
# ============================================
6-
# AUTHENTICATION (Clerk)
22+
# βœ… AUTHENTICATION (Clerk) - REQUIRED
723
# ============================================
24+
CLERK_SECRET_KEY=sk_test_YOUR_CLERK_SECRET_KEY # βœ… Runtime required
25+
CLERK_JWT_ISSUER_DOMAIN=https://your-clerk-issuer.example.com # βœ… Runtime required
26+
CLERK_WEBHOOK_SECRET=whsec_YOUR_WEBHOOK_SECRET # βœ… Runtime required
27+
28+
# πŸ“¦ Build-time only (set in Netlify Build environment, not runtime)
829
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_YOUR_CLERK_PUBLISHABLE_KEY
9-
CLERK_SECRET_KEY=sk_test_YOUR_CLERK_SECRET_KEY
10-
CLERK_JWT_ISSUER_DOMAIN=https://your-clerk-issuer.example.com
11-
CLERK_WEBHOOK_SECRET=whsec_YOUR_WEBHOOK_SECRET
1230

13-
# Clerk URLs
31+
# πŸ“¦ Clerk URLs (baked into build)
1432
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
1533
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
1634
NEXT_PUBLIC_CLERK_SIGN_IN_FORCE_REDIRECT_URL=/dashboard
@@ -19,126 +37,155 @@ NEXT_PUBLIC_CLERK_SIGN_IN_FALLBACK_REDIRECT_URL=/dashboard
1937
NEXT_PUBLIC_CLERK_SIGN_UP_FALLBACK_REDIRECT_URL=/dashboard
2038

2139
# ============================================
22-
# DATABASE (Supabase)
40+
# βœ… DATABASE (Supabase) - REQUIRED
2341
# ============================================
24-
SUPABASE_URL=https://YOUR_SUPABASE_PROJECT.supabase.co
25-
SUPABASE_SERVICE_ROLE_KEY=YOUR_SUPABASE_SERVICE_ROLE_KEY
26-
SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY
42+
SUPABASE_URL=https://YOUR_SUPABASE_PROJECT.supabase.co # βœ… Runtime required
43+
SUPABASE_SERVICE_ROLE_KEY=YOUR_SUPABASE_SERVICE_ROLE_KEY # βœ… Runtime required
44+
SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY # βœ… Runtime required
45+
46+
# πŸ“¦ Build-time only (baked into client bundle)
2747
NEXT_PUBLIC_SUPABASE_URL=https://YOUR_SUPABASE_PROJECT.supabase.co
2848
NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY
49+
50+
# βš™οΈ Optional (defaults provided)
2951
SUPABASE_POOL_SIZE=10
3052
SUPABASE_SCHEMA=public
3153

3254
# ============================================
33-
# AI SERVICES
55+
# βš™οΈ AI SERVICES - OPTIONAL
3456
# ============================================
35-
OPENAI_API_KEY=sk-proj-YOUR_OPENAI_API_KEY
36-
GEMINI_API_KEY=YOUR_GEMINI_API_KEY
57+
OPENAI_API_KEY=sk-proj-YOUR_OPENAI_API_KEY # βš™οΈ Optional - for AI matching
58+
GEMINI_API_KEY=YOUR_GEMINI_API_KEY # βš™οΈ Optional - for AI matching
3759

3860
# ============================================
39-
# PAYMENT PROCESSING (Stripe)
40-
# SECURITY: Price IDs are SERVER-SIDE ONLY
41-
# NEVER expose as NEXT_PUBLIC_* variables
61+
# βœ… PAYMENT PROCESSING (Stripe) - REQUIRED
4262
# ============================================
63+
# SECURITY: Price IDs are SERVER-SIDE ONLY via lib/stripe/pricing-config.ts
64+
# NEVER expose as NEXT_PUBLIC_* variables
65+
66+
STRIPE_SECRET_KEY=sk_test_YOUR_STRIPE_SECRET_KEY # βœ… Runtime required
67+
STRIPE_WEBHOOK_SECRET=whsec_YOUR_STRIPE_WEBHOOK_SECRET # βœ… Runtime required
68+
69+
# πŸ“¦ Build-time only (baked into client bundle)
4370
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_YOUR_STRIPE_PUBLISHABLE_KEY
44-
STRIPE_SECRET_KEY=sk_test_YOUR_STRIPE_SECRET_KEY
45-
STRIPE_WEBHOOK_SECRET=whsec_YOUR_STRIPE_WEBHOOK_SECRET
46-
47-
# Server-side Price IDs (NEVER prefix with NEXT_PUBLIC_)
48-
STRIPE_PRICE_ID_STARTER=price_starter_example
49-
STRIPE_PRICE_ID_CORE=price_core_example
50-
STRIPE_PRICE_ID_ADVANCED=price_advanced_example
51-
STRIPE_PRICE_ID_PRO=price_pro_example
52-
STRIPE_PRICE_ID_ELITE=price_elite_example
53-
STRIPE_PRICE_ID_PREMIUM=price_premium_example
54-
STRIPE_PRICE_ID_ALACARTE=price_alacarte_example
55-
STRIPE_PRICE_ID_ONECENT=price_penny_example
56-
STRIPE_PRICE_ID_PENNY=price_penny_example
71+
72+
# βœ… Server-side Price IDs (accessed via lib/stripe/pricing-config.ts)
73+
STRIPE_PRICE_ID_STARTER=price_starter_example # βœ… Required
74+
STRIPE_PRICE_ID_CORE=price_core_example # βœ… Required
75+
STRIPE_PRICE_ID_ADVANCED=price_advanced_example # βœ… Required
76+
STRIPE_PRICE_ID_PRO=price_pro_example # βœ… Required
77+
STRIPE_PRICE_ID_ELITE=price_elite_example # βœ… Required
78+
STRIPE_PRICE_ID_PREMIUM=price_premium_example # βœ… Required
79+
STRIPE_PRICE_ID_ALACARTE=price_alacarte_example # βœ… Required
80+
STRIPE_PRICE_ID_ONECENT=price_penny_example # βœ… Required (discount code)
81+
STRIPE_PRICE_ID_PENNY=price_penny_example # βœ… Required (discount code)
5782

5883
# Preceptor payout configuration
5984
PRECEPTOR_PAYOUT_PERCENT=0.70
6085

6186
# ============================================
62-
# COMMUNICATIONS
87+
# βœ… COMMUNICATIONS - REQUIRED
6388
# ============================================
6489
# Twilio (SMS)
65-
TWILIO_ACCOUNT_SID=YOUR_TWILIO_ACCOUNT_SID
66-
TWILIO_AUTH_TOKEN=YOUR_TWILIO_AUTH_TOKEN
67-
TWILIO_PHONE_NUMBER=+1YOUR_PHONE_NUMBER
90+
TWILIO_ACCOUNT_SID=YOUR_TWILIO_ACCOUNT_SID # βœ… Runtime required
91+
TWILIO_AUTH_TOKEN=YOUR_TWILIO_AUTH_TOKEN # βœ… Runtime required
92+
TWILIO_PHONE_NUMBER=+1YOUR_PHONE_NUMBER # βœ… Runtime required
6893

6994
# SendGrid (Email)
70-
SENDGRID_API_KEY=SG.YOUR_SENDGRID_API_KEY
71-
SENDGRID_FROM_EMAIL=support@mentoloop.com
72-
EMAIL_DOMAIN=mentoloop.com
95+
SENDGRID_API_KEY=SG.YOUR_SENDGRID_API_KEY # βœ… Runtime required
96+
SENDGRID_FROM_EMAIL=support@mentoloop.com # βœ… Runtime required
97+
EMAIL_DOMAIN=mentoloop.com # βš™οΈ Optional (defaults to mentoloop.com)
7398

7499
# ============================================
75-
# APPLICATION SETTINGS
100+
# βœ… APPLICATION SETTINGS
76101
# ============================================
77-
NODE_ENV=production
102+
NODE_ENV=production # βœ… Runtime required (set to 'production' in Netlify)
103+
104+
# πŸ“¦ Build-time only (baked into client bundle)
78105
NEXT_PUBLIC_APP_URL=https://YOUR_DOMAIN.com
79106
NEXT_PUBLIC_API_URL=https://YOUR_DOMAIN.com/api
80107
NEXT_PUBLIC_EMAIL_DOMAIN=mentoloop.com
81108
NEXT_PUBLIC_ANALYTICS_ENDPOINT=https://YOUR_DOMAIN.com/api/analytics
82109
NEXT_PUBLIC_DATA_LAYER=supabase
83110

84111
# ============================================
85-
# SECURITY SETTINGS
112+
# βœ… SECURITY SETTINGS
86113
# ============================================
87-
# CSRF Protection - Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
88-
CSRF_SECRET_KEY=YOUR_64_CHARACTER_HEX_STRING_HERE
114+
# CSRF Protection - Generate with: openssl rand -base64 32
115+
CSRF_SECRET_KEY=YOUR_64_CHARACTER_HEX_STRING_HERE # βœ… Runtime required (min 32 chars)
89116

90-
# Rate Limiting (Upstash Redis)
117+
# βš™οΈ Rate Limiting (Upstash Redis) - Optional, falls back to in-memory
91118
# Get credentials from: https://console.upstash.com/
92-
UPSTASH_REDIS_REST_URL=https://YOUR_UPSTASH_ENDPOINT.upstash.io
93-
UPSTASH_REDIS_REST_TOKEN=YOUR_UPSTASH_REST_TOKEN
119+
UPSTASH_REDIS_REST_URL=https://YOUR_UPSTASH_ENDPOINT.upstash.io # βš™οΈ Optional
120+
UPSTASH_REDIS_REST_TOKEN=YOUR_UPSTASH_REST_TOKEN # βš™οΈ Optional
94121

95-
# Other Security Settings (Optional)
96-
ADMIN_SECRET=admin-secret-key
97-
ENABLE_SECURITY_HEADERS=true
122+
# βš™οΈ Other Security Settings - Optional (defaults provided)
123+
ADMIN_SECRET=admin-secret-key # βš™οΈ Optional
124+
ENABLE_SECURITY_HEADERS=true # βš™οΈ Optional (defaults to true)
98125

99126
# ============================================
100-
# FEATURE FLAGS (Optional)
127+
# βš™οΈ FEATURE FLAGS - OPTIONAL (all default to true)
101128
# ============================================
102-
ENABLE_AI_MATCHING=true
103-
ENABLE_SMS_NOTIFICATIONS=true
104-
ENABLE_EMAIL_NOTIFICATIONS=true
105-
ENABLE_PAYMENT_PROCESSING=true
129+
# Only set these to 'false' to disable features
130+
ENABLE_AI_MATCHING=true # βš™οΈ Optional (defaults to true)
131+
ENABLE_SMS_NOTIFICATIONS=true # βš™οΈ Optional (defaults to true)
132+
ENABLE_EMAIL_NOTIFICATIONS=true # βš™οΈ Optional (defaults to true)
133+
ENABLE_PAYMENT_PROCESSING=true # βš™οΈ Optional (defaults to true)
106134

107135
# ============================================
108-
# MONITORING (Optional)
136+
# βš™οΈ MONITORING - OPTIONAL
109137
# ============================================
110-
SENTRY_DSN=YOUR_SENTRY_DSN
111-
NEXT_PUBLIC_SENTRY_DSN=YOUR_SENTRY_PUBLIC_DSN
112-
GOOGLE_ANALYTICS_ID=YOUR_GA_ID
113-
CI=false
138+
SENTRY_DSN=YOUR_SENTRY_DSN # βœ… Recommended for production (error tracking)
139+
GOOGLE_ANALYTICS_ID=YOUR_GA_ID # βš™οΈ Optional
140+
141+
# πŸ“¦ Build-time only
142+
NEXT_PUBLIC_SENTRY_DSN=YOUR_SENTRY_PUBLIC_DSN # πŸ“¦ Optional (exposed to client)
114143

115-
# Optional Social URLs (shown in footer if set)
116-
NEXT_PUBLIC_TWITTER_URL=
117-
NEXT_PUBLIC_LINKEDIN_URL=
118-
NEXT_PUBLIC_FACEBOOK_URL=
119-
NEXT_PUBLIC_TIKTOK_URL=
120-
NEXT_PUBLIC_THREADS_URL=
144+
# βš™οΈ Social Media URLs (shown in footer if set, accessed via SOCIAL_URLS constant)
145+
NEXT_PUBLIC_TWITTER_URL= # βš™οΈ Optional (empty = not shown)
146+
NEXT_PUBLIC_LINKEDIN_URL= # βš™οΈ Optional (empty = not shown)
147+
NEXT_PUBLIC_FACEBOOK_URL= # βš™οΈ Optional (empty = not shown)
148+
NEXT_PUBLIC_TIKTOK_URL= # βš™οΈ Optional (empty = not shown)
149+
NEXT_PUBLIC_THREADS_URL= # βš™οΈ Optional (empty = not shown)
150+
NEXT_PUBLIC_INSTAGRAM_URL= # βš™οΈ Optional (empty = not shown)
121151

122152
# ============================================
123-
# TESTING (Development/CI only)
153+
# πŸ§ͺ TESTING - DEVELOPMENT/CI ONLY (DO NOT SET IN PRODUCTION)
124154
# ============================================
125-
NEXT_RUNTIME=nodejs
126-
CLERK_TEST_MODE=false
127-
E2E_TEST=false
128-
TEST_ADMIN_EMAIL=admin@example.com
129-
TEST_ADMIN_PASSWORD=changeme
130-
TEST_PRECEPTOR_EMAIL=preceptor@example.com
131-
TEST_PRECEPTOR_PASSWORD=changeme
132-
TEST_STUDENT_EMAIL=student@example.com
133-
TEST_STUDENT_PASSWORD=changeme
134-
TEST_PASSWORD=changeme
155+
NEXT_RUNTIME=nodejs # πŸ§ͺ Dev only
156+
CLERK_TEST_MODE=false # πŸ§ͺ Dev only
157+
E2E_TEST=false # πŸ§ͺ Dev only
158+
TEST_ADMIN_EMAIL=admin@example.com # πŸ§ͺ Dev only
159+
TEST_ADMIN_PASSWORD=changeme # πŸ§ͺ Dev only
160+
TEST_PRECEPTOR_EMAIL=preceptor@example.com # πŸ§ͺ Dev only
161+
TEST_PRECEPTOR_PASSWORD=changeme # πŸ§ͺ Dev only
162+
TEST_STUDENT_EMAIL=student@example.com # πŸ§ͺ Dev only
163+
TEST_STUDENT_PASSWORD=changeme # πŸ§ͺ Dev only
164+
TEST_PASSWORD=changeme # πŸ§ͺ Dev only
165+
166+
# πŸ§ͺ CI Variables (DO NOT SET IN PRODUCTION)
167+
CI=false # πŸ§ͺ CI only
168+
BUILD_TIMEOUT=600 # πŸ§ͺ CI only
169+
CACHE_MAX_AGE=3600 # πŸ§ͺ CI only
170+
NODE_OPTIONS=--max-old-space-size=4096 # πŸ§ͺ Build only
171+
SECRETS_SCAN_ENABLED=false # πŸ§ͺ CI only
135172

136173
# ============================================
137-
# SECURITY NOTES FOR DEPLOYMENT
174+
# πŸš€ PRODUCTION DEPLOYMENT CHECKLIST
138175
# ============================================
176+
# βœ… Set ~27 runtime variables in Netlify (see docs/NETLIFY_ENV_VARS.md)
177+
# βœ… Remove all NEXT_PUBLIC_* from production runtime (keep in build scope)
178+
# βœ… Remove all TEST_*, CI, BUILD_* variables from production
179+
# βœ… Use production keys (pk_live_, sk_live_) for live deployment
180+
# βœ… Generate strong CSRF_SECRET_KEY: openssl rand -base64 32
181+
# βœ… Verify all 9 Stripe price IDs are set correctly
182+
# βœ… Test deployment: npm run validate:env-size
183+
#
184+
# SECURITY NOTES:
139185
# 1. NEVER expose Price IDs as NEXT_PUBLIC_* variables
140-
# 2. Price IDs are handled server-side via /api/create-checkout
186+
# 2. Price IDs accessed server-side via lib/stripe/pricing-config.ts
141187
# 3. All Stripe operations use server-side validation
142-
# 4. Use production keys for live deployment (pk_live_, sk_live_)
143-
# 5. Use test keys for staging/development (pk_test_, sk_test_)
144-
# 6. Never commit actual API keys to your repository
188+
# 4. NEXT_PUBLIC_* vars are PUBLIC - visible in browser
189+
# 5. Never commit actual API keys to your repository
190+
#
191+
# See docs/NETLIFY_ENV_VARS.md for complete deployment guide

0 commit comments

Comments
Β (0)