Back to all posts

Introducing Simple Unconference: Running an Unconference Without the Spreadsheet Pain

2026-05-2410 min readUpdated 2026-05-25

Unconferences are fun. Organizing them, less so.#

If you've ever attended a good unconference, you know the magic. Everyone shows up with ideas, somebody scribbles them on a wall, people vote with their feet, and by the end of the day you've had three conversations you didn't know you needed. No keynotes, no thirty-slide intros - just the topics the room actually cares about.

If you've ever organized one, you also know the other side. The spreadsheet that ends up with twelve tabs. The whiteboard photo someone took at 9am that's already out of date by 9:15. The participant who really wanted to attend session A but ended up wandering into session C because room B was already full.

That's the gap Simple Unconference is meant to close.

Try it before you self-host. There's a free public instance running at unconference.enking.dev. Same app, same chart, hardening enabled - feel free to spin up a test conference and click around.

What it actually does#

The short version: it's a single web app that handles the whole lifecycle of an unconference. Submissions, voting, room assignment, personal schedules, 1:1 expert bookings, in-app chat, notifications. One Docker image, one persistent volume, done.

The slightly less short version is that it tries to encode the rules of a good unconference into software, instead of leaving them as tribal knowledge that the organizer enforces by hand. A few examples of what that looks like in practice:

  • Sessions get starred, not voted on. A star is one signal that drives two outcomes - it ranks submissions for the auto-assignment algorithm and derives planned tracks onto your personal schedule. You don't have to remember to do two things; one click is enough.
  • The algorithm is a pure function. Given the same rooms, sessions and stars, it produces the same placement every time. No "let me re-run it and hope for a better result" lottery. The route layer adds pre-processing (overlap exclusions, pinned rooms, required room features), then the deterministic core decides who goes where.
  • Conflicts get resolved once, not iteratively. If a session needs a projector and every projector-equipped room is taken, the algorithm tells you up front in a single resolve panel. You decide how to fix it (skip this run, move a pin, override room requirements), apply, re-run. No game of whack-a-mole.

Why I built this#

Up front: this isn't an "I've organized fifty of these" pitch. The opposite. I went to one unconference recently, and walked out with a notepad full of "huh, that was clunky" observations. The session list lived on a wall. Room assignments happened by argument. The personal schedule was whatever you could remember from the morning kickoff. The good stuff was great. The logistics were held together with goodwill.

The tools that do exist for this either don't fit or don't exist:

  1. General event platforms (Eventbrite, Sessionize, etc.) - built for fixed-agenda conferences. They handle "here's the schedule, here's where to register" really well. They handle "we'll figure out the schedule together at 10am" not at all.
  2. DIY spreadsheets - flexible enough to do anything, structured enough to do nothing well. Works fine for a 30-person internal meetup. Breaks down hard at 200+ attendees with multiple parallel tracks.

What I wanted was something specifically shaped like an unconference: open submissions, signal-driven scheduling, room-aware assignment, and a personal schedule that updates the moment someone stars a session. And I wanted it to be self-hostable, because the kinds of events I'd want to use it for (community meetups, internal company barcamps) don't want their attendee data sitting in a third-party SaaS.

So I built it - based on exactly one unconference's worth of pain points and a lot of "what would I have wanted here?" thinking. It hasn't been run at a real event yet. The design comes from notes, not from battle-testing, and the only way to find out where the rough edges actually are is to put it in front of organizers who can break it. That's part of why this post exists.

The three slot types#

The agenda is built around three different kinds of slots, because real unconferences aren't pure freeform:

Slot typeWhat happensWhen you'd use it
NormalModerators pick which published submission runs in which roomKeynotes, opening / closing, invited talks
UnconferenceA deterministic algorithm places the most-starred sessions into appropriate rooms and assigns each starring userThe actual unconference blocks - open submission, community-driven
MixerCapacity-aware even split of every participant across selected rooms, with optional "avoid repeats" historyLunch tables, networking rounds, speed-dating-style intros

Slots can also be duplicated as linked offerings, which forms a slot series with shared rooms and submissions but rotating participants. So if you've got a popular workshop you want to run twice in the afternoon, the same star yields two schedule rows - and avoidRepeatsAcrossSiblings (on by default) keeps the same person from being assigned both times.

The personal schedule#

