2026-06-10 16:53:28 +02:00
2026-06-10 16:53:28 +02:00
2026-06-10 16:53:28 +02:00
2026-06-10 16:53:28 +02:00

mediator

A tiny self-hosted web app for scheduling get-togethers with your friend group. You circle dates on a calendar, optionally add a time per day, and share one link. Friends open the same calendar, circle the days that work for them, and the best date floats to the top. No accounts, no sign-up — the link is the key.

Built with Go standard library only: no external dependencies, one static binary, polls stored in a plain JSON file.

Run it

Requires Go 1.22+.

go build -o groupdates .
./groupdates

Open http://localhost:8080 — that's the page for creating a poll. þ Flags:

Flag Default Meaning
-addr :8080 Listen address
-data data Directory for polls.json

To let friends reach it, run it on a machine they can access (a small VPS, a Raspberry Pi behind a port forward, etc.) and put it behind HTTPS — e.g. a Caddy or nginx reverse proxy. The share links use whatever host your friends open the page on, so no configuration is needed.

How it works

  1. Create a poll — give it a title, click every date you want to offer on the calendar (only today and future dates are clickable), and optionally set a time for each date in the list below the calendar.
  2. Share — after creating you get two links:
    • Share link (/p/<id>) — send this to the group.
    • Admin link (/p/<id>?admin=<token>) — keep this. It's the only way to close or delete the poll.
  3. Friends answer — they open the share link, see the same calendar with the offered days highlighted, circle the ones that work, enter their name, and send. Answering again with the same name (case-insensitive) replaces the earlier answer.
  4. Close or delete — polls can never be edited after creation. From the admin link you can close the poll (answers freeze, results stay visible) or delete it entirely.

The poll page refreshes results every 30 seconds while open.

API (if you're curious)

Method Path What it does
POST /api/polls Create a poll, returns id + admin token
GET /api/polls/{id} Poll data (admin token never included)
POST /api/polls/{id}/votes Submit / replace an answer
POST /api/polls/{id}/close Close (admin token required)
DELETE /api/polls/{id} Delete (admin token required)

Admin token goes in the X-Admin-Token header or ?admin= query parameter.

Storage

Everything lives in <data-dir>/polls.json, written atomically on every change. Back it up by copying that one file. Deleting a poll removes it from the file immediately.

Project layout

main.go              server, storage, API handlers (stdlib only)
static/index.html    create-a-poll page
static/poll.html     voting + results page
static/calendar.js   the shared calendar widget both pages use
static/create.js     create-page logic
static/poll.js       poll-page logic
static/style.css     styles

Static files are embedded into the binary with go:embed, so the compiled groupdates binary is all you need to deploy.

S
Description
group scheduling
Readme 3.1 MiB
Languages
JavaScript 35%
CSS 24%
Go 21.6%
HTML 13.5%
Shell 5.9%