← All documentation

Website

Events — signups, waivers, waitlists and reminders

Create events with per-event public pages, RSVP forms, waivers, waitlists, iCal feeds, and day-before push reminders. Includes recurring events, walk-in signups, and the pivot that pins open maintenance issues to volunteer workdays.

Events are your org's calendar of workdays, rides, races, gatherings and anything else you want to invite people to. Each event has its own public page, its own signup form, a waitlist when it fills, an iCal feed, automatic day-before push reminders through the field app, and an attendee roster you can work from as the day approaches.

What an event is

One row per event series in the events table — plus a per-event signup roster in event_signups. Each event carries:

  • Identity & content — title, URL slug, excerpt, hero image, body (block canvas — same palette as the website builder).
  • When — date (required, in your org's timezone), optional start / end times, an All day toggle.
  • Where — a free-text location string ("Trailhead, town, address…"). No coordinates, no map picker.
  • Discovery copy — a Tag ("Race", "Workday", "Ride") and an Audience ("All ages", "Members").
  • Publishing — draft vs published, a first-publish timestamp, and a Notify followers when published switch.
  • Recurrence — optional. Daily / Weekly / Monthly, every N units, optionally ending on a date. One row per series; occurrences are expanded at read time.
  • Signups — enabled toggle, capacity (null = unlimited), deadline, per-event form-field visibility, and per-event copy overrides for the signup block.
  • Waiver — enabled toggle plus the full waiver text. Attendees click-wrap; the timestamp + their IP are stored with each signup as the audit trail.
  • Trail work — pin open maintenance issues this event will tackle so attendees know what they're signing up for.

There's no paid-event / ticketing flow — every signup is free.

Creating an event

Events lives in the sidebar under Public site authoring (visible when your role has the Manage events permission on).

The Index page lists your events with per-row status pills — Published (green) or Draft (gray), with past events relabelled Finished regardless of prior state. Click + New event to open the editor. Same three-panel editor layout as the website builder + News, minus the block canvas: by default new events show only the Event details form on the right. Click Custom page builder in the topbar to unlock the full canvas when you want a rich per-event page.

Top-bar controls: title "New event", a Draft / Published pill, a small amber dot for unsaved changes, Save (turns to Saving… while writing), Publish / Unpublish outline button, View live ↗ once saved, and the Custom page builder / Hide builder toggle. Mobile collapses the secondary actions into a kebab menu and shows bottom tabs Details / Blocks / Preview.

Flash toasts: "Event created.", "Event saved.", "Event deleted."

Every field on the form

The right panel's Event details section, top to bottom:

  • Title — placeholder "Event title".
  • URL slug — prefixed with /events/, placeholder "my-event". Auto-fills from the title until you edit it. Same slug rules as News.
  • Date — required date input.
  • All day — checkbox. When ticked, Start and End hide.
  • Start and End — time inputs, side by side.
  • Repeat — dropdown: Doesn't repeat / Daily / Weekly / Monthly.
  • Every N days/weeks/months — number 1–52. Label switches singular/plural.
  • Ends on (optional) — date. Helper flips between "Repeats {freq} until {date}." and "Repeats {freq} indefinitely."
  • Signups — the whole signup section (see next section for details).
  • Location — placeholder "Trailhead, town, address…".
  • Tag — placeholder "Race, Workday…".
  • Audience — placeholder "All, Members…".
  • Excerpt — 3-row textarea, placeholder "Short summary used in the Events block + event-meta slot." Up to 500 characters.
  • Hero image — upload widget, JPG / PNG / WebP up to 5 MB.
  • Notify followers when published — checkbox: "Sends a 'New event' push + bell-inbox row to people who favorited your org with the New events notification on. Uncheck to publish quietly."
  • Trail work — checkbox picker of open + in-progress maintenance issues.

At the bottom: "Hero, when, location, body — the layout these data points render through lives in your website builder → Event template page."

Signups — turning them on and customizing the form

The Signups toggle drives everything under it. Off: no public form, no roster page, no reminders. On: the public event page shows the RSVP form and the attendee roster becomes visible from View attendees →.

Helper text under the toggle: "When enabled, the event's public page shows a form for visitors to RSVP. Manage attendees from View attendees."

When Signups are on, these fields appear:

  • Capacity (optional) — number, placeholder "unlimited". When exceeded, new signups become waitlisted instead of rejected.
  • Deadline (optional) — date-time. After this timestamp the form refuses new signups.
  • Link View attendees →.
  • Form copy (overrides template) — four inputs (Eyebrow, Heading, Subtitle, Button label), each placeholder "(use template default)". Leave blank to use the defaults set on the Event template's Event signup form block in the website builder — set them here to override for this one event.
  • Form fields — table with columns Field / Show / Required. Rows: Name (always shown, required-toggle only), Email, Phone, Party size (show-only, no required toggle), Notes. Helper text: "Hide fields you don't need. Make the form as simple as a 'yep, count me in' button — or collect everything." If you hide Email, an amber warning appears: "Without email, attendees won't receive the confirmation + cancel email — you'll only see them in this dashboard."
  • Require liability waiver checkbox (see next section).

Cloudflare Turnstile guards the public form on the canonical host; it's skipped on vanity domains due to the Cloudflare-for-SaaS free-tier hostname cap, but the honeypot + per-IP rate-limit protections still apply.

Waivers

Require liability waiver turns on a click-wrap waiver on the public form. When on:

  • Waiver text appears — a big textarea, placeholder "Paste your full waiver text. Attendees must check 'I agree' before they can submit." Up to 20,000 characters. Helper: "The agreement timestamp + IP are stored with each signup as the audit trail (click-wrap consent)."
  • The public form shows a "Liability waiver" heading with the full text and a required "I have read and agree to this waiver." checkbox.
  • Server-side, an attempt without the checkbox fails: "You must agree to the waiver to sign up."
  • Every signup row stores the exact timestamp and IP where the waiver was agreed. Managers see a "✓ waiver" badge on the roster with the signed timestamp on hover.

Recurring events

Set Repeat to Daily / Weekly / Monthly and configure the interval + optional end date. The event is stored as one row per series and expanded to individual occurrences at read time.

  • The public event page shows every upcoming occurrence in the Which date dropdown when signing up.
  • The events index groups the next 12 months of occurrences (each recurring event contributes multiple rows).
  • The dashboard attendee roster groups signups by occurrence date so a weekly volunteer day shows separate rosters for each Wednesday.
  • Ending recurrence: leave Ends on blank for indefinite, or set a date. Setting Repeat back to Doesn't repeat clears the interval + end date fields on save (so stale values don't linger).

