Use this file to discover all available pages before exploring further.
Tymeslot’s booking pages are fully themeable. The theme system is built on an Elixir behaviour contract, a centralized catalog and registry, and a modular CSS architecture — giving each theme complete visual independence while sharing all booking logic. Tymeslot ships with two themes: Quill (glassmorphism aesthetic) and Rhythm (full-bleed video backgrounds). You can build additional themes using the same patterns.
Elixir behaviour all theme modules must implement.
TymeslotWeb.Themes.Shared.SchedulingLive
Web
Macro that injects all common LiveView callbacks into a theme’s live.ex.
TymeslotWeb.Themes.Shared.StateMachineHelpers
Web
Shared state transitions and navigation guards for all themes.
TymeslotWeb.Themes.Core.Dispatcher
Web
Dynamically loads and dispatches to the correct theme based on a user’s profile setting.
There is no per-theme state_machine.ex. State transitions live entirely in the shared TymeslotWeb.Themes.Shared.StateMachineHelpers. Both Quill and Rhythm have removed their local state machines. Do not create a new state_machine.ex file for your theme.
Themes may add extra internal structure beyond the above. Quill nests additional panel components under scheduling/components/schedule/panels.ex; Rhythm keeps a shared/ directory for components reused only within that theme.
Registry merges the two at compile time into the full theme_definition the web layer consumes. Domain code reads facts directly from Catalog and never reaches into the web layer.
Use the SchedulingLive macro. It injects mount/3, handle_params/3, all handle_info/2 clauses, and the standard handle_event/3 handlers. Your live.ex only needs render/1 and, optionally, handle_theme_event/3 or handle_theme_schedule_event/3 overrides for theme-specific events.
Each theme’s CSS is completely isolated from the global app styles.
/* assets/css/scheduling/themes/aurora/theme.css *//* Import shared structural primitives */@import "../../shared/reset.css";@import "../../shared/layout.css";@import "../../shared/utilities.css";/* Foundation — variables MUST come first */@import "./modules/variables.css";@import "./modules/base.css";@import "./modules/iframe.css";@import "./modules/typography.css";/* Feature modules (order among these is not significant) */@import "./modules/schedule-header.css";@import "./modules/calendar.css";@import "./modules/time-slots.css";@import "./modules/booking-form.css";@import "./modules/custom-questions.css";@import "./modules/overview.css";@import "./modules/confirmation.css";@import "./modules/payment-pages.css";@import "./modules/language-switcher.css";
The module split is per-theme, not canonical. Quill breaks UI controls into many small files (glass-card.css, buttons.css, animations.css, etc.); Rhythm consolidates them into a single components.css. Match whichever granularity suits your theme. The only universally expected modules are variables.css, base.css, and iframe.css.
Themes use CSS container queries and fluid sizing instead of viewport breakpoints. Set container-type: inline-size; container-name: scheduling; on your primary content container (e.g. .aurora-card), then use @container scheduling (...) queries in each component file.
Do not use responsive Tailwind classes (sm:, md:, lg:) in theme templates. Use semantic CSS class names describing what the element is (.calendar-grid, .duration-card), not how it looks.
Run the production checklist to verify your theme end-to-end:
# Test all registered themesmix test apps/tymeslot/test/tymeslot_web/live/themes/theme_production_checklist_test.exs# Test a specific theme by IDmix test apps/tymeslot/test/tymeslot_web/live/themes/theme_production_checklist_test.exs -t theme_id:3
The checklist automatically verifies that all meeting types render, edge cases are handled (no meetings, long names), basic mobile responsiveness works, and state transitions function correctly.
You rarely write event-handling, initialization, or formatting code by hand — the SchedulingLive macro wires everything up. These are the underlying modules it calls, documented for when you need to override or extend behaviour:
Declare which background types your theme supports in the features map in Catalog:
Feature flag
What it enables
supports_video_background
Preset and user-uploaded video backgrounds
supports_image_background
Preset and user-uploaded image backgrounds
supports_gradient_background
CSS gradient background presets
supports_custom_colors
User-selectable primary colour via CSS variable injection
The Tymeslot.ThemeCustomizations.Capability module reads these flags and generates the correct CSS variables based on the user’s selection. The custom_css string arrives as a ready-to-emit socket assign — render it inside a :root { … }<style> block in your wrapper; do not generate it yourself.