Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 152 additions & 54 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,96 +1,194 @@
# Database
# For local development, use SQLite:
# DATABASE_URL="file:./dev.db"
# For production, use PostgreSQL (Vercel Postgres, Railway, Supabase, etc.):
# =============================================================================
# Vets Who Code — environment variables
#
# Copy to .env.local for local development. Never commit real values.
# Every variable below is read by the running app, a config file, or a
# generator script — the consuming file(s) are noted per variable.
#
# "Required" means core app/auth breaks without it. Feature-scoped variables
# are required only when that feature is exercised.
#
# NODE_ENV and CI are also read (next.config.js, postcss.config.js,
# playwright.config.ts, src/lib/prisma.ts) but are set by Node/Next/CI
# tooling — do not set them here.
# =============================================================================

# --- Database ----------------------------------------------------------------

# Required | Secret | prisma/schema.prisma, src/pages/api/health.ts
# Local development can use SQLite: DATABASE_URL="file:./dev.db"
DATABASE_URL="postgresql://username:password@hostname:port/database"

# LMS Development Access - Set to 'true' to bypass auth in development ONLY
# WARNING: Never enable in production!
LMS_DEV_BYPASS=false
# --- NextAuth / GitHub -------------------------------------------------------

# NextAuth.js
# Required | Secret | src/pages/api/auth/options.ts, src/pages/api/health.ts,
# playwright.config.ts (test fallback)
NEXTAUTH_SECRET="your-secret-key-here"

# Required | Not secret | read internally by NextAuth, checked by
# src/pages/api/health.ts (Vercel sets this automatically in deployments)
NEXTAUTH_URL="http://localhost:3000"

# GitHub OAuth (for authentication)
# Required | Not secret | src/pages/api/auth/options.ts
GITHUB_CLIENT_ID="your-github-client-id"

# Required | Secret | src/pages/api/auth/options.ts
GITHUB_CLIENT_SECRET="your-github-client-secret"

# GitHub API Access (for fetching org data, repos, etc.)
GITHUB_PAT="your-github-personal-access-token"
GITHUB_TOKEN="your-github-token"
# Required | Not secret | src/pages/api/auth/options.ts — sign-in is gated on
# membership in this GitHub org
GITHUB_ORG="Vets-Who-Code"

# Admin allowlist — comma-separated GitHub usernames that bypass org-membership
# check on sign-in. Keep this list minimal (founders/external admins only).
# Optional | Secret | src/lib/git-api-client.ts — GitHub API reads (org data,
# repos, PRs); requests may fail without it
GITHUB_TOKEN="your-github-token"

# Optional | Not secret | src/pages/api/auth/options.ts — comma-separated
# GitHub usernames that bypass the org-membership check on sign-in. Keep this
# list minimal (founders/external admins only).
ADMIN_GITHUB_LOGINS=""

# Dev-only escape hatch. Set to "true" ONLY when running locally with
# NODE_ENV=development to allow any GitHub user to sign in. NEVER set in
# production or preview deployments.
# Optional, dev-only | Not secret | src/pages/api/auth/options.ts — set "true"
# ONLY when running locally with NODE_ENV=development to allow any GitHub user
# to sign in. NEVER set in production or preview deployments.
ALLOW_ANY_GITHUB_USER="false"

# Google Maps API (for location features)
NEXT_PUBLIC_GOOGLE_MAPS_KEY="your-google-maps-api-key"
# --- AI providers ------------------------------------------------------------
# src/lib/ai-provider.ts picks the first configured provider (gemini | azure |
# openai | phi3). Configure at least one for AI features.

# Optional: Other OAuth providers
# GOOGLE_CLIENT_ID="your-google-client-id"
# GOOGLE_CLIENT_SECRET="your-google-client-secret"

# AI Teaching Assistant (J0d!e) - Phase 5
# Primary AI provider: gemini | azure | openai | phi3
# Optional | Not secret | src/lib/ai-provider.ts — force a provider instead of
# auto-detection
PRIMARY_AI_PROVIDER="gemini"