Signup deadlines apply per-occurrence: signups for a past occurrence are always refused, even when the series continues.

Trail work linkage

The Trail work picker links this event to open + in-progress maintenance issues. Search open issues by title in the picker; tick the ones this event will tackle.

Blurb: "Pin open maintenance issues this event will tackle. The public event page lists them so attendees know what they're signing up for." Empty state (no open issues): "No open maintenance issues. Add some from Maintenance in the sidebar."

Linked issues render on the public event page through the event_maintenance slot block (default heading "What we'll be working on"). Attendees clicking through get context: what's broken, where it is, how bad. Great for volunteer workdays where you want people to see the actual scope.

Linkage is many-to-many, per-event. Linking here doesn't change the issue itself — it's a soft relationship for public communication only.

The signup flow (public side)

The public event page renders through the org's Event template (composed from event_hero + event_title + event_when + event_location + event_excerpt + event_body + event_maintenance + event_signup slot blocks — arrange them however fits your brand in Website builder → Event template).

The signup form, when enabled, sits on the event page as the event_signup block. Fields are dynamically shown / required per the Form fields table you configured:

  • Which date (recurring only — select of upcoming occurrences).
  • Your name / Your name (optional).
  • Email / Email (optional).
  • Phone / Phone (optional).
  • Party size — number 1–50.
  • Anything we should know? — notes textarea.
  • Turnstile challenge on canonical hosts.
  • Waiver block if enabled.

Submit button label: whatever you set in the Form copy override, or the template default ("Count me in" out of the box). If the event is at capacity the button flips to "Join the waitlist" and the copy above the form reads "Event is full · N on waitlist".

Server-side responses:

  • Success: "You're signed up. We'll see you at {title}." or "You're on the waitlist for {title}. We'll be in touch if a spot opens up."
  • Duplicate email: "You're already signed up for {title} — see you there!" or the waitlist variant.
  • Missing waiver: "You must agree to the waiver to sign up."
  • Recurring event without a date pick: "Please pick a date for the event."
  • Rate-limited: "Too many attempts. Try again in {s}s."

