# ---- Core ---- NODE_ENV=development NEXT_PUBLIC_APP_URL=http://localhost:3000 # ---- Database (Postgres 16 + PostGIS) ---- DATABASE_URL=postgresql://linkder:linkder@localhost:5442/linkder # Managed Postgres only. Verifies the server's IDENTITY, not merely that the # link is encrypted — sslmode=require alone leaves you open to anything that can # answer for the hostname. Takes a path to the provider's .crt, or the PEM # inline for a platform whose secrets are environment variables. DATABASE_CA_CERT= # ---- Redis (pub/sub for SSE chat + BullMQ queues) ---- REDIS_URL=redis://localhost:6389 # ---- Auth.js v5 ---- # generate with: openssl rand -base64 32 AUTH_SECRET= AUTH_URL=http://localhost:3000 # Social sign-in. Each provider is optional and independent — leave a pair # blank and phone OTP still works. The buttons render either way and tell the # user when a provider is not set up, so the screen never changes shape between # environments. Set BOTH values of a pair or neither: a half-set pair is treated # as unset (see lib/auth.ts). # # Authorised redirect URI: {NEXT_PUBLIC_APP_URL}/api/auth/callback/google AUTH_GOOGLE_ID= AUTH_GOOGLE_SECRET= # Microsoft Entra ID (Azure AD). Register an app at # https://entra.microsoft.com > App registrations, add a Web platform with # redirect URI {NEXT_PUBLIC_APP_URL}/api/auth/callback/microsoft, then create a # client secret under Certificates & secrets. # # TENANT_ID decides WHO may sign in and defaults to `common`: # common work, school and personal Microsoft accounts # organizations work and school only # consumers personal only # one organisation only # For a consumer marketplace `common` is almost always what you want — set the # app registration's supported account types to match, or sign-in fails at # Microsoft's end with AADSTS50194 no matter what is set here. AUTH_MICROSOFT_ID= AUTH_MICROSOFT_SECRET= AUTH_MICROSOFT_TENANT_ID=common # GitHub. Create an OAuth app at # https://github.com/settings/developers > New OAuth App, with # Authorization callback URL {NEXT_PUBLIC_APP_URL}/api/auth/callback/github. # # GitHub only returns a primary email if the OAuth app requests `user:email` # AND the account has a verified one; a user whose email is private signs up # with no address, so never assume `users.email` is reachable mail — gate # outbound on isSyntheticEmail() from @linkdr/shared, same as phone signups. AUTH_GITHUB_ID= AUTH_GITHUB_SECRET= # ---- Geocoding (Mapbox) ---- # Turns a typed address into the coordinates the deck matches on. Without it, # every job and every pro base falls back to the city centre and is stored with # location_precision='city' — honest, but unmatched: ST_Distance measures a # constant and ST_DWithin passes everyone. # # The token MUST be entitled for PERMANENT geocoding. We store the coordinates # indefinitely because they are the matching primitive, and Mapbox's temporary # endpoint forbids persistence — every request sets permanent=true, so a token # without that entitlement returns 401/403 rather than silently working. MAPBOX_TOKEN= # ISO 3166-1 alpha-2. Bounds results to one country: "Carrer de Sants" matches # in several places and the wrong continent is a worse answer than none. MAPBOX_COUNTRY=mx # ---- Phone OTP (Twilio Verify) ---- TWILIO_ACCOUNT_SID= TWILIO_AUTH_TOKEN= TWILIO_VERIFY_SERVICE_SID= # ---- Stripe Connect ---- STRIPE_SECRET_KEY= STRIPE_WEBHOOK_SECRET= NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY= # Platform commission in basis points (1500 = 15%) PLATFORM_FEE_BPS=1500 # ---- Didit (ID verification) ---- DIDIT_API_KEY= DIDIT_WORKFLOW_ID= DIDIT_WEBHOOK_SECRET= # ---- Resend (transactional email) ---- RESEND_API_KEY= EMAIL_FROM=noreply@linkdr.app # ---- Launch market (city-scoped MVP) ---- NEXT_PUBLIC_CITY_NAME=Ciudad de México NEXT_PUBLIC_CITY_LAT=19.4326 NEXT_PUBLIC_CITY_LNG=-99.1332 TWILIO_FROM_NUMBER= # Dev-only fixed login (+34600000000 / code 000000). MUST stay false/unset in production. ALLOW_DEV_LOGIN=false # Bugsink (Sentry-compatible error tracking). Write-only ingest key, safe in the # client bundle. Leave blank to disable reporting entirely. NEXT_PUBLIC_SENTRY_DSN= # ---- Object storage (DigitalOcean Spaces) ---- SPACES_REGION=nyc3 SPACES_BUCKET= SPACES_KEY= SPACES_SECRET= SPACES_CDN_URL=