In plain English
A control panel for the AI meetup I run in Copenhagen. It keeps track of upcoming sessions, who's coming, and what we'll demo, and pulls the latest AI news into one place to share with the group.
Community · Solo build
AI Community
A personal cockpit dashboard for running the AI Workshop Copenhagen meetup. One place to see what's next, plan ahead, track who showed up, capture signals, and read the bi-weekly news roundup. Markdown-driven, built solo, deployed to Vercel.

Take a look
The cockpit behind a bi-weekly AI meetup
Four tabs (Cockpit, News, Members, Sessions), markdown + JSON data sources, floating feedback button. Public read-only preview.
By the numbers
Cadence
Bi-weekly
Copenhagen, in-person
Tabs
4
Cockpit, News, Members, Sessions
Data sources
3
Markdown notes, JSON, OG images
Stack cost
Free
Vercel free tier
Why I built this
Solo-operating a recurring community is a lot of context switching. Who's presenting next session? Did Anna show up last time? Which demos are in the backlog? What did someone flag in the last feedback note? The information lives in markdown session notes, in a planning spreadsheet, in random WhatsApp messages, and in my head.
I wanted one screen that answers all of those questions without me digging. A build script parses my markdown session notes plus a few planning JSON files into a single data.json that the React app reads. Four tabs: Cockpit for what's-next-and-now, News for the bi-weekly roundup, Members for who's been showing up, Sessions for past history.
The framework underneath comes from a Community Operations doc that lives in the markdown vault (not the repo): per session lifecycle (T-7 to T+3), rotatable roles, quarterly health metrics. The dashboard is shaped by that framework, so it's as much an operating system as a UI.
Tab by tab
Cockpit
The home view: the next session at a glance, who's doing what (host, timekeeper, note-taker, and so on), the demo backlog, what's coming up, and how the meetup is doing against its goals. It also pulls the open to-dos out of every session's notes so nothing slips.
News
A hand-picked roundup of the AI news that matters to the group, laid out as clean cards with a short summary and a why-it-matters-for-us note. I curate it by hand rather than auto-aggregate, because the framing is the whole point.
Members
Member gallery with attendance history (last-seen) and demo history (last-demo). Computed from the parsed session notes, so it stays in sync with what actually happened in the room.
Sessions
Past sessions timeline with gap markers, so missed weeks are visible rather than glossed over. Each entry links to the underlying session note in the vault.
Key features
Session lifecycle indicator
Every upcoming session shows where it is in the T-7 → T+3 lifecycle, so the right work surfaces at the right time without me having to remember the framework.
Rotatable roles
Host, timekeeper, note-taker, demo curator, recap writer per session. Pulled from the schedule JSON, displayed prominently on the next-session card.
Open action items
Markdown session notes are parsed for unchecked task lines. Anything not closed surfaces in the Cockpit. No separate task tracker to maintain.
Org health metrics
Computed metrics (member retention, demo throughput, gap weeks) shown against framework targets. Quarterly review fuel without a separate analytics tool.
Magazine news cards
Each news entry rendered as a hero card with OG image, theme tag, summary, why-it-matters, source links. Themes (Global / EU+Policy) get their own statements.
Floating feedback button
Categorised feedback (Session, Idea, Demo signup, Venue, WhatsApp signal, General) appended to data/feedback.md via Vite middleware. Last 5 entries shown inline.
Tech stack
Frontend
Geist Sans + Geist Mono via fontsource-variable. agentation toolbar wired for in-app visual feedback during dev.
Data pipeline
scripts/build-data.js parses markdown session notes + planning JSON into one src/data.json. scripts/fetch-news-images.js pulls Open Graph images for news entries into public/news-images/.
Server + Deploy
Express for the production preview / feedback API. Deployed to Vercel. Vite middleware handles /api/feedback in dev (appends to data/feedback.md).
Under the hood
I keep my meetup notes as simple text files and let the dashboard read them directly, so updating it is just editing my notes, with no clunky admin screen to click through.
The whole thing is a plain website with no database or logins behind it, which makes it free to run and quick to change whenever the meetup changes.
Brand & creative
Manifesto, format, and animated creative
Two brand posters built over real photos from past workshop sessions, plus an animated 9:16 creative. Generated with Pomelli, Google's AI brand toolkit.
Manifesto
FormatCommon questions
Is the meetup open to anyone?+
Anyone working on a personal AI portfolio project in or around Copenhagen is welcome. The room intentionally stays small (8-15 people) so the demo feedback can be real.
Is the dashboard itself open to the public?+
Yes, the deployed URL is public. It's deliberately read-only and built around my specific Obsidian vault, so it won't be useful to fork as-is, but you can see exactly how a solo-operated community runs.
Why a custom dashboard instead of Notion or Airtable?+
Notion and Airtable are great until you want a UI shaped by your specific operating framework. The Cockpit's T-7 → T+3 lifecycle, rotatable roles, and computed health metrics need custom logic. A SaaS would have you adapt your framework to its primitives instead of the other way around.
Why is the news hand-curated instead of auto-aggregated?+
I built (separately) an AI news aggregator that scores stories with Claude. Started using its output, then went back to hand-curation for this dashboard. The bi-weekly roundup needs editorial framing (theme statements, regional why-it-matters notes) that a generic aggregator can't produce. The aggregator is great for daily signal; the dashboard is for editorial digest.
How is data updated?+
Edit the markdown session notes in my vault, edit the planning JSON in the repo, push. The build script re-runs as part of npm run dev / npm run build. The deployed Vercel site picks up changes on every git push. There's no admin UI on purpose: markdown + git is the admin UI.
What's the floating feedback button for?+
Capturing signals from the room without making people use a separate tool. Categories cover sessions, ideas, demo signups, venue tips, and 'WhatsApp signals' (things people mention in chat that I'd otherwise lose). Appends to a markdown file the dashboard reads on next build.
What I learned
- ·A clear way of running the community matters more than any feature. The dashboard is only useful because there is a real routine behind it, otherwise it would just be a prettier Notion page.
- ·Capture feedback where people already are. A small feedback button inside the dashboard the room is already looking at gets far more useful input than asking people to email me their thoughts.
- ·Show the gaps honestly. Marking the weeks where no session happened kept me accountable to the every-other-week rhythm, instead of quietly pretending the meetup never paused.
What's next
Honest roadmap. Things I know are gaps, in priority order.
Granola integration
Granola captures meeting transcripts and notes. Piping those into the session-notes parser would mean Action Items + Members + Demo backlog update automatically after each meetup, instead of me editing markdown.
Wire in the aggregator
I built (separately) a Claude-powered news aggregator that scores stories. Right now the dashboard's News tab is hand-curated. The natural integration: aggregator surfaces candidates, I mark the bi-weekly winners, dashboard picks them up. Two-stage curation.
Public member signup
Members are added by hand to the data file. A small signup form (writing to a per-event JSON) would let people join without me being the bottleneck.
Generic-fork-ready version
The vault path is hardcoded and the framework is mine. A generic 'community cockpit' template (configurable lifecycle, configurable roles, vault-path-configurable) would let other small communities run their own version.