One scheduling engine. Every product.
Booking and calendar built once in aumik-agents, reused by every brand through shared widgets and a self-service portal. No per-product booking code, no third-party scheduler.
See the provider side → Try a bookingThe modules
.ics feeds + CalDAV. Read-only egress.Same modules, every product
| Product | Resource | What gets booked |
|---|---|---|
| aumik-astro | Reader | A reading session |
| aumik-cleaning | Crew | A cleaning job |
| aumik-conferences | Room / track | A talk slot (event) |
| aumik-hospitality | Suite | A stay |
| aumik-dooh | Screen | Dayparting / ad slot |
Switch the product context (top-right) to see the same screens re-skinned per brand.
Where it lives
| Layer | Home |
|---|---|
| Engine (availability · book · events) | aumik-agents · Postgres + Hono |
| Embeddable UI | @aumik/widgets · <BookingScheduler/> |
| Self-service shell | @aumik/portal · My bookings |
| Notifications | Novu (infra#19) |
| Publish feeds | .ics + CalDAV (Radicale, infra#16) |
Tracking: Scheduling Platform epic → booking child infra#18.
Availability
Provider portal · your open hours feed the customer booking calendar
Weekly hours · ET · tap a cell to toggle
open blocked
Booking rules
Calendar
Provider portal · bookings and events together · one source of truth
Events
Provider portal · calendar entries that aren't bookings — talks, meetups, holds
New event
Events share the calendar with bookings but don't consume booking slots unless you mark them busy.
Publish & subscribe
Provider portal · let your bookings show up in the calendar apps you already use
Your calendar feed
A private, read-only link. Subscribe to it in Apple Calendar, Google Calendar, or Outlook and your bookings + events appear automatically.
webcal://cal.e4keih.uncld.dev/r/priya-r/feed.icsCopy link Reset link
CalDAV (advanced)
Point a CalDAV client at the box to subscribe per-calendar.
Server cal.e4keih.uncld.dev User priya-r Calendar bookings
.ics is read-only egress (Radicale, infra#16). No two-way Google/Outlook sync — that was an explicit decision (infra#18).Book a time
aumik-astro · with Priya R. (Vedic reader)
Pick a date
Outlined = open. Times shown in your timezone (ET).
Available times · Mon Jun 22
Slots come from the reader's open hours, minus what's already booked, time off, the 15-min buffer, and 12-hour min-notice.
Session
You're booked ✓
A confirmation just went out by WhatsApp + email. We'll remind you 24h and 2h before.
Your booking
| When | Mon Jun 22, 2026 · 2:00–2:45pm ET |
| With | Reader |
| How | Video call |
| Ref | BKG-4QF29 |
What happens next
All via Novu — honors your channel preferences.
My bookings
aumik-astro · signed in as Suresh S.
Upcoming
Past
Same “My bookings” shell (@aumik/portal) for every product — only the labels change.
Embed the scheduler
Any product drops in one widget — it talks to the shared engine
One widget, configured per brand
<AumikWidgetProvider agentsBaseUrl="https://agents.aumik.co" brand="astro"> <BookingScheduler resource="priya-r" /> </AumikWidgetProvider>
Lives in @aumik/widgets. The same component renders the date picker + slots you saw on the customer side.
Where it's used
API contract
What the engine exposes · multi-tenant by {resource}
Scheduling endpoints (aumik-agents)
GET /api/scheduling/{resource}/availability?from&to
POST /api/scheduling/{resource}/book
PATCH /api/scheduling/{resource}/bookings/{id} # reschedule
DEL /api/scheduling/{resource}/bookings/{id} # cancel
GET /api/scheduling/{resource}/events
GET /api/scheduling/{resource}/feed.ics # publish (read-only)
Data model
resources slug, product, timezone, default_hours, buffer
availability_rules weekday, start, end (+ availability_overrides)
bookings resource, tstzrange, status, contact
└─ EXCLUDE USING gist (resource, tstzrange) ← no double-book
events resource, range, all_day, visibility, busy?
notification_prefs per-user channel prefs (Novu)
Times stored UTC; converted per resource timezone at query time (DST-safe).