Confirmation email. Unless you've hidden the Email field, each signup gets an email immediately. Subject: "You're signed up for {title}" or "You're on the waitlist for {title}". Body includes When / Where / Party-size, an Add to calendar button linking a per-occurrence .ics file (also attached to the email), and a Cancel my signup button that's a 14-day signed URL. The cancel page shows "Signup canceled — Thanks for letting us know, {name}. Your spot for {title} has been freed up. You can close this tab." Expired links show "This cancel link has expired. Get in touch with the organization directly."

Managing signups (dashboard side)

From the event's editor click View attendees → in the Signups section, or land on /events/{event}/signups. Header shows "Attendees: {title}", the giant attendee total, "attendees across N signup(s)", and, when capped, an "of {capacity}" subtitle + a "+ N on waitlist" chip when the waitlist is populated.

Actions in the header:

  • Export PDF — a check-in sheet for the day: your letterhead at the top, then everyone going and waitlisted with their contact details, party size, date and whether the waiver is signed. Places taken and the waitlist count are totalled at the top.
  • CSV — the same people as raw rows (Name, Email, Phone, Party size, Status, Source, Occurrence date, Notes, Signed up, Waiver signed at). BOM-prefixed for Excel.
  • + Add walk-in — opens an inline form for someone signing up in person (Name / Email / Phone / Party size / date if recurring / Status Going or Waitlist / Notes). Walk-ins bypass capacity and skip the confirmation email.

Rosters group by occurrence date for recurring events; each group has a Going table and a Waitlist table. Per-row actions: Promote (waitlist → going, fires a personal push to app-signup attendees: "You're in: {title}"), Remove (browser confirm "Remove {name}'s signup?"; going-attendees get a "Signup canceled: {title}" push if they signed up through the app).

Per-row badges: walk-in (manager-added), 📱 app (signed up through the Report App — push-targetable), ✓ waiver (with signed timestamp on hover).

At each group header, Copy emails copies all attendee emails as a comma-separated list to your clipboard with the alert "Copied N emails to clipboard." There's no built-in "email all" — paste into your usual email tool.

An amber banner appears if signups are off but existing rows remain: "Signups are currently disabled for this event. Existing signups are shown for reference; the public form won't accept new ones until you re-enable signups in the event editor."

Empty state: "No signups yet."

Delete-event confirm: Delete "{title}"? This can't be undone. Cascades to every signup row and the trail-work pivot.

Publishing an event

Simple boolean — Draft or Published. No scheduling. The topbar Publish / Unpublish button flips the state and saves in one click. Existing events auto-save after toggling; the "unsaved" dot clears.

First publish stamps the publish date and — unless you unchecked Notify followers when published — fires a "New event: {title}" push and bell-inbox row to everyone who's favorited your org and left New events notification on.

Repeatedly saving an already-published event never re-pushes: the notification only fires on the first false → true transition.

On the Events index, past events show a Finished pill regardless of prior draft / published state so you can tell at a glance which side of the calendar they're on.

Where events show up publicly

Five surfaces:

  1. Individual event page/site/{slug}/events/{event} (canonical) or /events/{event} on vanity. Composed through your Event template with the slot blocks you configured.
  2. Events index/site/{slug}/events or /events on vanity. Header eyebrow "WHAT'S ON", heading "Events", subtitle "Upcoming workdays, rides, races, and gatherings." Row shows day chip, time, title, location, tag, audience, a ↻ Recurring marker, and N/C going if a capacity is set. Filter chips by tag: All plus every tag you've used. Empty states: "No upcoming events. Check back soon." / "No upcoming events tagged '{tag}'. Clear filter" Past events are hidden from the public index — the archive lives on the dashboard only.
  3. Events list block — Drop into any website-builder page. Same auto vs manual toggle as the News grid block; auto-mode pulls up to 12 upcoming published events.
  4. iCal feeds/events.ics for the whole calendar, /events/{event}.ics for a single event (honours ?date= for a specific recurring occurrence). Cached for 5 minutes.
  5. TrailsIQ Report App (field app) — Every event, every signup form, every cancel link works from the mobile app too. App signups carry a device ID so they're push-targetable for reminders + promotions.

