Astro + React booth experience. Attendees scan a QR code on their phones, fill out a form at /form, and their pin drops live on the D3 world map displayed on the booth laptop. No refresh needed as the map polls for new submissions every 3 seconds.
| Route | Purpose | Who uses it |
|---|---|---|
/ |
Live world map dashboard | Booth laptop (always-on display) |
/form |
Feedback & registration form | Attendees on their phones (via QR) |
/admin |
Attendee table + CSV export | Staff only — not linked from the main UI |
pnpm install
pnpm devOpen http://localhost:4321.
Booth screen: http://localhost:4321/ — shows the live map with QR code pointing to /form.
Attendee form: http://localhost:4321/form — the mobile-optimised 3-step form. Works in any browser; scan the QR on the dashboard or open directly.
Admin panel: http://localhost:4321/admin — live attendee table with a one-click CSV export. Not linked anywhere in the main UI.
Submissions are saved to .data/attendees.json in the project root. The folder is auto-created on first submission and is gitignored. The map dashboard polls /api/attendees every 3 seconds and animates any new pins with a comet effect automatically — no manual refresh needed.
Go to http://localhost:4321/admin and click Export CSV, or hit the endpoint directly:
GET http://localhost:4321/api/attendees.csv
The CSV includes: id, created_at, first, last, email, title, company, country, host, products, devcon, feedback. Multi-select products are joined with ; .
| Path | What it is |
|---|---|
.data/attendees.json |
Local submission storage, created on first form submit |
.wrangler/ |
Cloudflare KV cache from wrangler dev — not needed for pnpm dev |
.astro/ |
Astro type-gen cache |
pnpm buildDeploys via the @astrojs/cloudflare adapter. Storage switches from .data/attendees.json to Cloudflare KV (configured in wrangler.toml). The pnpm-workspace.yaml file must stay — it enables the native build scripts for esbuild and workerd that the Cloudflare adapter needs.
src/
components/
App.tsx # mounts Dashboard (dashboard is the root view)
Dashboard.tsx # live map + attendee list + stats + QR code
FeedbackForm.tsx # 3-step form with animated transitions + success screen
AdminPanel.tsx # attendee table + CSV export (admin only)
WorldMap.tsx # D3 world map with animated pins + comet effect
lib/
countries.ts # country list with lat/lng/flag
storage.ts # JSON / KV storage abstraction
types.ts # shared TypeScript interfaces
pages/
index.astro # booth map display
form.astro # attendee-facing form page
admin.astro # staff admin page (not linked in main UI)
api/
attendees.ts # GET (list) + POST (submit)
attendees.csv.ts # GET — CSV export
countries.ts # GET — country list for form picker
styles/
global.css # all styles