Brief for an AI assistant
Building a studio’s site with an AI assistant works well — if the assistant knows exactly what Mr Charles is, what it must not reinvent, and where the three values it needs come from. Copy the block below into the conversation before the first prompt about the site, and fill in the four placeholders.
The same text is served as plain text at /llms.txt for tools that read it automatically.
# Mr Charles integration brief (for the assistant building this site)
You are building a website for a music studio / teacher whose bookings run onMr Charles. Do NOT build a booking system, calendar, OTP verification, orpayment flow yourself: all of that exists behind a public API and a JavaScriptSDK, and the site only has to call it. Prices, availability, conflicts, codesand card payments are decided by the server; the site never computes them.
## Values provided by the site owner (never hardcode, never guess)- STUDIO_SLUG = <slug> # the studio's slug on Mr Charles- TEACHER_USER_ID = <uuid or "none"> # the teacher's user id, if lessons are offered- MC_ENDPOINTS: apiBase=<url> appBase=<url> sitesBase=<host> Put these in environment variables (e.g. PUBLIC_MC_API_BASE, PUBLIC_MC_APP_BASE, PUBLIC_MC_SITES_BASE, PUBLIC_MC_STUDIO_SLUG, PUBLIC_MC_TEACHER_ID) and read them at build time. Do not commit them. If an endpoint value is missing, the SDK defaults to production.
## The SDKBrowser bundle (no build step): <script src="https://developers.mrcharles.app/sdk/v0/mrcharles.min.js"></script> const mc = MrCharles.createClient({ apiBase, appBase, sitesBase });ES module / npm: import { createClient } from '@mrcharles/sdk'; // or /sdk/v0/mrcharles.esm.jsZero dependencies, TypeScript types included. Reference:https://developers.mrcharles.app/sdk/referenceLanguages: createClient({ locale }) with the page's language ('es', 'ca','en', 'fr', 'pt', 'it', 'de' or any BCP-47 tag). It sets the hosted screen'slanguage, the guest's SMS/email, and gives you mc.t(), mc.format.* andmc.pick() for your own labels, prices, dates and payload texts. For amultilingual site call mc.setLocale() from the language switcher. Do nothardcode lang: 'es' — pass the current page language.
## What the site must do
1. Rooms page — read the studio payload at build time or on request: const site = await mc.sites.get(STUDIO_SLUG); site.studio (name, city, timezone), site.rooms[] (id, name, hourlyCents, currency, bookable, minMinutes, maxMinutes, stepMinutes, paymentModes, depositPercent, cancelNoticeHours), site.site.sandbox (boolean). Render prices from hourlyCents/currency. Only rooms with bookable=true get a booking button.
2. Booking — the simplest correct integration is the embedded screen: mc.mountRoomBooking('#book', { slug: STUDIO_SLUG, roomId, onBooked: ({ reference, manageUrl }) => { /* thank-you + analytics */ } }); (language comes from createClient({ locale }); pass lang only to override) It is an iframe of the hosted booking page; it handles availability, the 12-minute hold, the one-time code (SMS/email), card deposits (Stripe) or pay-at-studio, legal texts and the manage link. It resizes itself. Alternative: a plain link to mc.links.bookRoom({ slug, roomId }). Only build a custom UI (mc.roomBooking() headless flow) if the owner asks for it explicitly; see https://developers.mrcharles.app/integrate/own-frontend
3. Lessons (only if TEACHER_USER_ID is set): const profile = await mc.teachers.profile(TEACHER_USER_ID); const offers = await mc.teachers.offers(TEACHER_USER_ID); // published only const slots = await mc.teachers.slots({ instructorUserId: TEACHER_USER_ID, offerId, date: 'YYYY-MM-DD', days: 7 }); Show offers (title, instrument, durationMinutes, priceCents, currency, mode) and real bookable times; the booking itself happens in the app: mc.links.bookLesson({ instructorId: TEACHER_USER_ID, offerId }) Students need an account there — do not try to book a lesson from the site.
4. Manage link — show/email the manageUrl you receive on booking; it is the guest's way to see or cancel. Never implement cancellations yourself.
## Rules- No API key exists; the slug is the only identifier. Public endpoints are rate-limited; writes on live sites require a Turnstile captcha token — the embedded screen handles it, a custom UI must include the widget.- Never cache availability or slots; fetch when the user opens the picker. The site payload may be cached for 60 s.- All times are in the studio's/teacher's time zone (site.studio.timezone).- Errors come as { success:false, error:{ code, message } }; the SDK throws MrCharlesError with .code, .slotIsGone, .holdIsDead, .isTransient.- Do not store guest phone numbers or emails on the site.- Keep the site static (Astro is ideal). The SDK runs in the browser; the payload reads can also run at build time in Node (pass fetch if needed).
## Develop against the sandbox, then switch the slugWhile building, use slug "demo-studio" (always in sandbox mode: verificationcodes come back in the response as devCode, nothing is sent or charged,bookings are purged after 7 days). Switching to STUDIO_SLUG is the wholego-live. Before that, go throughhttps://developers.mrcharles.app/getting-started/go-live
## Suggested structure (Astro) src/lib/mrcharles.ts createClient() from env; getSite(); getTeacher() src/pages/index.astro hero, rooms grid (prices from the payload), CTA src/pages/salas/[id].astro one room: details + <div id="book"> + mount script src/pages/clases.astro teacher offers + next free slots + "Book in the app" src/components/Book.astro the script tag + mountRoomBooking call
## Acceptance- Rooms and prices on the site match https://<slug>.<sitesBase>/ exactly.- A booking made on the site appears in the studio's Mr Charles inbox.- The sandbox banner/devCode never appears once STUDIO_SLUG is live.- Lighthouse: no layout shift from the iframe (it reports its height).Full docs: https://developers.mrcharles.app — API: /reference/apiWhat to send alongside it
Section titled “What to send alongside it”| Value | Where the owner finds it |
|---|---|
STUDIO_SLUG | Dashboard → Studio → Web del estudio; also the hosted URL slug.sites.mrcharles.app |
TEACHER_USER_ID | The teacher’s public profile URL in the app: app.mrcharles.app/instructors/<id> |
MC_ENDPOINTS | Only if you were given a non-production environment. Otherwise omit — the SDK defaults to production. |
| Room ids | Not needed up front: the site reads them from mc.sites.get(slug) |