Events
What was missing before.
The old events page could tell you that "Bakery District Street Fest" was on June 20th. It could not tell you whether your community was going, whether there was room left, when to remind you, or what to do if the event repeated every month. If you wanted to run an AMA series, a weekly office hour, or a capacity-limited workshop, you ended up in Eventbrite, Luma, or a Google Form. The community came home to discuss; the actual event lived somewhere else.
This release pulls the whole event surface back into Mobieus.
What shipped
One-tap RSVPs.
Every event detail page has a Going / Maybe / Not going chooser. Tap once, you're in. The page also tracks a guests count (0–9 extra people), so a member bringing their team or family can register the full group in one go. RSVPs are auditable in the admin event detail.
Capacity with auto-managed waitlist.
Set a capacity on any event. Once "Going" hits the cap, the next person to RSVP yes lands on the waitlist instead. When someone cancels, the earliest waitlister gets promoted to Going automatically — FIFO ordering — and Mobieus emails them "you're in." No spreadsheet, no manual chase. The whole transaction is atomic; you cannot end up over capacity from concurrent RSVPs.
Reminder emails at 24h and 1h.
Anyone marked as Going gets a reminder 24 hours before the event, and a second reminder 1 hour before. Both emails carry the event time formatted in the event's timezone, plus the iCal download link so the recipient can flip to their calendar app from inside the message. There is no admin configuration — the reminders run automatically once the feature is enabled on your tenant.
iCal export — "Add to calendar" in one click.
Every event detail page carries an "Add to calendar" button that downloads a standards-compliant .ics file. Google Calendar, Apple Calendar, Outlook, Fastmail, anything that reads iCalendar will accept it. The file includes a stable UID per event, the event timezone as a TZID parameter on DTSTART/DTEND, and RFC 5545-escaped SUMMARY, DESCRIPTION, LOCATION, and URL.
Recurring events without the spreadsheet.
Set up daily, weekly (with specific weekdays such as Mon/Wed/Fri), monthly, or yearly events from the same submit form. Pick an "Until" date or an occurrence count. Mobieus expands the series into individual event rows with a parent_event_id link, capped at 52 occurrences per parent to prevent runaway. Editing the parent rebuilds the series. Deleting the parent cascades to all occurrences.
Timezone-aware display everywhere.
Every event has an IANA timezone (defaults to UTC). Event lists, admin tables, and detail pages all render the date and time in the event's timezone with a small "(in EVENT_TZ)" note when it differs from the viewer's. The create/edit form has a searchable timezone picker covering Americas, Europe, Asia, Africa, Australia, Pacific, and UTC.
Attendee list, privacy-gated.
Going members appear as an avatar grid on the event detail page. The list is visible to other attendees, the event submitter, and admins — not to anonymous visitors. Up to 24 avatars shown with a "+N more" indicator when the list is longer.
How it works under the hood
The data model.
Three new things in the schema. A set of new columns on the existing events table for time-of-day, capacity, timezone, recurrence rule, and a self-referential parent_event_id. A new event_rsvps table with one row per (event, user) pair, status enum of yes/no/maybe/waitlist, and per-RSVP guest count. And a per-tenant scheduler entry that drives the reminder worker.
The recurrence engine.
Mobieus stores a compact subset of RFC 5545 RRULE (FREQ=WEEKLY;BYDAY=MO,WE,FR;INTERVAL=2;UNTIL=20260801) and expands it into individual event rows on save. Child rows carry parent_event_id; deleting the parent ON DELETE CASCADEs the children. The expander hard-caps at 52 occurrences and one year out, whichever is smaller, so a stray YEARLY rule cannot pollute the database.
The reminder pipeline.
A platform-wide cron worker runs every minute, iterates per-tenant credentials, and selects RSVPs whose event start falls inside the 24h or 1h reminder window (with a ±2-minute slack so a single missed cron tick does not skip a notification). Each due reminder is enqueued into the tenant's existing email_queue — not delivered directly — so the tenant's normal email-queue worker handles SMTP. Same separation we use for push notifications, automation queue, and the mail-reply bridge.
The iCal output.
The endpoint at GET /events/<id>/ical is public (no auth needed). Events with a time-of-day emit DTSTART/DTEND with TZID; all-day events emit VALUE=DATE with the spec-correct exclusive DTEND. Strings are escaped per RFC 5545 §3.3.11 (backslash, comma, semicolon, newline). The UID is stable across edits so a re-imported event updates the existing calendar entry instead of duplicating it.
What this means for operators
The feature ships enabled on every tenant. The reminder cron defaults to off so you can smoke-test on dev before flipping it on; set UPDATE cron_jobs SET enabled=1 WHERE job_name='process-event-reminders' on your tenant database to start sending. We have already enabled it on all three live tenants.
If you set capacity on a workshop, the math just works. If you set up a weekly cadence, the series populates. If your members live in three timezones, the display follows along. And if you put a Going RSVP on an event, you get the reminder — with the calendar invite attached — before it slips your mind.
Spot a bug or want a follow-up feature like per-occurrence overrides? Open a thread at support.mobieus.io/forums/feature-requests.

