# visit.waterschurch.org — Plan Your Visit landing page A focused, mobile-first advertising landing page for Waters Church that helps first-time visitors find their closest campus, know what to expect, and plan a visit. Built to deploy on the church's **cPanel/Apache** hosting as a static site with a small PHP API. ``` Ads (Facebook · Instagram · X · Google · TikTok) │ utm_* / gclid / fbclid / ttclid / twclid ▼ ┌──────────────────────────────┐ ┌────────────────────────────────────┐ │ Static site (Next.js export)│ JSON │ PHP API (public/api) │ │ hero · campus finder · │ ─────▶ │ validate → store lead (SQLite/MySQL)│ │ what to expect · kids · form│ │ → Mailchimp → Sinch Engage → retry │ └──────────────────────────────┘ └────────────────────────────────────┘ ``` ## Documentation | Document | Audience | | --- | --- | | [docs/SETUP.md](docs/SETUP.md) | Developers: run locally, test without sending messages, configure Mailchimp / Sinch / tracking, edit campus content | | [docs/DEPLOY-CPANEL.md](docs/DEPLOY-CPANEL.md) | Site administrator: create the subdomain, SSL, upload, private config, cron, updates | | [docs/LAUNCH-CHECKLIST.md](docs/LAUNCH-CHECKLIST.md) | Everyone: post-deployment verification and the list of items that need human/legal approval | | [.env.example](.env.example) | Every configuration key, with placeholders | | [config/campuses.json](config/campuses.json) | Campus names, addresses, service times, SMS numbers (single source of truth) | ## Quick start ```bash npm install cp .env.example .env # public build settings (safe to commit? no — .env is git-ignored) cp .env.example private/.env # local PHP API settings (INTEGRATION_MODE=mock) npm run dev # Next.js on http://localhost:3000 npm run dev:api # PHP API on http://127.0.0.1:8080 (needs PHP 8.1+ locally) ``` Point the frontend at the local API by setting `NEXT_PUBLIC_API_BASE=http://127.0.0.1:8080/api` in `.env` (and add `http://localhost:3000` to `ALLOWED_ORIGINS` in `private/.env`). Or preview the production build in one process (static files + PHP together): ```bash npm run build && php -S 127.0.0.1:8080 -t out ``` ## Scripts | Command | What it does | | --- | --- | | `npm run dev` | Next.js dev server | | `npm run dev:api` | PHP built-in server for the API (`public/`) | | `npm run build` | Optimize images → `next build` (static export) → post-build (`.htaccess`, campus config) → `out/` | | `npm run package` | Zip `out/` into `dist/` for upload through cPanel File Manager | | `npm test` | Vitest: distance, ZIP fallback, validation, consent, attribution, analytics, form flow (keyboard) | | `npm run test:php` | PHP suite: validation, Mailchimp/Sinch mapping, idempotency, partial failure + retry, HTTP end-to-end | | `npm run typecheck` / `npm run lint` | TypeScript and ESLint | | `npm run images` | Regenerate responsive AVIF/WebP/JPEG images from `assets/source` | ## Project layout ``` config/campuses.json campus data (read by TS and PHP) src/config/ site settings, campus loader, image manifest src/content/ copy, FAQs, kids info, consent text, testimonials src/components/ page sections (Hero, CampusFinder, PlanVisitForm, …) src/lib/ geo, attribution, analytics, schema, api client public/api/ PHP endpoints + lib (Mailchimp, Sinch, GeoIp, Geocode, LeadProcessor) public/api/cron/ retry-integrations.php, export-leads.php (CLI only) deploy/htaccess.root Apache config copied to out/.htaccess at build assets/source/ original logos/photos (see SOURCES.md) tests/ Vitest (TS) and tests/php (PHP) docs/ setup, deployment, launch checklist ``` ## Architecture decision (cPanel) The target host is cPanel on Apache (confirmed: `waterschurch.org:2083` answers, server header `Apache`). Whether the account offers the Node.js Application Manager could not be verified without logging in, so the build targets the lowest common denominator that every cPanel account supports: * **Frontend:** Next.js App Router + TypeScript + Tailwind, compiled with `output: "export"` to plain HTML/CSS/JS. No Node process runs in production. * **Backend:** PHP 8.1+ endpoints (cPanel ships PHP 8.x with cURL and PDO/SQLite). Secrets live in a `.env` file *outside* the document root. Leads are stored in SQLite (or cPanel MySQL) **before** Mailchimp/Sinch are called; failures are retried by a cPanel cron job. * **Location:** approximate server-side IP lookup (city-level, rounded, cached by hashed IP) for the recommendation; precise browser geolocation only on request; ZIP search always available. If Waters Church later confirms Node hosting, the frontend needs no change; the PHP layer could be swapped for route handlers, but there is no functional reason to. ## Source of truth: Gitea The repository lives at `Waters-Church/visit.waterschurch.org` on the church's Gitea (`ssh://git@chronicles-ab.waterschurch.org:3022/Waters-Church/visit.waterschurch.org.git`). Clone it to a normal local folder (for example `~/Sites/visit.waterschurch.org`); do not develop inside Google Drive, which fights with `node_modules` and build output. The original copy in the "Websites" shared drive is kept only as a snapshot and is no longer updated. ## Facts and placeholders Campus addresses, service times, phone numbers, kids age groups and safety practices were verified against waterschurch.org on 2026-09-22. Items that could **not** be verified are `null` in `config/campuses.json` (listed under each campus's `verify` array) or flagged `placeholder: true` / `confirm: true` in `src/content/`. Testimonials are intentionally empty. See [docs/LAUNCH-CHECKLIST.md](docs/LAUNCH-CHECKLIST.md).