Inspiration

Google Maps tells you what's there. It doesn't tell you what's good right now, or what actually fits the mood you're in tonight. Event listings are just as static — a page full of things that are technically happening, with no sense of which one is actually buzzing versus which one is a ghost town. We wanted a map that felt alive: one where the city's real energy — driven by real people, not stale listings — was the whole point.

What it does

Pulse is a live map of Sydney where suburbs glow and event pins brighten based on real-time check-ins, not guesswork. Tap into a suburb to see what's happening now, ranked by live buzz. Don't know where to go? A four-tap mood quiz (energy level, who you're with, how much time you've got, what you're after) matches you to the suburb and events that actually fit, with the leaderboard re-ranking live as you answer. Check in when you arrive and the map updates for everyone watching, in real time.

How we built it

  • Frontend: Next.js 14 (App Router) + TypeScript + Tailwind, with a dark glassmorphism design system built on Radix UI primitives and Framer Motion for the interaction layer.
  • Map: MapLibre GL over a MapTiler basemap — we started on Mapbox but switched because Mapbox GL JS refuses to initialize without an access token even for third-party styles, while MapLibre has no such requirement.
  • Backend: Supabase (Postgres + Realtime) for suburbs, events, check-ins, and "going" RSVPs, with buzz scores computed client-side from the live check-in/going stream — the same signal drives pin glow, the heatmap, and the quiz's suburb rankings.
  • Data pipeline: a hand-curated "golden path" of real Sydney events layered with live pulls from the Ticketmaster API, plus a tiered randomized seeding script so the map never looks dead — or lopsided — on first load.

Challenges we ran into

  • Proportion problem: early on, a single real check-in would light up like the whole suburb was on fire, because there was no baseline activity to compare it against. Fixed with a log-scaled buzz curve, a seeded baseline of realistic activity, and a heatmap color ramp with a wide "quiet" floor.
  • A Flexbox gotcha: overflow-hidden on a flex-column child implicitly zeroes its minimum height per the CSS spec, which silently crushed two of our collapsible cards down to nothing and made them overlap.
  • MapLibre's expression rules: you can't combine a zoom expression with other operators — it has to be the sole top-level input to an interpolate. Cost us a round of debugging before we split the logic into two separate paint properties.
  • An unbounded scroll container: a suburb with a lot of events had nowhere to stop scrolling, so the whole page — not just the panel — scrolled with it. Traced it back to a missing overflow-y-auto boundary.
  • Iterating on the heatmap itself: we tried a proper hex-bin grid (via turf.js) as a more "designed" alternative to the gaussian blur, but pulled it back in favor of a gaussian heatmap re-styled with quantized color bands — giving a concentric-rings look without the extra complexity.

Accomplishments that we're proud of

  • A real end-to-end pipeline: tap check-in → Supabase Realtime → every connected client's pin glow and heatmap update, live, no polling.
  • A quiz that recomputes the full suburb leaderboard on every single tap, so the map visibly reacts to your answers before you've even submitted.
  • Filters that actually filter — toggling a category hides non-matching suburbs and pins outright, not just dims them.
  • A cohesive dark glassmorphism redesign applied consistently across every panel, chip, and drawer in the app, not just the flashy parts.

What we learned

  • Live-activity visualizations are only as convincing as their baseline — you can't validate "does this look right" on real data alone; you need a believable seeded backdrop first.
  • Library APIs deserve a quick sanity check before you trust them: turf.js's points() helper applies one shared properties object to every point rather than one-per-point, which quietly broke our first heatmap aggregation attempt.
  • Sometimes the more "sophisticated" solution (hex-binning) isn't the right one — a well-tuned version of the simpler approach can look better and ship faster.

What's next for Pulse

  • Expand past Sydney to other cities, since the whole architecture (suburb vibe vectors, live buzz scoring) is city-agnostic.
  • Persistent user accounts instead of anonymous session IDs, so check-in history and quiz preferences carry over.
  • Push notifications: "the suburb you matched with just started buzzing."
  • Social layer — see which suburb your friends are actually in, right now.
  • More live event sources beyond Ticketmaster to keep the golden path fresh automatically.

Built With

Share this project:

Updates

Submission history