Next.js 16 static export + PHP 8 API for cPanel/Apache hosting. - Location-aware campus finder (IP estimate, optional precise location, ZIP search) - Three-step Plan Your Visit form with separate email/SMS consent - PHP API: validation, anti-spam, rate limiting, SQLite lead store, Mailchimp and Sinch Engage adapters, idempotent retries via cron - Attribution capture (utm_*, gclid/gbraid/wbraid, fbclid, ttclid, twclid) and consent-aware analytics hooks - Vitest and PHP test suites, cPanel deployment script and docs Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
111 lines
5.1 KiB
Bash
111 lines
5.1 KiB
Bash
# =============================================================================
|
|
# visit.waterschurch.org — environment configuration (PLACEHOLDERS ONLY)
|
|
#
|
|
# Two consumers read this file format:
|
|
# 1. `npm run build` (Next.js) reads NEXT_PUBLIC_* from ./.env at build time.
|
|
# These values are embedded in the static HTML/JS — never put secrets here.
|
|
# 2. The PHP API reads EVERYTHING ELSE at runtime from
|
|
# <VISIT_PRIVATE_DIR>/.env on the server (outside the web root).
|
|
# Copy this file there as `.env` and fill in real values.
|
|
# =============================================================================
|
|
|
|
# ---- Public site ------------------------------------------------------------
|
|
NEXT_PUBLIC_SITE_URL=https://visit.waterschurch.org
|
|
PUBLIC_SITE_URL=https://visit.waterschurch.org
|
|
# Comma-separated extra origins allowed to call the API (local dev only)
|
|
ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000
|
|
# true = search engines may index. Set false on staging.
|
|
NEXT_PUBLIC_ROBOTS_INDEX=true
|
|
# Where the browser calls the API. Same-origin "/api" in production; php -S in dev.
|
|
NEXT_PUBLIC_API_BASE=/api
|
|
# Default landing-page variant label (override per ad with ?v=b)
|
|
NEXT_PUBLIC_VARIANT=a
|
|
# Legal pages
|
|
NEXT_PUBLIC_PRIVACY_URL=https://waterschurch.org/privacy/
|
|
NEXT_PUBLIC_TERMS_URL=
|
|
# "Text Us" number before a campus is chosen (must be SMS-enabled on the Sinch account)
|
|
NEXT_PUBLIC_CENTRAL_SMS_NUMBER=+15086951300
|
|
|
|
# ---- Integration mode -------------------------------------------------------
|
|
# mock = log what WOULD be sent, send nothing (default). live = real Mailchimp + Sinch calls.
|
|
INTEGRATION_MODE=mock
|
|
LOG_LEVEL=info
|
|
# Random string used to hash IPs for rate limiting / consent records. Generate: openssl rand -hex 32
|
|
HASH_SALT=change-me-to-a-long-random-string
|
|
# Set true ONLY if the site is behind Cloudflare or another trusted proxy
|
|
TRUST_PROXY_HEADERS=false
|
|
|
|
# ---- Lead storage -----------------------------------------------------------
|
|
# Default: SQLite at <VISIT_PRIVATE_DIR>/data/leads.sqlite (no setup needed).
|
|
# To use cPanel MySQL instead, create a database + user in cPanel and set:
|
|
DATABASE_DSN=
|
|
# e.g. mysql:host=localhost;dbname=cpaneluser_visit;charset=utf8mb4
|
|
DATABASE_USER=
|
|
DATABASE_PASSWORD=
|
|
# Override the data directory (must be writable by PHP and outside the web root)
|
|
DATA_DIR=
|
|
# Delete fully-processed leads older than N days (0 = keep forever). Confirm with Waters Church.
|
|
LEAD_RETENTION_DAYS=0
|
|
|
|
# ---- Mailchimp --------------------------------------------------------------
|
|
# Account → Extras → API keys. The key ends in "-usXX"; that suffix is the server prefix.
|
|
MAILCHIMP_API_KEY=
|
|
MAILCHIMP_SERVER_PREFIX=us21
|
|
# Audience → Settings → Audience name and defaults → "Audience ID"
|
|
MAILCHIMP_AUDIENCE_ID=
|
|
# Optional: API-triggered Customer Journey (Automations → journey → API trigger step)
|
|
MAILCHIMP_JOURNEY_ID=
|
|
MAILCHIMP_JOURNEY_STEP_ID=
|
|
# Tag prefix applied to every contact from this page
|
|
MAILCHIMP_TAG_PREFIX=Visit:
|
|
# true = new contacts start as "pending" and receive a Mailchimp confirmation email
|
|
MAILCHIMP_DOUBLE_OPTIN=false
|
|
|
|
# ---- Sinch Engage (formerly MessageMedia) -----------------------------------
|
|
# Sinch Engage portal → Settings → API credentials (Basic auth key + secret).
|
|
# Regional host: US https://us.app.api.sinch.com | EU https://eu.app.api.sinch.com | APAC https://au.app.api.sinch.com
|
|
SINCH_API_BASE=https://us.app.api.sinch.com
|
|
SINCH_API_KEY=
|
|
SINCH_API_SECRET=
|
|
# Send from each campus's own number/sub-account (config/campuses.json). Recommended.
|
|
SINCH_USE_CAMPUS_NUMBERS=true
|
|
SINCH_USE_CAMPUS_SUBACCOUNTS=true
|
|
# Fallback sender when a campus has no number (must be a 10DLC/toll-free number on the parent account)
|
|
SINCH_DEFAULT_SOURCE_NUMBER=+17746436322
|
|
# Fallback sub-account (leave blank to send as the parent account)
|
|
SINCH_ACCOUNT_ID=
|
|
# Optional staff heads-up text for every new lead (no visitor PII beyond first name)
|
|
SINCH_INTERNAL_NOTIFY_NUMBER=
|
|
# Optional override of the confirmation template. Placeholders: {{first_name}} {{campus_name}} {{service_or_date}} {{address}}
|
|
SINCH_CONFIRMATION_TEMPLATE=
|
|
|
|
# ---- Location services ------------------------------------------------------
|
|
# Approximate IP geolocation: none | header | ipapi_co | ipinfo | ip_api_com
|
|
GEOIP_PROVIDER=ipapi_co
|
|
GEOIP_API_KEY=
|
|
GEOIP_CACHE_TTL=3600
|
|
# ZIP lookup: zippopotam | nominatim | google
|
|
GEOCODE_PROVIDER=zippopotam
|
|
GEOCODE_API_KEY=
|
|
# Local testing helpers (never enable in production)
|
|
DEBUG_GEO=false
|
|
|
|
# ---- Anti-spam ----------------------------------------------------------------
|
|
# Optional Cloudflare Turnstile (free). Leave blank to rely on honeypot + timing + rate limits.
|
|
NEXT_PUBLIC_TURNSTILE_SITE_KEY=
|
|
TURNSTILE_SECRET_KEY=
|
|
MIN_FORM_SECONDS=3
|
|
RATE_LIMIT_SUBMIT_PER_10MIN=5
|
|
RATE_LIMIT_SUBMIT_PER_DAY=60
|
|
RETRY_BATCH_SIZE=25
|
|
|
|
# ---- Analytics & advertising (all optional; nothing loads when blank) -------
|
|
# implied = fire immediately (typical US ad landing page); opt-in = show a consent prompt first
|
|
NEXT_PUBLIC_ANALYTICS_CONSENT_MODE=implied
|
|
NEXT_PUBLIC_GTM_ID=
|
|
NEXT_PUBLIC_GA4_ID=
|
|
NEXT_PUBLIC_META_PIXEL_ID=
|
|
NEXT_PUBLIC_TIKTOK_PIXEL_ID=
|
|
# Google Ads conversion "send_to" value, e.g. AW-123456789/AbC-D_efG-h12_34-567
|
|
NEXT_PUBLIC_GADS_CONVERSION=
|