# Omega Fire Ministries Conference Portal

A complete conference platform with a premium public website, registration, Stripe Checkout, verified payment webhooks, conference support, a protected admin portal, attendee and payment reporting, exports, and transactional email, SMS and official WhatsApp provider integrations.

## What is included

- Responsive public pages: Home, About, Register, Support, Confirmation, Privacy and Terms
- Durable relational database for events, admins, sessions, registrations, payments, support gifts, speakers, schedules, FAQs, messages, notes, webhooks and activity
- Free or paid registration, controlled by the event registration fee
- Stripe Checkout for paid registrations and conference support
- Signature-verified, idempotent Stripe webhook processing
- Explicit successful, pending, failed, cancelled and refunded payment states
- Secure password hashing, database-backed admin sessions and protected admin APIs
- Dashboard metrics, attendee/payment/support lists, search, filters and CSV export
- Communications composer and history for Resend email, Twilio SMS and official Meta WhatsApp Cloud API
- Responsive SaaS-style admin interface
- Sitemap, robots rules, metadata and semantic accessible forms

## 1. Requirements

- Node.js 22.13 or newer
- npm
- A Cloudflare D1 database when using the included Sites/Workers deployment
- A Stripe account
- Optional: Resend, Twilio and Meta WhatsApp Cloud API accounts

## 2. Install

```bash
npm ci
cp .env.example .env.local
```

Never commit `.env.local`. Put real credentials only in your server or hosting provider's environment settings.

## 3. Database setup

The relational schema is in `db/schema.ts`. Generated migrations are in `drizzle/`.

For the included Cloudflare deployment, bind a D1 database as `DB`, apply the generated migrations, and then run `scripts/seed.sql` once. The seed adds one editable conference, three sample ministers, initial schedule items and FAQs. It does not add fake registrations or fake payments.

To regenerate migrations after changing the schema:

```bash
npm run db:generate
```

Do not edit an already-applied production migration. Create a new migration.

## 4. Environment variables

Copy `.env.example` to `.env.local` and replace every placeholder you intend to use. The important values are:

- `PUBLIC_APP_URL`: Full HTTPS address of the portal
- `STRIPE_SECRET_KEY`: Stripe server secret, never a publishable key
- `STRIPE_WEBHOOK_SECRET`: Signing secret for this exact webhook endpoint
- `ADMIN_SETUP_TOKEN`: One-time high-entropy value for first-admin creation
- `RESEND_API_KEY` and `EMAIL_FROM`: Transactional email
- `TWILIO_ACCOUNT_SID`, `TWILIO_AUTH_TOKEN`, `TWILIO_FROM_NUMBER`: SMS
- `WHATSAPP_PHONE_NUMBER_ID`, `WHATSAPP_ACCESS_TOKEN`, `WHATSAPP_DEFAULT_TEMPLATE`: Official WhatsApp Cloud API

## 5. Stripe setup

1. Open Stripe Dashboard and enable test mode.
2. Copy the test secret key into `STRIPE_SECRET_KEY` on the server.
3. Keep registration free by leaving `registration_fee` at `0`, or set a fee in the event record.
4. Support gifts always use the supporter-selected amount.
5. Test with Stripe test cards before switching to live mode.

Card numbers are entered only on Stripe Checkout and are never sent to or stored by this application.

## 6. Stripe webhook

Create a Stripe webhook endpoint at:

`https://your-domain.org/api/stripe/webhook`

Subscribe to:

- `checkout.session.completed`
- `checkout.session.expired`
- `payment_intent.succeeded`
- `payment_intent.payment_failed`
- `payment_intent.canceled`
- `charge.refunded`

Copy the endpoint signing secret to `STRIPE_WEBHOOK_SECRET`. The handler rejects invalid/old signatures and records processed event IDs so duplicate delivery cannot duplicate payment effects. A success-page visit never marks a payment successful.

## 7. Email

Create a Resend API key, verify your sending domain, set `RESEND_API_KEY`, and use a verified address in `EMAIL_FROM`. The branded HTML wrapper is in `lib/server.ts`. The Communications screen stores provider IDs, delivery state and errors.

## 8. SMS

Create a Twilio account and approved sending number. Set the three `TWILIO_*` variables. Use full international recipient numbers, for example `+234...` or `+1...`.

## 9. WhatsApp

Use only Meta WhatsApp Cloud API. Create and approve a conference message template, then set the three `WHATSAPP_*` variables. The portal sends the configured approved template. It does not use WhatsApp Web, scraping or unofficial automation.

## 10. Create the first administrator

1. Generate a long random `ADMIN_SETUP_TOKEN` and add it to the server environment.
2. Apply migrations before visiting the admin portal.
3. Open `/admin/login`.
4. Expand “First administrator setup”.
5. Enter your name, email, a password of at least 12 characters and the one-time setup token.
6. After the account is created, remove `ADMIN_SETUP_TOKEN` from the production environment.

There is no default admin password. Passwords use PBKDF2-SHA256 with a unique salt and 210,000 iterations. Sessions are server-side, time-limited, HttpOnly, Secure and SameSite Strict.

## 11. Run locally

```bash
npm run dev
```

The application expects a D1-compatible `DB` binding. Use the hosting platform's local D1 configuration when testing database workflows.

## 12. Production build and checks

```bash
npm run build
npm run lint
npm test
```

## 13. Deploy

The included configuration targets Cloudflare Workers through ChatGPT Sites. It includes a logical D1 binding named `DB`. For another Cloudflare account, create the D1 database, map the binding, add environment secrets, apply migrations, seed once, build and deploy.

If moving to a conventional Node server in Claude Code, retain the domain model and API behavior, replace the D1 adapter with PostgreSQL/Prisma, and preserve the webhook signature and idempotency rules.

## 14. Change conference information

Initial conference content is in `scripts/seed.sql`. The primary event database record controls the name, theme, description, dates, venue, currency, fee, registration state, deadline, contact details, registration prefix and suggested support amounts. The public marketing copy is in `app/page.tsx` and `app/about/page.tsx`.

## 15. Change branding

Shared colors, typography, spacing, cards and responsive rules are in `app/globals.css`. Main tokens are at the top: `--red`, `--deep`, `--ink`, `--cream`, `--gold` and `--line`.

## 16. Replace images

Replace `public/hero-conference.png` with an optimized landscape image using the same filename, or update `.hero-image` in `app/globals.css`. Keep a dark enough left side for readable hero text. Speaker image URLs are stored in the `speakers` table.

## 17. Security checklist

- Use HTTPS in production.
- Never commit secrets or live credentials.
- Remove the admin setup token after first use.
- Keep dependencies and the runtime patched.
- Restrict database access to the application.
- Verify Stripe live and test webhook secrets separately.
- Use official provider APIs only.
- Publish an accurate privacy policy and retention policy for your jurisdiction.
- Back up the database and test restoration.
- Apply rate limiting at the edge for registration, support, login and message endpoints.
- Review administrators regularly and disable unused accounts.

## Project structure

- `app/`: Pages and server API routes
- `components/`: Public and admin UI
- `db/`: Relational schema and database access
- `drizzle/`: Generated database migrations
- `lib/server.ts`: Security, Stripe and communication provider services
- `scripts/seed.sql`: Removable initial content
- `public/`: Brand and conference assets

## Payment and message states

Payments preserve `pending`, `successful`, `failed`, `cancelled` and `refunded`. Communications preserve queued/sending, sent and failed states with provider references and errors. Admin lists and exports read directly from the database.
