Notes still only attach to tagged versions, so they can be written ahead of a release or corrected afterwards without tagging a new version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cross Events Hub
Joshua's central management app for every Cross Events install: customers, licences, install health and usage, and alerts. Customers never log in here.
Naming: Cross Events was called Hope Events until October 2026. Older commits, the
hope-eventsrepo name and thehel1.licence-token prefix still use the old name. The prefix is part of the protocol, so it stays.
backend/— Express + Prisma (Postgres) API, port 5200frontend/— Next.js dashboard, port 3200docs/hub-protocol.md— the contract with Cross Events installs (a copy lives in thehope-eventsrepo; change both together)
Installs only ever call the Hub (register, heartbeat); the Hub never reaches into an install and holds no church data — just versions, health and aggregate counts.
Run it locally
Needs Node 20+ and Postgres.
cd backend
cp .env.example .env # set DATABASE_URL, JWT_SECRET, HUB_ENCRYPTION_KEY
npm install
npx prisma migrate deploy && npx prisma generate
npm run generate-keys # licence signing key → keys/hub-signing-key.pem
npm run create-admin -- --email you@example.com --name "Your Name"
npm run dev # http://localhost:5200
cd ../frontend
cp .env.example .env.local # NEXT_PUBLIC_API_URL=http://localhost:5200
npm install
npm run dev # http://localhost:3200
The first login sets up two-factor with an authenticator app (required).
To try it with Cross Events locally, point the install at the Hub with HUB_URL=http://localhost:5200
and HUB_PUBLIC_KEY (the public key shown in Hub → Settings) in Cross Events' backend/.env.
Releases and notices
- Releases come from git: every
v1.2.3tag ofjoshua/hope-eventsis a release, the newest is the latest version, and the notes churches see come fromWHATS-NEW.mdon that repo's default branch (only for tagged versions, so notes can be written ahead or corrected later). The Hub checks every 15 minutes (and on Sync now, Releases page). So releasing Cross Events is: write the version's section inWHATS-NEW.md, tag, push — installs see the update with their next heartbeat. - Notices (Notices page) are banners on churches' sites for their admins and supervisors, emails to them, or both — e.g. planned maintenance.
The licence signing key
Licences are tokens signed with an Ed25519 key. The private key exists only on the Hub server;
installs check licences with the public key, which is built into Cross Events
(backend/src/hub/publicKey.js).
- Create the production key once, on the Hub server:
npm run generate-keys. Back upkeys/hub-signing-key.pemsomewhere safe and offline. - Put the public key it prints into Cross Events (
backend/src/hub/publicKey.js) and release. - Losing or replacing the key means every install needs a Cross Events update with the new public key before it can trust new licences — so don't.
HUB_ENCRYPTION_KEYencrypts install secrets: it must never change after installs register.
Deploying
Same pattern as Cross Events: on the server (events-hub.crosscode.co.za), behind nginx with
HTTPS, two PM2 processes (backend: npm start; frontend: npm run build && npm start),
TRUST_PROXY=1, FRONTEND_URL=https://events-hub.crosscode.co.za, and the frontend's
NEXT_PUBLIC_API_URL set to the public API address (e.g. https://events-hub.crosscode.co.za
with nginx routing /api to port 5200). Back up the database daily, plus the signing key.
Tests
cd backend && npm test — encryption, licence tokens, request signatures, two-factor codes
(RFC 6238 vector) and alert rules.