# Just a Good Guy: docs for AI agents The AI website build guide followed by the reference pages it relies on. Generated from the docs sources; the same pages are at https://justagoodguy.us/docs/. Index: https://justagoodguy.us/llms.txt --- # AI website build guide > The instruction book for AI coding agents that build a small-business website on Just a Good Guy, or connect an existing one. What to gather, what to paste, the quality bar, and how to ship and check it. Source: https://justagoodguy.us/docs/ai-build-guide > [!IMPORTANT] > **AI agents: read this whole page before you write any code.** Every attribute, method, event and endpoint below is checked against the source. Don't use names that aren't on this page or its linked references. > > - This page as plain Markdown: [/docs/ai-build-guide.md](https://justagoodguy.us/docs/ai-build-guide.md) > - This page plus every reference page in one file: [/llms-full.txt](https://justagoodguy.us/llms-full.txt) > - Starter site to copy: [/docs/starter-site.zip](https://justagoodguy.us/docs/starter-site.zip) ([browse the files](https://justagoodguy.us/docs/starter-site/README.md)) ## What Just a Good Guy is - An AI receptionist for small businesses. It answers the website chat, the phone and texts. - It books customers into real open times, and takes call-back requests, messages and quote requests for the owner. - A website connects with **one script tag**, the widget. It adds a chat and booking button, inline booking and other widgets, and lets any button open booking or chat. - A **public API** with a publishable `pk_` key gives a web page live services, prices and hours, and accepts call-back and message forms. A **REST API** with a secret `sk_` key, plus signed webhooks, is for servers. - It can **host the site** too: on a free address like `https://joes-plumbing.justagoodguy.us`, on the business's own domain, or on the business's own server. ## Rules you never break - **Never put a secret key (`sk_...`) in anything a browser loads.** No HTML, no JavaScript, no public repo. Web pages only ever use the publishable key (`pk_...`). - **Never invent facts.** No made-up prices, reviews, star ratings, awards, years in business, licences, staff, opening hours or service areas. Use the intake answers, the live API and what the operator tells you. If a fact is missing, leave it out or ask. - **Book only through Just a Good Guy.** Use the widget, its buttons or the public API. Never build a form that emails a "booking request" instead. - **Load the widget once per page**, with the business's own key. - **Inline SVG for icons.** Never emoji or Unicode symbols as icons. - **No native date, time or ` ``` - Fields are matched by type, name, label or placeholder: name (or first and last name), email, phone, subject and the message. Anything else (a date, a budget, a checkbox) is sent along as "Label: value". - After sending, the form is replaced by a thank-you line. Set your own with `data-gg-thanks`. - Problems ("Please write your message.") show above the form's button in plain words. - A hidden "honeypot" field that a bot filled in means nothing is sent. - The widget's `lead.created` event fires with `source: "site_form"`. ## Script options All of these are optional except `data-key`. Add them to the same ` ``` ## For developers ### How loading works `/w.js` is a tiny loader. Browsers may cache it for 5 minutes. It finds its own ` ``` - You can have as many inline widgets on a page as you like. - Widgets added to the page later are picked up automatically (the script watches the page). You can also render one from code with [`GoodGuy.mount`](https://justagoodguy.us/docs/javascript-api#methods). - If the page only uses inline widgets, add `data-launcher="false"` to the script tag to hide the floating button. - An element is only rendered once. To change its options, replace the element with a new one. | Type | What it shows | Options | |---|---|---| | [`chat`](#chat) | The AI chat, inline | `data-gg-height` | | [`booking`](#booking) | The step-by-step booking flow | `data-gg-service`, `data-gg-staff`, `data-gg-source` | | [`services`](#services) | Your services with prices and a Book button on each | none | | [`callback`](#callback) | A "Call now" button, or a call-back request form | none | | [`contact`](#contact) | A message or quote request form | `data-gg-service` | | [`hours`](#hours) | Your weekly hours with an Open now or Closed badge | none | | [`manage`](#manage) | One customer's booking: move or cancel | `data-gg-token` (required) | | [`offer`](#offer) | A waitlist offer the customer can claim | `data-gg-token` (required) | ## chat The same AI receptionist as the floating panel, shown inline. Good for a "Questions?" section or a contact page. | Option | Default | Notes | |---|---|---| | `data-gg-height` | `480` | Height in pixels. The smallest allowed is 320. | ```html
``` The conversation is shared with the floating panel on the same site, so a visitor can start in one and carry on in the other. ## booking A step-by-step flow: 1. pick a service 2. pick a person, if more than one person does that service and you let customers choose 3. pick a day and time (buttons, not a date picker) 4. enter a name and a mobile number or email, plus the address for [at-home visits](https://justagoodguy.us/docs/bookings#service-kinds) 5. confirm After booking it shows the confirmation and a link to change or cancel. | Option | What it does | |---|---| | `data-gg-service` | Preselect a service by id or by name, for example `data-gg-service="Haircut"`. | | `data-gg-staff` | Preselect a person by staff id. | | `data-gg-source="booking_page"` | Records the booking as coming from a booking page instead of the widget. Only `widget` (the default) and `booking_page` are accepted. | ```html
``` Service and staff ids come from [`GET /v1/services`](https://justagoodguy.us/docs/rest-api#list-services) and [`GET /v1/staff`](https://justagoodguy.us/docs/rest-api#list-team-members), or from [`GET /api/public/services`](https://justagoodguy.us/docs/public-api#services). ## services Your active services, with each one's price label (for example "$45", "From $80" or "Price varies") and a **Book** button. Tapping **Book** opens the booking flow with that service selected. ```html
``` There are no options. The list follows the order you set in the dashboard. ## callback When someone can take a call right now (you're inside your [call hours](https://justagoodguy.us/docs/phone#call-hours-vs-booking-hours), live calls are on and you have a phone number), it shows a **Call now** button that dials your number. Otherwise it shows a form to request a call-back, with the next open call-back windows as buttons. ```html
``` Call-back windows come from your call hours. A request lands in your inbox and triggers a "Call-back requested" alert. ## contact A form for a message or a quote request: name, phone or email, and what they need. It creates a lead in your inbox. | Option | What it does | |---|---| | `data-gg-service` | Ties the request to a service, by id. Useful for [quote-type services](https://justagoodguy.us/docs/bookings#service-kinds). | ```html
``` ## hours Your weekly booking hours, with an **Open now** or **Closed** badge. The weekly list shows your regular business hours. The badge also takes whole-business closures and holidays into account. ```html
``` ## manage One customer's booking, opened from the private link in their confirmation. It shows the details and lets them: - **Pick a new time** from open times in the next 14 days - **Cancel** | Option | What it does | |---|---| | `data-gg-token` | **Required.** The token from the customer's manage link, `https://justagoodguy.us/m/`. | ```html
``` You rarely need this yourself: every confirmation already links to a ready-made page at `/m/`. Use it if you want that page on your own site. Treat the token like a password: anyone with it can change the booking. ## offer A waitlist offer, opened from the link in the offer text or email. It shows the service and time with a **Claim this spot** button, or a "someone got it" message if it's gone. | Option | What it does | |---|---| | `data-gg-token` | **Required.** The token from the offer link, `https://justagoodguy.us/offer/`. | ```html
``` See [Waitlist](https://justagoodguy.us/docs/bookings#waitlist) for how offers are sent. ## Errors and loading While the widget loads its settings it shows a small loading state. If something is wrong, such as a revoked key or a site that isn't on your [allowed sites](https://justagoodguy.us/docs/add-widget#allowed-sites) list, it shows the server's message inside the widget and logs a warning that starts with `[GoodGuy]` to the browser console. --- # Buttons and triggers > Make any button or link on your site open chat, booking, a call-back form or a question. Source: https://justagoodguy.us/docs/triggers ## Three attributes Add one of these to any element. Clicking it opens the floating panel. | Attribute | What it does | |---|---| | `data-gg-open="chat"` | Opens the panel on a view: `chat`, `booking`, `callback` or `contact`. | | `data-gg-book="Haircut"` | Opens booking with that service selected. Use a service id or its name. Leave it empty (`data-gg-book=""`) to open booking at the first step. | | `data-gg-ask="Do you take walk-ins?"` | Opens chat and sends that question for the visitor, so the answer is waiting for them. | ```html Is there parking? ``` If an element has more than one, `data-gg-ask` wins, then `data-gg-book`, then `data-gg-open`. ## Good to know - **Elements added later work too.** Clicks are caught at the document level, so triggers inside menus, modals or content loaded after the page work without extra code. - **The click's default action is cancelled.** A link with a trigger won't navigate. To keep a fallback for people without JavaScript, point the link at your [booking page](https://justagoodguy.us/docs/booking-page): ```html Book online ``` - **Your own click handlers come first.** If another script cancels the click (`event.preventDefault()`), the trigger is skipped. - **Use real buttons or links.** A `