What's new
Things that look saved really are saved
A reliability pass across the app so the screen never tells you something worked unless it actually did:
- Register — adding a walk-in. If adding a student to a register doesn't go through (locked register,
weak signal, a future date), the row now rolls back and you get a clear message — instead of a student who looks added but was never saved. Walk-ins still don't count against class limits.
- Student notes. Adding, editing, or deleting an internal note is now handled by our secured server.
If a save fails, your typed text, your edit, or the note itself stays put with a clear message — nothing silently disappears.
- Video reviews. A submission is only ever marked "reviewed" once the score is safely recorded, so a
green/amber/red can't go missing while the submission looks done.
- Closure notifications. Closures added from the calendar now actually notify affected members
(previously only the Settings → Closures path did) — within 14 days they queue a *lesson cancelled* message per affected member. The confirmation says notifications are *queued for affected members* rather than implying guaranteed delivery.
Student Profile → Billing tab no longer breaks on older records
The membership tab could show "We couldn't load this membership information" if a single background detail failed to load. It now shows everything it can and a gentle note about the rest, instead of hiding the whole tab.
Events can't be saved with impossible dates
Creating or editing an event now blocks date combinations that don't make sense — an end before the start, a booking cut-off after the event has started, or an early-bird deadline after the cut-off. You get a clear message and the save is prevented (on the form and on the server), so links can't go out with a cut-off in the past. Existing events are untouched.
Dialogs no longer hide behind the menu
Groundwork to stop pop-up dialogs ever appearing *behind* the side menu or student list: shared dialogs now render above everything on a consistent layering scale.
Automations — "Save draft" works again, and the builder is tidier
- Fixed: saving a Communications Trigger draft was failing silently (a 405 error) — it now saves
reliably in both the simple and advanced builders. Existing published triggers were unaffected.
- The trigger builder is now a focused workspace — the section nav pills are hidden while you're
editing, so it doesn't feel like another settings page.
- Picking when a trigger fires uses clear, scannable cards instead of a dropdown — now with a
search box and category filter pills so the right trigger is quick to find as the list grows. Choosing what it does (Email / SMS / Telegram / Delay) uses matching cards.
- The right-hand flow summary is restyled as an obvious view-only preview (it no longer looks editable).
- The builder title now updates live as you rename a trigger — no more stale "Untitled trigger" while
you're editing.
Safer refunds when a paid competition/event entry is cancelled
Cancelling a paid external-event entry is now protected against accidental duplicate refunds: a double-click, page refresh, or network retry can no longer create a second Stripe refund or double-count the refund on a shared (bundled) invoice — the refund is keyed so it happens exactly once. Partial refunds on bundled invoices and paired-entry cancellations are unchanged, and if a refund fails you now get a clear message and the entry is not marked cancelled.
Automations made simpler
The Automations area is now organised around three clear places instead of six engine-flavoured tabs: Build (make and manage your automations — the main screen), Activity (what ran, what's queued and anything that failed, now grouped together), and Settings (safety, sending state, Trigger.dev status, test recipients and any legacy-rule conflict warnings). Opening Automations now lands you on Build. None of the sending behaviour changed — this is purely how it's laid out and labelled.
Calendar week view now reads in time order
In week view, classes and events are now listed together in time order — a 9am event shows above a 6pm class, instead of all classes first then all events. Colours, trial markers, venue/location and click behaviour are unchanged. The day pop-out also scrolls properly now on desktop and mobile (no more cramped/stuck scrolling), with the date header and "Add event" button staying put.
Calendar: a proper full-page day view
Clicking a day in the calendar now opens a dedicated day page (/calendar/day/…) instead of the cramped slide-over, so it scrolls normally on desktop and mobile, has a clear Back to calendar button, and gives classes, events, trials and bookings real room. The day list is in time order, and add/edit/ cancel events, trials, invites and bookings work exactly as before. (Deep-linkable too — you can bookmark a specific day.)
Automations: archive, steadier tables, categories & a Templates home
- Archive a trigger or flow instead of deleting it. Archived automations stop
running but keep every version, run and delivery record, and you can restore them anytime (they come back as a draft to re-publish). A new Archived view lists them. Drafts that were never published and have no history can be Discarded outright. Archiving and discarding are owner/admin-only and fully audited.
- Tidier tables everywhere in Automations — long trigger names, error messages,
recipient addresses, provider IDs and cron routes no longer stretch or wrap the columns; they truncate with the full value on hover, and tables scroll sideways on small screens instead of crushing. Status, type, channel, version, date and action columns stay on one line.
- Categories on the Build list — quick category chips (Membership, Payments,
Trials, Events…) plus a small category tag on each row, and search now matches the category too.
- Templates under Automations — the message templates your automations send now
have a home right next to Build, alongside the existing Settings location.
A clearer Comms Centre
The communications area now hangs together as a Comms Centre: from the message composer you can jump straight to Templates and Deliverability, which now have their own pages alongside Comms, Automations and the Comms Map — all reusing the same panels you already knew from Settings (Settings keeps them too, so nothing moved out from under you). Email templates are much easier to find from the comms area.
In Automations → Build, each trigger now has a tidy ⋯ More menu to Archive it (it stops running but keeps its history) or Discard an unpublished draft, with an Archived view to restore from. Nothing about how messages send has changed.
Fix: archived legacy automations no longer block new triggers
Archiving a legacy automation in Settings now fully retires it — the new Communications Triggers area no longer flags it as a conflict, and it can never make a builder trigger defer. (The legacy guard now ignores archived rules, and archiving also disables the rule.) No change to how anything sends.
Automation builder: club + member merge tags now resolve
Builder-trigger emails can now use the club and member personalisation tags — {{club_name}}, {{club_logo_url}}, {{club_email}}, {{club_contact}}, plus {{belt_rank}}, {{belt_system}}, {{membership_plan}}, {{mobile}}, {{household_name}}, {{age}} and more — not just the recipient name + each trigger's own tags. The builder's tag picker now offers exactly the tags that will resolve for the selected trigger (so no more tags that render as literal {{…}} text). No change to who is emailed or whether — only what the message can say.
Domain-proof email logos (inline/CID embedding)
For gold-standard multi-tenant deliverability: the club logo can now be embedded directly in each email as an inline (CID) attachment instead of linking to an external image URL. With no external image, there's nothing to mismatch the sending domain — so the "host images on your sending domain" warning can't apply, no matter which domain a club sends from. Behind a flag (EMAIL_INLINE_IMAGES, off by default) and fully fail-safe: if the logo can't be embedded for any reason, the email still sends exactly as before with the logo as a normal image. The in-app "view email" preview keeps the image URL so it still renders in the dashboard.
Fix: no more duplicate booking/automation confirmations
When a club publishes a Communications Trigger for an event (e.g. event booked), the legacy automation engine's built-in default email no longer also fires — so members get ONE confirmation, not two. The legacy default now stands aside whenever a live builder trigger covers the event; clubs that haven't built a trigger keep their default as before.
Automations Activity: see a preview of what was sent
Each delivery row in a run's detail now shows a short preview of the message that went out, so you can tell at a glance what was sent. The full rendered email remains in Communications history.
Cleaner, honest automation merge tags
One canonical merge-tag registry now drives the automation builder, the email-template editor, previews, and docs — so every tag a club is offered genuinely fills in.
- Builder pickers only show tags that resolve for the chosen trigger. Member details
(belt, plan, etc.) are no longer offered on trial/waiting-list triggers, where there's no member record yet — they'd otherwise have shown up blank.
- Event automations got the full event pack. An "Event booked" automation can now use
{{event_time}}, {{event_end_time}}, {{event_location}}, {{event_cost}}, {{earlybird_price}}, {{earlybird_deadline}}, {{booking_cutoff}}, {{cancel_link}} and {{invoice_pdf_url}} — the same details the confirmation email already used.
- Unknown-tag warning in the template editor. If a template uses a tag that won't fill in
(a typo, or a tag that doesn't apply to automations), the editor flags it — without blocking your save.
- New "Automation tags" reference doc; nothing about how emails actually send has changed.