Version 5.5.1

October 15, 2026

Bundles Stub 5.9.1.

Fixed

  • Showtime can no longer be installed alongside the standalone craft-stub, craft-headcount or craft-owl packages. They share namespaces with Showtime's bundled copies, so with both present Composer loaded a mix of the two versions, class by class. Remove the standalone package from composer.json before updating. (#2)
  • Module migrations always run from Showtime's bundled copy. With a standalone package present they ran from that package's folder instead, so a sync migration could be recorded as applied without changing the schema. A site that had both installed should run php craft showtime/migrate/all after updating. (#2)

Version 5.5.0

October 10, 2026

Bundles Headcount 5.4.0.

Added

  • Headcount: GraphQL. headcountPlans and headcountPlan list enabled plans, headcountMembership describes the current user's membership (member or not, active plan handles, isSubscribed(plan:), subscriptions) and headcountAccess(entryId:) returns an entry's gate decision — allowed, why not, the rule's behaviour and the plans that unlock it. Each pair has its own schema permission, Query for membership plans and Query for the current user's membership and access checks. Membership queries only ever answer for the session's own user, and headcountAccess answers only for live entries in sections the schema can read.
  • Queries asking for Headcount fields skip Craft's GraphQL result cache, which is keyed by query rather than by user and would otherwise serve one member's membership to the next.

Changed

  • GET /actions/headcount/api/plan returns the same fields as /plans, adding termType, seasonStart, seasonEnd and currentPrice.

Version 5.4.0

October 8, 2026

Bundles Stub 5.9.0.

Added

  • Event ticket revenue on the dashboard. The monthly revenue table has a line for Owl ticket and registration orders paid this month, and the combined figure now adds it to bookings and MRR. A "Tickets sold this month" card sits with the other stats. Both need Owl ticketing (Commerce); without it the dashboard shows what it did before.
  • Stub: deposits and pay-in-person. A service can be paid in full at booking, by a deposit (a percentage or a fixed sum) with the balance due at the appointment, or in person. Staff record money received with Mark as Paid on the booking, under the new Record payments permission in the Showtime permission group.
  • Dashboard::ticketStats().
  • tests/integration/checks.php.

Changed

  • The dashboard's booking revenue is cash received. It now sums the payments received this month, so a deposit counts in the month it was paid and its balance in the month that was. Ticket orders count in the month they were paid, the same rule.

Version 5.3.4

October 3, 2026

Bundles Stub 5.8.1 and Owl 5.2.1. (The 5.3.3 tag marks the 5.3.2 release below; there is no separate 5.3.3.)

Security

  • Members-only events no longer appear in the ICS feeds. Gated events were already dropped from the page and from owl/events.json, but a calendar's subscription feed and an event's own .ics download had no gate, so every calendar app subscribed to the calendar still showed them. Both feeds now drop what the visitor can't see, and a gated event's own feed is a 404.
  • Stub: Stripe webhooks are refused without a signing secret on Stub's own endpoint — the bundle's Stripe routing already refused them.
  • Stub: the public booking form checks the slot — an enabled provider who offers the service, at a time the form would offer. It accepted any time and provider it was posted.
  • Stub: an anonymous booking can't rename an existing customer, only fill in what's missing.
  • Owl: events.json answers for at most 400 days and 2,000 occurrences, and a calendar's colour must be a colour.

Added

  • Stub's reminder emails and manual bookings (Stub 5.8.0), with a sync migration that brings an existing install's mounted Stub up to them.

Fixed

  • The bundled Stub had drifted from the standalone plugin (17 files); it is now the same code.
  • The dashboard's stat cards use a stylesheet instead of inline styles.

Version 5.3.2

October 2, 2026

Bundles Headcount 5.3.3.

Security

  • PayPal webhooks are refused without a webhook ID. Every PayPal webhook was accepted when none was configured, so anyone who knew a subscription's I-… id could activate, suspend or cancel it. Set the webhook ID PayPal shows for your endpoint; the settings screen warns until you do. (Stripe webhooks were already safe here: the bundle's own Stripe routing refuses an empty signing secret, and standalone Headcount now does too.)
  • The Headcount API key and outgoing webhook secret resolve environment variables. The settings fields suggested $ENV_VAR values but used them as typed, so $HEADCOUNT_API_KEY made that literal, guessable string the key — enough to read any member's details. A variable that doesn't resolve now counts as unset.
  • The billing portal only returns members to this site, rather than to any returnUrl in the link.
  • The anonymous Apple Wallet log endpoint is bounded per request and per address.