Notifications and reminders

  • On publish (once) — Push + bell-inbox row "New event: {title}" / "{Mmm d} · {location}" to every org follower who left the New events notification on. Skip with Notify followers when published.
  • Reminder push (day-before / day-of) — An hourly cron fires per-occurrence reminders. Events that start at noon or later: reminder at 09:00 local on the same day. Events before noon: reminder at 17:00 local the previous day. All-day: reminder at 17:00 the previous day. Push title "Reminder: {title}", body "today at HH:MM · {location}" or "tomorrow at HH:MM · {location}". Per-signup dedup; only signups that came through the field app (with a device ID) and left Event reminder on receive them.
  • Confirmation email — immediate on signup, unless email is hidden or the signup was a manager walk-in.
  • Promotion push — when a manager promotes a waitlist attendee (only if they signed up through the app): "You're in: {title}" / "A spot opened up — your signup is now confirmed."
  • Manager-cancel push — when a manager removes a going attendee (app signups only): "Signup canceled: {title}" / "Your signup was removed by the organization. Reach out if you have questions."

No SMS. No email reminders — reminders are push-only through the field app.

Editing, canceling, deleting

  • Edit — click the event to reopen the same editor. Slug is editable; the auto-fill from title stops once you touch it.
  • Unpublish — flip to Draft. The public event page 404s immediately; existing signups stay in the roster. No emails or pushes go out on unpublish.
  • Delete — from either the Index or the editor. Confirm: Delete "{title}"? This can't be undone. Hard delete; cascades to every signup and the trail-work pivot.
  • Attendee self-cancel — the 14-day signed link in the confirmation email marks the signup as canceled. It's recoverable — you can see the row and re-promote if there's confusion.
  • No dedicated "cancel event" button — either delete the event, or flip it to Draft (hides from public but keeps the roster + signups queryable).

Permissions and plan gating

Plan gate. Events are Pro / Enterprise. Free-plan orgs can hit /events and see the list read-only, but get an amber card at the top: heading "Pro plan required", body "Events are part of the Pro plan, alongside the website builder." + an "Upgrade to Pro" link. Create / edit / delete / image endpoints abort with "Events require Pro or Enterprise."

Role gate. The "Manage events" permission (blurb: "Create, edit and delete events on the org's public hub + website, and approve / decline signups. Requires Pro or Enterprise.") defaults on for owner + manager; off for field worker + volunteer. Toggle per-role from Settings → Roles & permissions. The sidebar entry is gated on this permission.

The public signup endpoint is anonymous — no user account required, and it's rate-limited + Turnstile-gated on canonical hosts.

Common gotchas

  • All-day is the schema default for recurring events but the editor starts new events with All day unchecked. Tick the box explicitly if you want an all-day event.
  • Slug uniqueness is per org, not global. Two orgs can both have /events/summer-workday.
  • Deleting an event hard-deletes all its signups. No trash. Use Unpublish if you want a soft-delete effect.
  • Notify-on-publish only fires on the first draft → published transition. Saving an already-published event never re-pushes even if you toggle the checkbox.
  • Hidden email field = no confirmation email, no calendar .ics, no self-cancel link. The editor shows an amber warning about this. Attendees exist in your dashboard roster only.
  • Turnstile is skipped on vanity domains (Cloudflare free-tier limit). Rate-limit + honeypot still protect. If your event is high-profile and expecting bot traffic, publicise the canonical URL for extra bot protection.
  • Waitlist is manual promotion only. When a going attendee cancels, waitlisted attendees don't auto-promote. Watch the roster and click Promote explicitly.
  • Signup form heading + button copy default to the Event template's block copy (Sign up, Count me in). Per-event overrides live in the Event editor's Signups panel under "Form copy (overrides template)".
  • Recurrence values (interval + end date) are cleared on save whenever Repeat is Doesn't repeat. Flip repeat off intending to re-enable later and you'll have to re-enter the interval / end date.
  • Public events index hides past events entirely. Managers can browse the full history in the dashboard (Finished pill); the public can only see upcoming.
  • Event reminders go to app signups only. Signups that came through the public web form and left an email address don't get reminder push notifications — encourage attendees to install the app for reminders, or add a "Reminders" line to your confirmation email template.
  • No paid-event flow. Every signup is free. If you need paid tickets, integrate an external service and link out from the event body.

What's next

  • Style your Event template once in the website builder so every event inherits your brand — hero image size, when / location layout, signup form placement, related trails.
  • Drop an Events list block on your home page and pin it to auto-mode so new events show up automatically.
  • If your event needs a waiver, draft the waiver text in a doc first, paste it into the Waiver textarea, and test the click-wrap with a personal email — the audit trail is only as good as what you've drafted.
  • Read the News article for the sister content type, and the Website builder article for the block-canvas mechanics your Event template + custom event body pages share.