Skip to content

Repository files navigation

Conference Pulse

Conference Pulse is a live companion website for Campaign Lab’s AI & Campaigning Conference on 16 July 2026 at Newspeak House, London.

It gives everyone in the room one simple place to follow the day, share reactions, and vote. The organiser runs the event from a private dashboard, while a separate big-screen view shows the room’s live response.

What people can do

Attendees open the website from a QR code. They can:

  • See the day’s schedule and which panel is live.
  • Add short anonymous comments during each panel.
  • Read a few AI-assisted “live takes” drawn from the room’s comments.
  • Vote at the end of each panel: Just Hype, Could be useful, with work, or Already useful & real.
  • Send private feedback to the organisers.
  • Join Campaign Lab’s mailing list with clear consent.

The projector shows the latest comments, live takes, and voting result. At the end of the conference, it can show the full day’s results on one board.

The important links

Replace your-domain with the Vercel address for the deployed app.

Link Who it is for
https://your-domain/ Attendees: schedule and live panel
https://your-domain/join Attendees: join Campaign Lab
https://your-domain/screen Projector: current panel and room response
https://your-domain/screen/day Projector: full-day results
https://your-domain/admin Organiser: event controls
https://your-domain/api/health Quick check that the app and database are working

Only the attendee homepage should appear in the printed QR code. Keep the organiser and projector links private.

How to run the event

Before people arrive

  1. Open /api/health. It should say "status":"ok" and "database":"ready".
  2. Sign into /admin with the organiser passphrase.
  3. Check the panel titles, speakers, and timings under Panel content.
  4. Open /screen on the projector and put the browser into full-screen mode.
  5. Test one comment and one vote from a phone.

For each panel

  1. In /admin, open Live room and select the panel that is starting.
  2. Leave voting closed during the discussion. Comments can come in throughout.
  3. Remove any unsuitable projected comment using the moderation controls.
  4. In the final minute, press Open voting.
  5. When the chair calls time, press Close voting.

For the conference close, open /screen/day to show every panel’s result.

After the event

  1. Open /adminPrivate data.
  2. Download the signup and feedback export.
  3. Import it into Campaign Lab’s normal system and verify the record count.
  4. Delete the private data from Conference Pulse.

Before the event, organisers can also use Private data → Clear all test activity to reset comments, votes, live takes, feedback, and signups without changing the conference programme.

The app also removes signup and feedback records automatically after 30 days. The fuller checklist and fallback plan are in the event runbook.

How it is built

Conference Pulse deliberately uses a small, conventional setup:

  • Next.js provides the website and server endpoints.
  • Vercel hosts the application in London.
  • Neon Postgres stores panels, comments, votes, feedback, and signups.
  • Anthropic can optionally summarise comments into short live takes.
  • Ordinary browser polling refreshes the screens every few seconds; there is no separate realtime service.

Everything is in this one repository. There is no separate backend project, queue, WebSocket server, or complicated permissions system. Coding agents should read AGENTS.md before changing the application.

Setting up a deployment

1. Deploy the repository

Import this repository into Vercel as a Next.js project. The app is at the repository root, so leave Root Directory blank.

2. Create the database

Create a Neon Postgres project in AWS Europe (London). Add its pooled connection string to Vercel as DATABASE_URL.

Open Neon’s SQL Editor and run the complete setup script at migrations/001_initial.sql. It creates the tables and loads the conference programme. It is safe to run more than once.

3. Add the private settings

Add these under Vercel → Project → Settings → Environment Variables and apply them to Production:

Name What to enter
DATABASE_URL Neon’s pooled connection string
ORGANIZER_PASSPHRASE A long passphrase chosen for the event
SESSION_SECRET A random secret, different from the others
DEVICE_HASH_SECRET Another random secret
CRON_SECRET Another random secret
ANTHROPIC_API_KEY Optional: Campaign Lab’s Anthropic API key
ANTHROPIC_MODEL Optional; defaults to claude-sonnet-4-6

Generate each random secret with openssl rand -hex 32, or use a password manager’s random generator. Store the organiser passphrase in Campaign Lab’s password manager and do not reuse it elsewhere.

Environment-variable changes only affect new deployments, so redeploy after adding or changing them.

Editing the conference programme

Routine changes do not require code:

  1. Sign into /admin.
  2. Open Panel content.
  3. Choose a panel, edit it, and save.
  4. Publish it when its information is final.

Panel 4 begins as an unpublished draft because its briefing was incomplete. Panel 3’s second speaker is also marked TBC.

Privacy and safeguards

  • Signup email addresses and private feedback are never available through public endpoints.
  • Every signup records the consent wording and time shown to that person.
  • Comments are anonymous and do not store a device identifier.
  • Each device can vote once per panel, while the organiser controls when voting is open.
  • Exports are protected against spreadsheet-formula injection.
  • Export and deletion actions are recorded without copying personal data into the audit log.
  • If the AI service fails, comments and voting continue normally and the previous live takes remain visible.

This is appropriate integrity for a friendly conference vote, not identity verification. Someone who deliberately clears their browser storage can receive a new device identity.

Working on the code

Requirements: Node.js 20+ and a Postgres database.

npm install
cp .env.example .env.local
npm run db:migrate
npm run dev

Before pushing a change:

npm test
npm run lint
npm run build

There is intentionally no pretend in-memory database. Local and deployed versions use the same Postgres behaviour, so a missing database connection fails honestly.

Reference material