Use cases · Classes & memberships

Fitness studio

A boutique studio running scheduled classes — spin, yoga, strength — with hard capacity, waitlists, and check-in. Members pay monthly; drop-ins buy class packs. A no-show on a packed class costs someone else a spot, so the rules around capacity, packs, and fees have to be exact.

The shape

A class is a Seldon EventSession under an EventSeries, projected through an open_capacity Availability that caps seats; a Registration is the roster spot with a waitlist, and Attendance records check-in. Membership tiers and entitlement live in Terminus; class packs are Mallow stored value; recurring dues run through Daneel + Payments.

  • Seldon models the timetable as an EventSeries of EventSessions. An open_capacity Availability enforces the seat cap; Registration handles booking + waitlist; Attendance records who actually showed. One-on-one PT uses a variable-duration grid instead.
  • Terminus holds members as Persons. An "Unlimited" plan is a RankedGroup(kind=tier) with a TierDefinition auto-enrolment rule; member-only classes gate on checkEntitlement.
  • Mallow runs class packs as stored value — a 10-class pack is a StoredValueAccount, and each booking burns one with a StoredValueTransaction. Monthly membership dues post to the same ledger.
  • Payments charges recurring dues on a stored credential (MIT / merchant-initiated), so the monthly run doesn't need the member present.
  • Daneel owns the recurring-billing workflow and the no-show fee that fires off the Seldon no_show emission.
  • Speaker sends class reminders (consent-gated; the studio's operator app is an installable PWA on the push channel).

Walk-through

Book a class

A member books Saturday's 9am spin. Seldon checks the open_capacity seat cap and, because it's a member-only class, calls Terminus checkEntitlement against her Unlimited tier. Both pass; a Registration lands her on the roster.

Sell out and waitlist

The series fills. The next member to register enters the waitlist (a Registration in waitlisted status, with a position). When a confirmed member withdraws, Seldon moves the head of the waitlist to confirmed in the same transaction. No message goes out on that promotion today, so the studio tells the member.

Drop-in on a class pack

A non-member books with a 10-class pack. There's no entitlement tier, so booking redeems one credit from her Mallow StoredValueAccount — a single StoredValueTransaction — and the roster spot is hers. The pack balance is now nine.

Check-in

At the door, the front desk taps her in; Seldon records Attendance against the Registration. A no-show, by contrast, leaves the Registration unattended — the Seldon no_show emission triggers a Daneel workflow that books the studio's late-cancel fee against the member.

Monthly dues

On the first, Daneel's billing workflow runs the membership roster: for each active tier member, Payments charges the stored credential merchant-initiated, Mallow posts the dues to the ledger, and a failed charge opens a dunning sub-flow rather than silently lapsing the membership.

Why this is hard without LatticeKit

Studio software usually bundles scheduling, memberships, and billing into one closed monolith — great until you want the class pack to draw from the same ledger as the retail counter, or the no-show fee to reconcile against the same invoices as dues. Here capacity, entitlement, stored value, and recurring billing are separate primitives that compose: the seat cap is Seldon's, the tier gate is Terminus's, the pack balance is Mallow's stored-value ledger, and the monthly charge is Payments' MIT path — so a refunded class credit and a failed dues charge both land in the one ledger your accountant already reads.