# Google Gemini (recommended for cost-effectiveness)
# Optional* | Secret | src/lib/ai-provider.ts,
# src/pages/api/api-helpers/classify-contact.ts, scripts/generate-*.ts
# (*one Gemini key — this or GEMINI_API_KEY — is needed for Gemini features)
GOOGLE_GENERATIVE_AI_API_KEY="your-google-ai-api-key"

# Contact Form Spam Filter (Gemini)
# Optional* | Secret | same consumers as GOOGLE_GENERATIVE_AI_API_KEY
GEMINI_API_KEY="your-gemini-api-key"

# Optional | Not secret | src/pages/api/api-helpers/classify-contact.ts —
# contact-form spam-filter model (has a default in code)
GEMINI_MODEL="gemini-2.5-flash"

# Azure OpenAI (GPT-4)
# Optional | Secret | src/lib/ai-provider.ts
AZURE_OPENAI_API_KEY="your-azure-openai-key"
# Optional | Not secret | src/lib/ai-provider.ts
AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com"
# Optional | Not secret | src/lib/ai-provider.ts
AZURE_OPENAI_DEPLOYMENT="your-gpt4-deployment-name"

# OpenAI (GPT-4)
# Optional | Secret | src/lib/ai-provider.ts
OPENAI_API_KEY="your-openai-api-key"

# Phi-3 (optional - for local/Azure AI Studio deployment)
# Optional | Not secret | src/lib/ai-provider.ts
PHI3_ENDPOINT="your-phi3-endpoint"
# Optional | Secret | src/lib/ai-provider.ts
PHI3_API_KEY="your-phi3-api-key"

# Lightcast (Emsi) - labor market data: salary by SOC, demand, top skills
# Both required for live data; without these, scripts fall back to Census/curated.
# Used by: src/lib/lightcast-client.ts, scripts/generate-tech-pathways.ts
LIGHTCAST_CLIENT_ID="your-lightcast-client-id"
LIGHTCAST_CLIENT_SECRET="your-lightcast-client-secret"
# --- J0dI3 AI backend --------------------------------------------------------
# Server-side only — never prefix with NEXT_PUBLIC_.

# US Census ACS - fallback salary data when Lightcast is unavailable
CENSUS_API_KEY="your-census-api-key"
# Required for J0dI3 features | Not secret | src/lib/j0di3-client.ts
J0DI3_API_URL=
# Required for J0dI3 features | Secret | src/lib/j0di3-client.ts
J0DI3_API_KEY=

# Shopify Storefront API (for browsing products/cart)
SHOPIFY_STORE_DOMAIN="your-store.myshopify.com"
SHOPIFY_STOREFRONT_ACCESS_TOKEN="your-storefront-access-token"
# --- Cloudinary --------------------------------------------------------------

# Shopify Admin API (optional - for making API calls to Shopify)
SHOPIFY_ADMIN_ACCESS_TOKEN="your-admin-access-token"
# Required for media | Public (client bundle) | src/lib/cloudinary.ts,
# src/lib/cloudinary-helpers.ts, src/lib/blog.ts,
# src/pages/api/upload/signature.ts, scripts/
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME="your-cloud-name"

# Shopify Webhook/API Secrets (REQUIRED for order webhooks - the API Secret Key from API credentials)
# The webhook handler will check for any of these names:
SHOPIFY_WEBHOOK_SECRET="your-webhook-secret" # Primary option
SHOPIFY_API_SECRET="your-api-secret-key" # Alternative name
SHOPIFY_CLIENT_SECRET="your-client-secret" # Alternative name
# Required for LMS media | Not secret | src/pages/api/lms/progress/index.ts,
# src/pages/api/lms/certificates/generate.ts — same value as above, read
# without the NEXT_PUBLIC_ prefix server-side
CLOUDINARY_CLOUD_NAME="your-cloud-name"

# Cloudinary (for image uploads and management)
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME="your-cloud-name"
# Required for media | Not secret | src/lib/cloudinary.ts,
# src/pages/api/upload/signature.ts, src/pages/api/lms/*, scripts/
CLOUDINARY_API_KEY="your-api-key"