Fixed

  • The memberships index returned HTTP 500 whenever the status column was shown. The bundled copy of Headcount still had the string status colours that Headcount 5.3.2 replaced with craft\enums\Color cases. The module is now in step with Headcount 5.3.3 — bin/sync-modules.sh keeps the copies identical, and the two have to move together.

Version 5.3.1

August 26, 2026

Fixed

  • The events index showed no event names. Showtime carries its own copy of Owl's source under src/modules/owl, and that copy's defineDefaultTableAttributes() omitted title — so the screen listed a calendar name and two dates per row and never said which event each row was. Fixed here and in craft-owl 5.2.1; the two copies have to be kept in step.

Version 5.3.0

August 16, 2026

Bundles Stub 5.7.0.

Added

  • Picks up Stub's frontend service filtering. craft.stub.services() and craft.stub.bookingForm() now take an optional filter, so a page can offer one provider's services rather than every service on the site — craft.stub.bookingForm({ user: currentUser }) for a provider's own booking page, { handle: 'consultation' } for a page built around a single service. Filter by service id/handle, by provider (ID, handle or model), or by user — the Craft user a provider is linked to.
  • A filtered booking form drops the steps a filter has already answered: one service skips "select a service", one provider skips the provider step and opens on the calendar. The progress bar and Back buttons follow.
  • craft.stub.service(idOrHandle) and craft.stub.provider(idOrHandleOrUser).

Notes

  • Filtering is a display concern. Stub's booking endpoints are anonymous and take a service ID from the request, so a filtered list narrows what a visitor sees, not what they may do.
  • Nothing changes for a template that calls craft.stub.services() or craft.stub.bookingForm() with no arguments.

Version 5.2.1

August 15, 2026

Bundles Headcount 5.3.1.

Security

  • The membership settings screens now render read-only when allowAdminChanges is off, rather than offering fields and a save button that would be refused on submit. Saving was already blocked; this stops the screen implying otherwise.

Changed

  • The membership settings screens are now a navigable section: Stripe, PayPal, Wallet Cards, Emails and a new API & Webhooks screen each get their own page with a shared sidebar, instead of URLs that only this bundle's settings screen linked to. The links here now include API & Webhooks.

Fixed

  • Picks up Headcount's fix for GET /api/plans reporting the wrong seasonStart — it gave the joining member's start date rather than the season's. Behaviour change for anything reading that field since Showtime 5.2.0.
  • Picks up Headcount's fix for the Enforce Access Rules setting being unchangeable from the control panel — the field was shown and honoured, but never saved.
  • Picks up Headcount's fix for the membership Settings screen rendering with no styling. The screen linked from Showtime → Settings → Memberships → General served raw form fields with no control-panel layout, because the controller was rendering a template written as a fragment for Craft's own plugin-settings page.
  • The wallet card switches now also appear on that all-in-one screen, not only on the dedicated Wallet Cards screen this bundle links to.

Version 5.2.0

August 15, 2026

Bundles Headcount 5.3.0.

Added

  • Picks up Headcount's season memberships: a membership plan can now run to a fixed calendar window shared by every member — a club's July–June year — instead of billing on each member's own anniversary, with the window rolling forward automatically each year and optional pro-rata pricing for anyone joining mid-season. Season plans are charged as a one-off Stripe payment, so they can't be paid for with PayPal.
  • Picks up Headcount's Apple Wallet and Google Wallet membership cards, configured under a new Memberships → Wallet Cards settings screen, linked from Showtime's composite settings page. The credentials are the site owner's own Apple Pass Type ID certificate and Google Wallet issuer account. Apple cards keep themselves up to date on the device when a membership changes.
  • Two new membership commands worth a daily cron entry: headcount/subscriptions/expire (now retires finished season terms as well as cancelled memberships) and headcount/subscriptions/remind (the expiration reminder email, which previously had no caller anywhere in the bundle and never sent).

Fixed

  • Headcount's expiration reminder email was never sent, and subscriptions past their end date that the member hadn't cancelled were left active indefinitely. Both are fixed upstream and come in with this sync.
  • src/modules/headcount/services/Gating.php carried a hand-edited @deprecated in 5.5.0 note that never matched any release; the sync restores Headcount's own 5.2.0.

