Prompts for Claude Code
Each prompt below is a complete brief. Open Claude Code at the root of the project you want to change, paste one, and answer the questions it comes back with (usually your booking page's slug, sometimes your clndr.pro username). The prompts tell the agent which docs pages to read, spell out the facts it tends to get wrong, and end with a "done when" list it should check before stopping.
They assume:
- you have a clndr.pro account with at least one booking page and some availability,
- you'll create the key yourself under API keys and put it in
.env.local. The prompts never ask for the key's value, and you shouldn't paste it in, - Claude Code can fetch URLs. If it can't, install the skill first; it carries the same facts offline.
Not sure which one you need? Start with the first. It looks at the project and picks.
Any project
Add clndr.pro booking to this project
Add clndr.pro booking to this project.
Read these first. They are Markdown pages written for coding agents:
- https://docs.clndr.pro/llms.txt (index of every docs page)
- https://docs.clndr.pro/integration-options.md
- https://docs.clndr.pro/nextjs.md for a Next.js app, otherwise https://docs.clndr.pro/react/components.md or, for a site without React, https://docs.clndr.pro/embed/script.md
Facts to rely on:
- API base URL: https://www.clndr.pro/api/v1. Always the www host: the bare domain redirects and the redirect drops the Authorization header.
- Packages: @clndr-pro/react (components and hooks, browser) and @clndr-pro/sdk (typed client, mainly server). Use @clndr-pro/react 0.2.1+ and @clndr-pro/sdk 0.1.5+. With older versions, pass baseUrl "https://www.clndr.pro".
- Import @clndr-pro/react only from files marked 'use client'.
- Publishable key (clndr_pk_...) goes in NEXT_PUBLIC_CLNDR_PUBLISHABLE_KEY. It is browser-safe and can read booking pages and slots and create bookings.
- Secret key (clndr_sk_...) goes in CLNDR_SECRET_KEY. Server only. It can also list, confirm and cancel bookings. Never import it into client code.
Steps:
1. Look at the project: framework and router, styling (Tailwind? shadcn/ui under components/ui?), and where a booking page fits. Tell me what you found and which integration you'll use before you change files.
2. Ask me for the booking page slug. Ask for my clndr.pro username too if you pick an embed.
3. Add the env vars to .env.example with placeholder values and tell me to put the real keys in .env.local.
4. Build it with the project's existing components and styles.
5. Run the type checker and the build, and fix what breaks.Next.js
Drop-in booking page with shadcn components
Add a /book page to this Next.js App Router app that shows my clndr.pro booking form, rendered with this project's own shadcn/ui components.
Read first: https://docs.clndr.pro/quickstart.md, https://docs.clndr.pro/nextjs.md and https://docs.clndr.pro/react/styling.md
Facts:
- Install @clndr-pro/react 0.2.1 or later. It talks to https://www.clndr.pro by default.
- ClndrProvider takes publishableKey={process.env.NEXT_PUBLIC_CLNDR_PUBLISHABLE_KEY!}. Put it in its own app/providers.tsx ('use client') and wrap {children} in app/layout.tsx with it. Don't make the root layout a client component.
- <BookingInline slug="..." /> renders the whole flow: date, slots, the host's questions, confirmation. Import it only from a 'use client' file; keep app/book/page.tsx a Server Component that renders that client file.
- Restyle it with components={{ Button, Input, Label, Textarea }} (pass the shadcn components) and classNames={{ root, heading, muted, slotGrid, slotButton, ... }} (Tailwind classes). The full slot and className list is in react/styling.md.
- The page's description is Markdown; it renders automatically.
Steps:
1. Check that shadcn/ui is set up (components.json, components/ui). Add button, input, label and textarea with the shadcn CLI if missing.
2. Ask me for the booking page slug.
3. Create app/providers.tsx, update app/layout.tsx, create app/book/page.tsx and app/book/booking-widget.tsx.
4. Map the slots to our components and theme tokens so it matches the rest of the site in light and dark mode.
5. Add NEXT_PUBLIC_CLNDR_PUBLISHABLE_KEY to .env.example; tell me to set it in .env.local. Run the type checker and build; fix what breaks.
Done when: /book renders without hydration warnings, every @clndr-pro/react import sits in a 'use client' file, and the form uses our Button and Input.Custom booking widget with shadcn/ui and the hooks
Build a custom booking widget for my clndr.pro booking page in this project, using shadcn/ui and the @clndr-pro/react hooks instead of the built-in form: a calendar, open times for the picked day, the host's questions, and a confirmation state.
Read first: https://docs.clndr.pro/tutorials/shadcn-booking-widget.md, https://docs.clndr.pro/react/hooks.md and https://docs.clndr.pro/concepts.md
Facts:
- @clndr-pro/react 0.2.1+. Hooks need <ClndrProvider publishableKey={process.env.NEXT_PUBLIC_CLNDR_PUBLISHABLE_KEY!}> above them, in a 'use client' file.
- useBookingPage(slug) -> { data: { bookingPage, userProfile, questions } | null, isLoading, error }.
- useAvailableSlots(slug, date: Date | null) -> { slots: [{ start, end }], isLoading, error, refetch }. The date is read as a calendar day in the HOST's timezone (userProfile.timezone). Build it as new Date(year, monthIndex, day), never new Date('YYYY-MM-DD').
- useCreateBooking() -> { create, isLoading, error, data }. create({ bookingPageId: bookingPage.id, guestName, guestEmail, startTime: slot.start, endTime: slot.end, responses: [{ questionId, answer }] }). Send slot times unchanged.
- Show slot times in the guest's local timezone. Past slots are already excluded; days past bookingPage.max_days_ahead return no slots, so disable them in the calendar.
- question_type is text | email | textarea | phone | select (with options) | checkbox. The API doesn't enforce is_required: validate in the form.
- booking_type 'approval' means the booking is pending: say "Request sent", not "Booked". A taken slot fails with HTTP 409 (message starts "This time slot"): call refetch() from useAvailableSlots.
- bookingPage.description is Markdown.
Steps:
1. Check shadcn/ui is set up; add calendar, button, card, input, label, textarea and skeleton if missing.
2. Ask me for the booking page slug and where the widget should live.
3. Build the widget as one 'use client' component with loading skeletons, an empty state for days with no times, inline errors and a success state.
4. Add NEXT_PUBLIC_CLNDR_PUBLISHABLE_KEY to .env.example. Run the type checker and build; fix what breaks.
Done when: it works with the keyboard, looks right in light and dark mode and at 375px wide, and a booking made with it shows up under Meetings in the clndr.pro dashboard.A "Book a call" button that opens a dialog
Add a "Book a call" button to this site's header that opens my clndr.pro booking form in a shadcn/ui Dialog, without leaving the page.
Read first: https://docs.clndr.pro/tutorials/shadcn-booking-dialog.md and https://docs.clndr.pro/react/components.md
Facts:
- @clndr-pro/react 0.2.1+, imported only from 'use client' files. ClndrProvider with publishableKey={process.env.NEXT_PUBLIC_CLNDR_PUBLISHABLE_KEY!} must be above the button (app/providers.tsx wrapping {children} in the root layout).
- Render <BookingForm slug="..." components={{ Button, Input, Label, Textarea }} onBooked={...} /> inside the Dialog. Use the project's shadcn Dialog rather than the package's BookingModal, so focus trapping, escape and styling match the site.
- onBooked(bookingId) fires after a successful booking. Keep the confirmation visible for a moment, then close the dialog.
- The form fetches the booking page when it mounts, so render it only while the dialog is open.
Steps:
1. Find the site header/navbar component and check shadcn/ui (add dialog and button if missing).
2. Ask me for the booking page slug and the button label.
3. Build a 'use client' BookCallButton and put it in the header. Make the dialog scroll on small screens.
4. Add NEXT_PUBLIC_CLNDR_PUBLISHABLE_KEY to .env.example. Run the type checker and build; fix what breaks.
Done when: the dialog opens from the keyboard, closes on Escape, and the header stays a Server Component if it was one.Book through a server action
Build a /book page in this Next.js App Router project that books clndr.pro meetings through a server action, so the browser never calls clndr.pro and no clndr.pro key reaches the client.
Read first: https://docs.clndr.pro/tutorials/server-actions.md and https://docs.clndr.pro/sdk.md
Facts:
- @clndr-pro/sdk 0.1.5+; client in lib/clndr.ts with `import 'server-only'` and new Clndr(process.env.CLNDR_SECRET_KEY!). Never use NEXT_PUBLIC_ for the secret key.
- clndr.bookingPages.get(slug) -> { bookingPage, userProfile, questions }. clndr.bookingPages.getSlots(slug, 'YYYY-MM-DD') -> [{ start, end }]; the date is a calendar day in the host's timezone and past slots are excluded.
- clndr.bookings.create({ bookingPageId, guestName, guestEmail, startTime, endTime, responses }) with slot start/end unchanged. booking_type 'approval' -> "Request sent".
- The API doesn't enforce required questions. Re-check the slot is still in getSlots() right before create. Errors throw ClndrError { status, message }.
Steps: follow the tutorial's structure (lib/clndr.ts, app/book/page.tsx, app/book/actions.ts with zod, app/book/booking-form.tsx with useActionState). Ask me for the slug first. Add CLNDR_SECRET_KEY to .env.example. Run the type checker and build; fix what breaks.
Done when: no 'use client' file imports lib/clndr.ts, slot times show in the guest's timezone, and a taken slot shows a clear message.Server side
Approvals screen in my admin
Add an admin page at /admin/bookings that lists pending clndr.pro bookings with the guest's answers and lets me approve or decline them.
Read first: https://docs.clndr.pro/tutorials/approvals-dashboard.md and https://docs.clndr.pro/types.md
Facts:
- Secret key, server only: lib/clndr.ts with `import 'server-only'`, new Clndr(process.env.CLNDR_SECRET_KEY!) from @clndr-pro/sdk 0.1.5+.
- clndr.bookings.list({ status: 'pending', limit }) (latest start first, max 200). clndr.bookings.get(id) adds meeting_responses [{ question_id, answer }] (not in the SDK type: cast). Question text: clndr.bookingPages.get(slug).questions.
- Approve: clndr.bookings.update(id, { status: 'confirmed' }). Decline: update(id, { status: 'cancelled', reason }).
- API approvals send no clndr.pro email; Google invites the guest only when the page makes Meet links. Declines send nothing. We send our own emails.
Steps: find the project's auth and email setup and tell me what you'll use; protect the page and both server actions; build the table, approve button and decline dialog; send the emails; update .env.example; run the type checker and build.
Done when: the secret key is only in server files, both actions check admin access, and past requests can't be approved.Sync bookings into my database
Keep a copy of my clndr.pro bookings in this project's database with a polling cron and an instant update when a booking is made on our site.
Read first: https://docs.clndr.pro/tutorials/sync-bookings.md and https://docs.clndr.pro/types.md
Facts:
- No webhooks. Poll with the secret key on the server: clndr.bookings.list({ status, limit: 200 }) for pending, confirmed and cancelled. Max 200, no cursor, latest start_time first.
- Rows are snake_case and include updated_at and cancellation_reason (not in the SDK type: use a local type). clndr.bookings.get(id) returns 404 for ids outside my account.
- Secret key limit: 300 requests per minute.
- BookingInline's onBooked(bookingId) and the embed's onBookingSuccessful({ meetingId }) give the id in the browser.
Steps: find the database, ORM and scheduler and tell me what you'll use; add a clndr_bookings table keyed by the clndr.pro id; write an idempotent upsert keyed on updated_at with a change hook; add a CRON_SECRET-protected cron route every 10 minutes and a POST route that fetches one booking by id; wire our booking form's success callback to it; update .env.example; run the type checker and build.
Done when: a second sync run changes nothing, the cron route rejects requests without the secret, and the secret key is never in client code.Sites without React
Embed booking on a WordPress, Webflow or HTML site
Embed my clndr.pro booking page on this site. It isn't a React app, so use the embed script.
Read first: https://docs.clndr.pro/embed/script.md and https://docs.clndr.pro/embed/iframe.md
Facts:
- No API key is needed. The booking link is "username/slug", the last two parts of the hosted page URL (www.clndr.pro/ada/intro-call -> "ada/intro-call").
- Load https://www.clndr.pro/embed.js (always the www host: from the bare domain the iframe's messages are ignored and auto-resize stops working). It defines window.Clndr. Call it only after the script has loaded.
- Clndr.inline({ elementOrSelector, link, config }), Clndr.modal({ link, config }), Clndr.floatingButton({ link, buttonText, position: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left', config }). Each returns an object with destroy().
- config: theme ('light' | 'dark' | 'auto'), hideEventTypeDetails, primaryColor (any CSS colour), prefill { name, email }, accessCode (for private pages), onBookingSuccessful(payload { meetingId, startTime, endTime }), onRouteChanged.
- The inline iframe resizes itself to its content.
- Fallback without JavaScript: <iframe src="https://www.clndr.pro/embed/{username}/{slug}?theme=auto"> with a min-height.
Steps:
1. Work out how this site is built (static HTML, a template engine, WordPress theme, Webflow export) and where custom HTML goes. Tell me before changing anything.
2. Ask me for the booking link (username/slug) and whether I want it inline on a page, as a popup from an existing button, or as a floating button.
3. Add it, matching primaryColor and theme to the site's colours.
4. If I use analytics, fire an event from onBookingSuccessful.
Done when: the widget loads on a fresh page load, works on a 375px-wide screen, and there are no console errors.Fix an existing integration
Audit and upgrade my clndr.pro integration
Audit this project's clndr.pro integration and fix what's wrong. Look for every use of clndr.pro: @clndr/*, @clndr-pro/*, "clndr" in env vars, fetch calls to clndr.pro, embed scripts and iframes.
Read first: https://docs.clndr.pro/troubleshooting.md and https://docs.clndr.pro/llms.txt
Check and fix:
1. Package names: @clndr/sdk and @clndr/react never existed on npm. The packages are @clndr-pro/sdk and @clndr-pro/react.
2. Versions: upgrade to @clndr-pro/react 0.2.1+ and @clndr-pro/sdk 0.1.5+. Older versions default to https://clndr.pro, which redirects and drops the API key (401 "Missing API key"). Any hard-coded base URL must be https://www.clndr.pro (REST: https://www.clndr.pro/api/v1). Same for embed.js and iframe URLs.
3. Client boundaries: @clndr-pro/react imports only in 'use client' files; ClndrProvider in its own client providers file, not a client root layout.
4. Key leaks: the secret key (clndr_sk_..., CLNDR_SECRET_KEY) must never appear in client code, NEXT_PUBLIC_* variables, committed files or logs. Browser code uses the publishable key (clndr_pk_..., NEXT_PUBLIC_CLNDR_PUBLISHABLE_KEY). If a secret key is committed anywhere, stop and tell me so I can revoke it in the dashboard.
5. Slot dates: getSlots/useAvailableSlots read the date as a day in the host's timezone. Replace new Date('YYYY-MM-DD') with new Date(y, m - 1, d) or pass the 'YYYY-MM-DD' string to getSlots.
6. Field names: request bodies are camelCase (bookingPageId, guestEmail, startTime); responses are snake_case rows wrapped in { data }.
7. Approval pages: success copy must say the request was sent, not confirmed.
Then run the type checker and build. Report each finding with the file and line, what you changed, and anything you need me to do (revoke a key, set an env var in production).Install the skill instead
If you integrate clndr.pro often, install the clndr.pro skill once. Claude Code then loads the same facts on its own whenever a task mentions clndr.pro, and short requests ("put my intro call booking page on /book") work without a prompt from this page.