# Required for media | Secret | same consumers as CLOUDINARY_API_KEY
CLOUDINARY_API_SECRET="your-api-secret"

# Email Service (Resend - for sending certificate emails)
# --- Email (Resend) ----------------------------------------------------------

# Required for email features | Secret | src/lib/email.ts
RESEND_API_KEY="your-resend-api-key"
EMAIL_FROM="noreply@vetswhocode.io" # Optional: Custom from address (requires domain verification)

# J0dI3 AI Backend (server-side only — never prefix with NEXT_PUBLIC_)
J0DI3_API_URL=
J0DI3_API_KEY=
# Optional | Not secret | src/lib/email.ts — defaults to noreply@vetswhocode.io
# (custom address requires domain verification in Resend)
EMAIL_FROM="noreply@vetswhocode.io"

# --- Shopify -----------------------------------------------------------------

# Required for store | Not secret | src/lib/shopify.ts, playwright.config.ts
SHOPIFY_STORE_DOMAIN="your-store.myshopify.com"

# Required for store | Secret | src/lib/shopify.ts, playwright.config.ts
SHOPIFY_STOREFRONT_ACCESS_TOKEN="your-storefront-access-token"

# Required for order webhooks | Secret |
# src/pages/api/shopify/webhooks/orders/create.ts — the handler accepts any
# one of these three names; set whichever matches your credential naming
SHOPIFY_WEBHOOK_SECRET="your-webhook-secret"
SHOPIFY_API_SECRET="your-api-secret-key"
SHOPIFY_CLIENT_SECRET="your-client-secret"

# --- Slack form webhooks -----------------------------------------------------
# Path segment after https://hooks.slack.com/services/ for each form.

# Required for contact form | Secret | src/pages/api/contact.ts
CONTACT_WEBHOOK_ID=""
# Required for application form | Secret | src/pages/api/apply.ts
APPLY_WEBHOOK_ID=""
# Required for mentor/mentee forms | Secret | src/pages/api/mentor.ts,
# src/pages/api/mentee.ts
MENTOR_WEBHOOK_ID=""

# --- Mailchimp (newsletter) --------------------------------------------------

# Required for newsletter signup | Secret | src/pages/api/newsletter.ts
MAILCHIMP_API_KEY="your-mailchimp-api-key"
# Required for newsletter signup | Not secret | src/pages/api/newsletter.ts
MAILCHIMP_LIST_ID="your-mailchimp-list-id"

# --- Labor market data -------------------------------------------------------

# Optional | Secret | src/lib/lightcast-client.ts,
# scripts/generate-tech-pathways.ts — both needed for live Lightcast data;
# without them, code falls back to Census/curated data
LIGHTCAST_CLIENT_ID="your-lightcast-client-id"
LIGHTCAST_CLIENT_SECRET="your-lightcast-client-secret"

# Optional | Secret | src/lib/census-client.ts — fallback salary data when
# Lightcast is unavailable
CENSUS_API_KEY="your-census-api-key"

# --- Maps, analytics, site ---------------------------------------------------

# Required for map components | Public (client bundle) |
# src/components/ui/google-map/index.tsx
NEXT_PUBLIC_GOOGLE_MAPS_KEY="your-google-maps-api-key"

# Optional | Public (client bundle) | src/pages/_document.tsx — Google
# Analytics loads only when set
NEXT_PUBLIC_GOOGLE_ANALYTICS_ID=""

# Optional | Public | next-sitemap.config.js — defaults to
# https://vetswhocode.io
NEXT_PUBLIC_SITE_URL="https://vetswhocode.io"

# --- Content generator scripts (npm run generate:*) --------------------------

# Optional | Secret | scripts/generate-*.ts — legacy-named fallback Gemini API
# key, read when GEMINI_API_KEY is unset
GOOGLE_PRIVATE_KEY=""

# Optional | Not secret | scripts/generate-tech-pathways.ts — Gemini model
# override for the tech-pathways generator
TECH_PATHWAYS_MODEL=""
Loading