Booking
Skill seldonframe/seldonframe/packages/crm/src/blocks/booking
Open-source AI front office for local service businesses: AI receptionist (voice/SMS/chat) + website + CRM + booking. Self-hostable or $29/mo flat. The open-source GoHighLevel alternative.
npx -y skills add seldonframe/seldonframe --skill bookingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 16 stars16 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
The booking page (calendar) — what visitors see when they hit /book. Title, description, slot duration, location kind, weekly availability hours, and the form fields collected at booking time.
SKILL.md
10.8 KB, as published. Nobody here has run it
Booking Block — generation prompt
You are configuring the booking page (the calendar visitors hit at /book). v1's hardcoded defaults leaked "Free consultation / 30-minute conversation" into every workspace whose vertical wasn't in the curated list. v2's job is to produce booking metadata that matches the actual primary appointment of THIS business.
The mental model
The booking page is where intent becomes commitment. The visitor scrolled through the hero, the services, the FAQ — and clicked "Book". They expect the calendar to confirm:
"Yes, this is the right place to book the thing I came here for."
A grooming customer expects "Book Your Dog's Mobile Grooming". A legal customer expects "Book a Free 30-Minute Consultation". A barbershop customer expects "Book Your Cut". The title alone, before they pick a date, has to feel right.
Voice rules
- Title names the actual appointment. Match what the visitor came to book. NOT "Free consultation" unless that IS the appointment.
- Duration matches the vertical. Don't put 30 minutes for a 90-minute grooming. Don't put 60 minutes for a 15-minute nail trim.
- Location kind is structural, not stylistic. Pick the real one based on how the business operates. HVAC = on-site-customer. Barbershop = on-site-business. Coach = video unless they specifically meet in person.
- Availability matches the trade. A bar opens at 4pm. A mobile groomer works 9-6. An HVAC tech is on-call 7am-7pm. Pick believable hours; skipping days is fine ("Closed Sunday").
- Form fields are EXTRAS only. The server always adds standard name + email — DO NOT include them in form_fields (they'll be deduped). Only add genuine operator-specific extras: "Dog's name" for a groomer, "Service address" for HVAC, "Party size" for a restaurant. Skip the array entirely for simple bookings.
Worked examples
Mobile dog grooming
{
"title": "Book Your Dog's Mobile Grooming",
"description": "Pick a slot and we'll come to your driveway in our converted van. One dog at a time, no kennels, no waiting. Please confirm your dog's size and coat type so we can plan the visit.",
"duration_minutes": 90,
"location_kind": "on-site-customer",
"weekly_availability": {
"mon": [9, 18],
"tue": [9, 18],
"wed": [9, 18],
"thu": [9, 18],
"fri": [9, 18],
"sat": [9, 16],
"sun": null
},
"form_fields": [
{ "id": "dog_name", "label": "Your dog's name", "type": "text", "required": true },
{ "id": "dog_breed", "label": "Breed", "type": "text", "required": true, "placeholder": "e.g. Goldendoodle, Mixed" },
{ "id": "service_address", "label": "Service address", "type": "text", "required": true },
{ "id": "notes", "label": "Anything we should know? (anxiety, sensitivities, etc.)", "type": "textarea", "required": false }
]
}
HVAC
{
"title": "Schedule HVAC Service",
"description": "Pick a 60-minute window and we'll dispatch a technician. Same-day available for emergencies. Please confirm the equipment type so we arrive with the right parts.",
"duration_minutes": 60,
"location_kind": "on-site-customer",
"weekly_availability": {
"mon": [7, 19], "tue": [7, 19], "wed": [7, 19], "thu": [7, 19], "fri": [7, 19],
"sat": [8, 16],
"sun": null
},
"form_fields": [
{ "id": "service_address", "label": "Service address", "type": "text", "required": true },
{ "id": "equipment_type", "label": "Equipment", "type": "select", "required": true, "options": ["Central AC", "Furnace", "Ductless mini-split", "Heat pump", "Water heater", "Other"] },
{ "id": "issue", "label": "What's going on?", "type": "textarea", "required": false }
]
}
Legal (consultative)
{
"title": "Book a Free Consultation",
"description": "30 minutes, in person at our Vancouver office or by phone. We'll listen, give you our honest read on your options, and tell you whether we're the right fit. No obligation either way.",
"duration_minutes": 30,
"location_kind": "hybrid",
"weekly_availability": {
"mon": [9, 17], "tue": [9, 17], "wed": [9, 17], "thu": [9, 17], "fri": [9, 17],
"sat": null, "sun": null
},
"form_fields": [
{ "id": "matter_type", "label": "Type of matter", "type": "select", "required": true, "options": ["Divorce", "Custody / Parenting", "Mediation", "Estate planning", "Other"] },
{ "id": "preferred_format", "label": "Preferred format", "type": "select", "required": true, "options": ["In-person at our office", "Phone"] },
{ "id": "summary", "label": "Briefly, what's the situation?", "type": "textarea", "required": false }
]
}
Barbershop
{
"title": "Book Your Cut",
"description": "Pick a time, walk in, sit down. Standard cuts run 30 minutes; combo cut + beard runs 60. If you're a first-timer, mention what you're going for in the notes.",
"duration_minutes": 30,
"location_kind": "on-site-business",
"weekly_availability": {
"mon": null,
"tue": [10, 19], "wed": [10, 19], "thu": [10, 19], "fri": [10, 19],
"sat": [9, 17],
"sun": [10, 16]
},
"form_fields": [
{ "id": "service", "label": "What service?", "type": "select", "required": true, "options": ["Haircut", "Beard trim", "Cut + beard combo", "Kids cut"] },
{ "id": "notes", "label": "Anything we should know?", "type": "textarea", "required": false }
]
}
Output format
Return ONLY a single JSON object matching the props schema. No prose, no
markdown fences. The persistence endpoint runs JSON.parse directly.
If the operator gave you minimal context (no service hours, no clear
primary service), default to weekday business hours (mon-fri, 9-17) and
pick the duration that matches the OBVIOUS primary service from the
business description. Don't invent extra form fields just to fill space —
omit form_fields entirely if name + email is sufficient.