Configuration

Showtime owns the settings for all three bundled plugins and hands each module its slice at boot. Values you would otherwise have entered three times — Stripe credentials, the from-address, the currency — are entered once and fanned out, with per-module overrides available when you genuinely need something different.

Where the settings live

Everything is at Settings → Plugins → Showtime, or via the Settings item in the Showtime nav. The screen has three parts:

  1. Shared — the Stripe trio, the email identity, and the default currency.
  2. Bookings — Stub’s own settings, inlined.
  3. Memberships — links out to Headcount’s own settings screens, which it ships itself.

Owl has no plugin-settings screen of its own; its configuration lives on the calendars themselves (project config) plus a small handful of PHP-file options covered below.

Shared settings

SettingGoes toNotes
stripe.secretKeyStub, HeadcountMapped to each module’s own stripeSecretKey
stripe.publishableKeyStub, HeadcountMapped to stripePublishableKey
stripe.webhookSecretStub, HeadcountMapped to stripeWebhookSecret
email.fromNameBooking & membership mailThe name on outgoing messages
email.fromEmailBooking & membership mailThe address on outgoing messages
defaultCurrencyHeadcountThree-letter code, e.g. USD

All three Stripe fields accept $ENV_VAR syntax and offer environment-variable autosuggest, so the real values stay in .env:

STRIPE_SECRET_KEY=sk_live_xxx
STRIPE_PUBLISHABLE_KEY=pk_live_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx

Stub and Headcount each have their own webhook endpoint, and Stripe issues a different signing secret per endpoint. If you run both flows, set the shared webhookSecret to whichever you use more and override the other per-module — or leave the shared field empty and set both explicitly.

How a value is resolved

When a module is mounted it is handed a settings array assembled in this order, last wins:

  1. Shared values, translated into that module’s own attribute names.
  2. Per-module overrides, stored under the module’s handle in Showtime’s settings.
  3. config/<handle>.php — the module’s own PHP config file, honoured exactly as it is standalone.

Two details are worth knowing, because both exist to stop a shared value being silently lost:

  • Saving a module’s settings screen stores only its genuine overrides. Values it merely inherited from the shared layer are stripped before storage — otherwise saving Stub’s settings would freeze a copy of the shared Stripe key into Stub, and changing the shared key later would quietly stop reaching it.
  • An empty override for an attribute that has a shared counterpart means “inherit”, not “blank”. A module configured before the shared key existed stores an empty string, and without this rule that empty string would shadow the shared value forever.

PHP config files

Each bundled plugin still reads its own config file, and those values win over everything set in the control panel. This is deliberate: an existing deployment’s config keeps working verbatim after adopting Showtime, and the standalone plugins’ published documentation stays correct.

config/stub.php

<?php

return [
    'defaultTimezone' => 'America/New_York',
    'minimumNotice' => 60,          // minutes before the earliest bookable slot
    'maxAdvanceBooking' => 90,      // days you can book ahead
    'slotInterval' => 15,           // minutes between offered start times
    'autoConfirmFreeBookings' => true,
    'requirePhone' => false,
    'allowCustomerNotes' => true,
    'referencePrefix' => 'STB',
    'paymentEnabled' => true,
    'stripeSecretKey' => getenv('STRIPE_SECRET_KEY'),
    'stripePublishableKey' => getenv('STRIPE_PUBLISHABLE_KEY'),
    'stripeWebhookSecret' => getenv('STRIPE_WEBHOOK_SECRET'),
    'adminEmail' => '[email protected]',
    'sendCustomerConfirmation' => true,
    'sendAdminNotification' => true,
    'sendCancellationEmail' => true,
    'enableHoneypot' => true,
    'bookingsPerHour' => 10,        // per-IP rate limit
    'paymentIntentsPerHour' => 30,
];

config/headcount.php

<?php

return [
    'stripeSecretKey' => getenv('STRIPE_SECRET_KEY'),
    'stripePublishableKey' => getenv('STRIPE_PUBLISHABLE_KEY'),
    'stripeWebhookSecret' => getenv('STRIPE_WEBHOOK_SECRET'),
    'paypalClientId' => getenv('PAYPAL_CLIENT_ID'),
    'paypalClientSecret' => getenv('PAYPAL_CLIENT_SECRET'),
    'paypalEnabled' => false,
    'defaultCurrency' => 'USD',
    'checkoutSuccessUrl' => '/membership/thank-you',
    'checkoutCancelUrl' => '/membership/plans',
    'loginUrl' => '/login',
    'pricingUrl' => '/membership/plans',
];

config/owl.php

<?php

return [
    'occurrenceHorizonMonths' => 24,   // how far ahead recurring events are materialised
    'maxOccurrencesPerEvent' => 5000,  // safety valve on open-ended rules
    'enableDemoTemplates' => false,
];

Per-module overrides in the control panel

Anything you set on Stub’s inlined fields, or on Headcount’s own settings screens, is stored as that module’s override. Leave a field empty to inherit the shared value. Use this when, for example, memberships bill through a different Stripe account from bookings.

Owl’s edition

Owl ships as Lite (free) and Pro ($149). Showtime includes Pro, and asserts that edition when it mounts the module — Craft never license-checks a mounted module, so without that assertion Owl would silently run as Lite and Commerce ticketing would never boot. There is nothing to configure; it is simply on.

Verifying what a module actually received

The quickest check is a settings save round-trip: change a shared value, save, and confirm the behaviour changes in both modules. Note that Craft’s autosuggest fields render only a disabled preview input server-side — the real named input is created by JavaScript at runtime — so grepping the page source for the field name finds nothing even when everything is correct. Test the behaviour, not the markup.