This is the bit that I think most clearly shows the difference between "a conference app" and "an unconference app". Each participant gets a single view that unions, for their identity:

  • Their unconference + mixer placements (algorithm output)
  • Every planned-slot track derived from their stars (mandatory tracks, starred sessions, sessions they're presenting themselves)
  • Their expert bookings (as booker or as expert)

When the unconference runs and someone couldn't be placed because all their stars filled up, they get a Pick a session banner with the rooms still available. Manual picks survive re-runs. Same-submission rows across sibling offerings are grouped with a Same session also at HH:MM caption. Overlapping starred entries surface a conflicts with X pill so people can decide which to attend before the slot starts, not during it.

There's also a per-identity iCal feed, so the people who live in their calendar app can pin it once and let it update itself.

Experts: the 1:1 booking layer#

This is the feature I'm most attached to, and the one that hasn't shown up in any of the off-the-shelf tools I've tried. Promote any participant to an expert, give them a room pool and one or more bookable timeframes, and the app derives slots deterministically from each timeframe. Other participants book one with a single click.

Room allocation locks at booking time, so re-shuffling an expert's room config doesn't strand existing bookings. The booked person gets a notification. The booker gets the slot on their personal schedule. The expert sees their bookings on theirs.

It's the closest thing I've found to encoding the "let me grab fifteen minutes with the person who actually knows about X" hallway moment, without forcing it to happen by accident.

Self-hosting#

If you want to host it yourself - and I'd encourage you to, even just for a test event - the deployment story is intentionally boring.

Docker:

bash
docker run -d \ --name simple-unconference \ -p 3000:3000 \ -v simple-unconference-data:/app/data \ --restart unless-stopped \ ghcr.io/enyineer/simple-unconference:latest

The SQLite database lives at /app/data/prod.sqlite inside the container. Mount a volume there and you're done. On startup the container runs prisma migrate deploy, so upgrading is just a docker pull and a restart.

Kubernetes:

bash
helm install unconf oci://ghcr.io/enyineer/charts/simple-unconference --version <version>

The chart provisions a Deployment, Service, optional Ingress, the SQLite PersistentVolumeClaim, and a Secret carrying the database URL. Probes hit /api/health. There's a workers.count: "auto" option that fans out to multiple Bun workers inside a single pod based on the CPU + memory limits, if you want more throughput from one node.

A note on serverless: the app needs a persistent disk for SQLite and a long-running process for the Bun + Hono server. That rules out Vercel and Netlify - their ephemeral filesystems would lose the database on every cold start. Use a PaaS that runs containers with attached volumes (Railway, Render, Fly.io, DigitalOcean App Platform) or just throw it on any VM.

What's actually under the hood#

For the tech-curious - and because the architecture matters when you're deciding whether to trust an app with a year's worth of event registrations - here's the stack:

  • Runtime: Bun
  • HTTP: Hono
  • Database: Prisma 7 with the libSQL driver-adapter (SQLite locally, Turso if you want it remote)
  • Validation: valibot, with schemas shared between server and client
  • Frontend: React 19 + Vite
  • Design system: per-conference pluggable (ships with GitHub Primer + a Minimal theme, both dark-mode aware)
  • Assignment algorithm: pure function, deterministic, separately tested with units + scale + integration

The assignment algorithm is the piece I'm proudest of, mostly because it's the piece that most events I've seen handle by hand. It uses Kuhn's algorithm for bipartite matching when sessions have room requirements (e.g. needs projector, needs whiteboard), with a post-processing swap pass so that the most-starred session gets the largest matching room. If a tag-constrained session can't be matched, the algorithm cascades to the next-most-starred candidate and re-runs - all conflicts surface in a single resolve panel rather than forcing the moderator into iterative resolve-and-rerun rounds.

There's a "How assignment works" modal in the app that renders a plain-language explanation of every rule, so participants and moderators don't have to take it on faith.

Hardening for public instances#

The public instance at unconference.enking.dev is on the open internet, which means it has to survive the realistic abuse vectors without breaking the venue-WLAN traffic pattern where dozens of legitimate attendees share one NAT. Four layers handle it:

  1. Cloudflare Turnstile on the high-abuse endpoints (signup, login, invite claim, join-via-link). Invisible to most users, challenges suspicious traffic.
  2. Per-email failed-login lockout for credential stuffing - NAT-blind by design, so a venue WLAN with hundreds of concurrent logins doesn't lock anyone out.
  3. Per-account write rate limit (sliding hour window) catches compromised accounts being used as spam vehicles.
  4. Per-account / per-conference quotas as the hard ceilings on what one user can accumulate.

Every layer can be disabled by setting its env var to 0 for private deployments where you trust your users. Defaults are sized for ~2000-attendee events with ~5 sessions per attendee. Larger? Self-host and raise the caps.

Try it#

If you're organizing an unconference, a barcamp, an internal company off-site, or even just a small community meetup that wants to feel less ceremonial - give it a shot.

It's MIT-licensed. Use it, fork it, host it for your community, embed it in your company's internal events platform - I genuinely don't mind. If you run an event with it I'd love to hear how it went, what broke, and what was missing. That's the feedback that turns a side project into something usable.


Found a bug, missing a feature, or just want to share how your event went? Open an issue on GitHub or drop me a line directly.

Frequently Asked Questions

What is an unconference?

An unconference is a participant-driven event where the agenda is built on the day by the attendees themselves. People propose session ideas in the morning, the group votes or self-selects what to discuss, and rooms are scheduled around what people actually want to talk about - rather than a fixed program decided months in advance.

Is Simple Unconference free and open source?

Yes. The whole project is open source and self-hostable. You can run it on a small VPS or in a container alongside your other community tooling, no SaaS subscription required.

What does Simple Unconference actually do?

It handles the moving parts that usually live in a spreadsheet: collecting session proposals, letting participants signal interest, generating a schedule that fits the rooms and time slots you have, and showing the resulting program to attendees. The goal is to keep organisers focused on the event itself, not on logistics.

Do attendees need an account?

A lightweight account, yes - enough to propose sessions and signal interest. The signup is designed to take seconds; there is no email verification dance or third-party auth required to participate.