Kansas Korean
Live · Community meetupFind your people. Make a plan.
Choose an interest, join a meetup and carry your itemized share into a prefilled Venmo payment.
Interactive explanation · not the live service
Loading interactive explanation…
Watch the original recordingsMobile · Recording notes included
Use the left and right arrow keys to switch slides.
Recorded from a local build with fictional members; AMC showtimes and translations were stubbed.
Joining a weekly pickleball meetup, matching an AMC showtime, checking a bowling settle-up, and switching the app from Korean to Spanish.
1 / 6Explore the architectureSystem diagrams, design decisions and detailed flows
System overview
- PWA in browserUI + service workerStep 1, pages + /apiVERCELNext.js appApp Router + API routesDrizzleSTORAGENeon Postgresmeetups, rules, alerts
- VERCELVercel Crondaily, 13:00 UTCGET /api/cronNext.js appStep 2, VAPID pushWeb Push servicesbrowser push endpointsalert + badgePWA in browser
Other connections
- Next.js apptoUpstash Redisshowtime cache
- Next.js apptoVercel Blobupload tokens
- Next.js apptoKakao / GoogleOAuth
- Next.js apptoAMC + TMDBshowtimes
- Next.js apptoClaude Haikutranslate
View the diagram as text
Parts
- PWA in browser (UI + service worker): Client / UI
- Vercel Cron (daily, 13:00 UTC): Background job
- Next.js app (App Router + API routes): Owned service
- Web Push services (browser push endpoints): External service
- Neon Postgres (meetups, rules, alerts): Data store / broker
- Upstash Redis (AMC showtimes, picks): Data store / broker
- Vercel Blob (meetup photos): Data store / broker
- Kakao / Google (OAuth sign-in): External service
- AMC + TMDB (showtimes, film metadata): External service
- Claude Haiku (on-demand translation): External service
Connections
- Step 1: PWA in browser → Next.js app: pages + /api
- Next.js app → Neon Postgres: Drizzle
- Vercel Cron → Next.js app: GET /api/cron
- Step 2: Next.js app → Web Push services: VAPID push
- Web Push services → PWA in browser: alert + badge
- Next.js app → Upstash Redis: showtime cache
- Next.js app → Vercel Blob: upload tokens
- Next.js app → Kakao / Google: OAuth
- Next.js app → AMC + TMDB: showtimes
- Next.js app → Claude Haiku: translate
How a weekly meetup reaches members
Host posts a weekly meetup
The host ticks 'repeat weekly' and the browser posts to /api/posts. The server checks the HMAC-signed session cookie and picks the region from the request's hostname.
Rule and first occurrence saved
A recurring rule is stored with the chosen weekday, and the first occurrence is created right away. The meetup, the host's participation and one inbox row per subscriber of that category and region are written in a single transaction.
Subscribers get a push
Alert text is rendered in each recipient's language, then sent as VAPID-signed Web Push to every device they subscribed, with that person's unread count. The service worker shows the notification and sets the app-icon badge.
Daily cron opens next week
Vercel Cron calls the reminders route once a day with a bearer secret. For each region, the server creates any occurrence due in the next 7 days that does not exist yet, keyed by rule and date; deleted occurrences count as existing, so a skipped week is not re-created.
Day-of reminder
In the same run, participants of today's meetups, in each region's own time zone, get a reminder. Meetups already reminded are skipped, so re-running the cron sends no duplicates.
The project & my contribution
- Problem
- Hobby meetups like movie nights, pickleball and climbing needed one place to plan, sign up and split costs.
- Solution
- A meetup app where members post and join meetups, comment, share photos, leave reviews and split costs, with recurring schedules and push alerts. One codebase serves both cities.
- Result
- Live in both cities since July 2026, with weekly recurring meetups.
- 73 members
- 70 meetups
- 507 RSVPs
Live site: Korean interface by default; English and Spanish are available.
The source code is private. I'm happy to walk through it on request.
How it's built
- Next.js 15 on Vercel with Neon Postgres (Drizzle), Upstash Redis and Vercel Blob
- Kakao and Google sign-in; in-app inbox and Web Push to an installable PWA
- Korean, English and Spanish UI, with on-demand Claude Haiku translation of posts
Highlights
- A daily cron creates recurring meetups idempotently, so a canceled week stays canceled
- Meetups and their notifications are written in one transaction, localized per recipient
- Cost splitting in integer cents and prefilled Venmo links; payment confirmation stays in Venmo