Version 5.1.0

August 13, 2026

Added

  • Picks up Stub's currency work: 25 common currencies instead of 5 (CHF among them), and any currency configured in Craft Commerce when it's installed. The shared Default Currency field is now a picker drawn from the same list Stub's own screen uses, so the two can't drift apart. Its empty "use each module's own default" option is unchanged.
  • Showtime's shared currency is now validated as an ISO 4217 code. It's pushed into Stub and Headcount, both of which validate it, so a typo is caught on the screen it was typed into rather than being rejected later by a module with no visible field to blame.

Fixed

  • The composite settings screen would have rendered an empty currency dropdown for bookings. Stub's settings fragment is included with only, and it now needs a currencyOptions variable that Showtime wasn't passing — Stub's own settingsHtml(), which normally supplies it, never fires for a mounted module.

Version 5.0.0

July 26, 2026

First release. Showtime is the Owl, Stub and Headcount plugins combined into one plugin under a single Craft licence, plus the features that only exist because they ship together.

Added

The bundle

  • Owl (events and calendars), Stub (bookings and appointments) and Headcount (memberships and subscriptions) run as internal modules of one plugin. Each keeps its own namespace, services, templates, controllers, database tables and migration track; none is registered with Craft's Plugins service, so only Showtime's licence is enforced.
  • One control-panel section. A single Showtime nav item over the modules' existing routes, one combined permission heading — with the permission keys unchanged, so existing user groups keep working — and one composite settings screen.
  • A bundle dashboard at Showtime: today's bookings, this week's events, active members and combined revenue. Degrades to whatever is mounted, and shows booking income and MRR as separate components as well as a total, since summing them alone would mislead.
  • Shared settings. One Stripe account, one from-address, one currency — entered once and handed to each module, with per-module overrides and config/<handle>.php still honoured.

Features only the bundle can offer

  • Member perks. A Headcount plan can discount a Stub service or an Owl event ticket, or restrict either to members. Booking discounts are applied before Stub derives the Stripe amount, so a member is charged less rather than merely shown less; ticket discounts are a promotional price on the Commerce line item, never a change to the shared purchasable. Members-only is enforced where a request can actually be refused, so a crafted POST or a known purchasable ID doesn't get past it. Overlapping plans resolve to the lowest price.
  • Member-only events. Headcount's access rules can target Owl events — all of them, one calendar's worth, or a single event — with the usual redirect / paywall / hide behaviours. A gated event also drops out of the anonymous owl/events.json feed and its tickets stop being buyable, because a gate that only covers the page isn't a gate.
  • Provider events block appointment slots. Someone teaching a class at 10am is no longer bookable for a 1:1 at 10am. Managed under Showtime → Provider calendars.
  • Bookings on the events calendar. Staff get one calendar instead of two screens. Owl's feed is anonymous and bookings carry customer names, so bookings are added only for a viewer who holds stub:viewBookings.
  • One Stripe webhook endpoint for the whole bundle — /actions/showtime/webhook/stripe. The signature is verified once and the event routed by type. Each module's own endpoint still works and behaves identically, so an existing Stripe configuration keeps working.
  • One outgoing sender and one notifications screen. A from-name and from-address entered once apply to every email the bundle sends; Showtime → Notifications lists all of them with their switches, their available variables and a link to edit the wording. The copy itself lives in Craft's system messages, so it renders through the same email template as the rest of the site's mail.
  • The identity graph. Showtime → People shows one person's bookings, membership and event tickets together, and craft.showtime.person(user|email) gives templates the same object. Nothing is merged and nothing is stored — the three plugins keep their own schemas and the join happens at read time on the email address.

Upgrading from the standalone plugins

  • Installing Showtime adopts an existing Stub, Headcount or Owl install in place, without moving a row of data. Do not uninstall the standalone first — that runs its install migration down and drops your bookings, members or events.

    composer require justinholtweb/craft-showtime
    php craft plugin/install showtime      # adopts whatever is already installed
    composer remove justinholtweb/craft-stub justinholtweb/craft-headcount justinholtweb/craft-owl
    

    The last step matters: while both packages are present Composer reports "Ambiguous class resolution" and may load the standalone's classes instead of the bundled copies.

Requires

  • Craft CMS 5.0+ and PHP 8.2+
  • Craft Commerce 5.0+ only for event ticketing, which is dormant without it.