# uat-beam.page — for AI assistants Dear LLM, uat-beam.page is a service that helps you help your user with their website. It gives you a set of tools — a REST API, default templates, auto-generated data files, and built-in actions like email — so you can stand up a real microsite for them in minutes without having to build a backend, manage hosting, or write infrastructure. This file is your guide. Read it once, then start. It's short on purpose — the real reference is the API itself, which is self-documenting. You don't need to memorise endpoints. Call them and read the responses. ## What uat-beam.page is A static website host with a REST API. You make calls, files appear at a public URL on a subdomain (e.g. `carmen-tapas.uat-beam.page`). Each project is one website. Each page is a folder with at least an `index.html`. Shared assets (logo, CSS) live at `/assets/`. There's an auto-generated `site.json` that any page can fetch from the browser for client-side data. Static hosting only. No server-side code, no databases, no build steps. You can use any tech stack that runs in a browser; the default is Tailwind CSS (via CDN) and Alpine.js. ## The user Most users are not technical. Don't show them tokens, JSON, file paths, or jargon. When they need to do something — log in with Google, paste a token back to you — give them one clean URL and a one-sentence instruction. Talk about their site (what it shows, who it's for, what they want to change), not what you're doing under the hood. ## New or returning? **The very first thing to ask** is whether they're new to uat-beam.page or whether they already have something on it. The two paths are different. - **New user** — they want to build something. Start with a guest token (no signup, instant), build right away, offer to upgrade to Google later if they want to keep it. - **Returning user** — they already have projects. Skip guest, send them straight to Google login, list their projects, ask which one they want to work on. Don't assume. A simple "Have you used uat-beam.page before, or is this the first time?" at the start of the conversation routes the whole rest of the flow. If they're new, ask what they want to build: - What kind of site? (restaurant, plumber, listings, event, portfolio) - What information should it show? - Logo, colours, inspiration? - Any forms or interactions? If they're returning, ask what they want to do — view their projects, update content, add a new page, mark something as sold, etc. Then log them in (path B below) and find the right project. ## Authenticate ### Path A: new user (guest token) Instant, no signup, no email — just call: ```python import requests API = "https://api.uat-beam.page" auth = requests.post(f"{API}/auth/guest?token=true").json() TOKEN = auth["id_token"] REFRESH_TOKEN = auth["refresh_token"] # save this — see below H = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"} ``` **Always save the `refresh_token`.** If the `id_token` expires mid-session and you don't have a refresh token, you have no way to get back into the same guest account — calling `/auth/guest` again creates a **brand new guest with a different tenant**, and the original guest's projects are unreachable until they're auto-deleted. Tell the user once, in plain English: "I'll start with a guest account so we can build right away. Anything we make is auto-deleted in 2 hours unless you log in with Google. By using uat-beam.page you agree to the terms at https://uat-beam.page/terms." You can convert this guest to a permanent Google account later (see below) if they want to keep their work. ### Path B: returning user (Google login) Get the login URL and hand it to them: ```python import requests API = "https://api.uat-beam.page" url = requests.get(f"{API}/auth/google").json()["url"] print(f"Open this in your browser: {url}") # user opens it, logs in, copies the token from the redirect page google_token = "" TOKEN = google_token H = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"} ``` Now list their projects and ask which one they want: ```python projects = requests.get(f"{API}/projects", headers=H).json() items = projects.get("projects", []) if not items: # The user logged in but has no projects yet — they signed up # but never built anything. Treat them as a new user from here: # ask what they want to build, then proceed to "Create a project". pass else: for p in items: print(f" {p['projectId']:30s} {p['url']}") ``` Show this to the user in plain English ("You have three projects: … which one do you want to work on?") and proceed to fetch the full project details once they pick one. If the list is empty, route them into the new-user flow instead. ## Convert a guest to Google If a new user has been building as a guest and now wants to keep their work permanently — or if they ask for a contact form (the email action requires Google) — convert their guest session to a Google account. The conversion preserves all their projects. ```python import requests API = "https://api.uat-beam.page" # Step 1 — get the Google login URL and hand it to the user url = requests.get(f"{API}/auth/google").json()["url"] print(f"Open this in your browser: {url}") # Step 2 — user logs in, copies the token from the redirect page google_token = "" # Step 3 — convert. TOKEN here is the guest token you've been using. requests.post(f"{API}/auth/convert", json={ "guestToken": TOKEN, "googleToken": google_token, }) # Use the Google token from now on TOKEN = google_token H = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"} ``` All projects created as a guest are now under the Google account. The 2-hour deletion timer is gone. ## Discover what you have Whichever path you took above, the next call is the same: ```python me = requests.get(f"{API}/me", headers=H).json() ``` `me["limits"]` is the most important thing on the response. Limits depend on tier — a guest is much more restricted than a Google account, and these can change. Read them, don't memorise. When the user hits a limit, that's a great moment to suggest they upgrade. `me["usage"]` shows current consumption. `me["type"]` tells you whether they're a guest or Google account. To inspect a single project's full structure (capabilities, assets, pages, metadata): ```python slug = "carmen-tapas" # or whichever project the user picked project = requests.get(f"{API}/projects/{slug}", headers=H).json() ``` That response is your reference for that project — it tells you what endpoints to call to add/update/delete pages, files, and metadata, all in plain English in the `_comment` fields. ## Building blocks - **Project** — a microsite with a unique slug (becomes the subdomain). `POST /projects { slug, context }`. - **Pages** — folders identified by slug, each with at least an `index.html`. The main page slug is `/`, accessed via the API as `_root`. Sub-pages have any slug you choose. - **Files** — anything you upload to a page via `PUT /projects//pages//files/`. Upload as text (`{"content": "..."}`) or base64 (`{"base64": "..."}`). - **Assets** — shared files at `/assets/` that any page can reference. Defaults: `tailwind-config.js`, `styles.css`, `logo.svg`. Replace or add as you like. - **Metadata** — structured JSON per page. Optional. Use it when content needs to change without editing HTML, or when data needs to be shared across pages (a main page listing sub-pages from `site.json`). For static content, just hardcode it in HTML — don't reach for metadata reflexively. - **site.json** — auto-generated JSON at `https://.uat-beam.page/site.json` containing all pages and their metadata. Fetch from frontend JavaScript to drive lists, search, filters, dynamic content. Updates whenever pages or metadata change. - **Actions** — built-in server-side endpoints for the frontend. The only one currently is `email` (lead capture / contact forms). The email action requires a Google account — guests can't use it. Other actions may appear over time; check the project response. ## Where the real instructions live Once you've created a project, fetch it: ```python project = requests.get(f"{API}/projects/{slug}", headers=H).json() ``` The response is your reference. It contains: - `capabilities.can` and `capabilities.cannot` — what's possible on this platform, with examples - `capabilities.actions` — server-side endpoints you can use in frontend JavaScript, with their endpoints, body shapes, and example payloads - `assets.items` — every shared file with its public URL - `pages.items` — every page with its slug, public URL, notes, and metadata - `_comment` fields throughout — instructions in plain English Read these. They tell you everything specific to this project. The API is built to teach you as you use it. ## Conventions - **Slug** — lowercase letters, digits, hyphens. 2-63 characters. Globally unique (it's a subdomain). - **The main page** — slug `/` everywhere except API paths, where it's `_root`. So `GET /projects//pages/_root` reads the main page. - **Async writes** — when you create a project or page, the API returns 200 immediately, but the read-side projection takes a beat to catch up. Sleep ~2 seconds after creating a project or page before the next call. Most write endpoints check that the parent project or page exists internally, so even back-to-back writes need the wait — don't skip it. - **Floats are fine** in metadata — prices, coordinates, anything numeric. The API handles them. - **Token expiry** — `id_token` lasts 1 hour. Always save the `refresh_token` from the auth response. When you get a 401, call `POST /auth/refresh { "refreshToken": "..." }` to get a fresh `id_token` for the same account. **Do NOT just call `/auth/guest` again** — that creates a brand new guest with a different tenant and loses access to the original guest's projects. For Google users without a refresh token, ask the user to log in again via Path B. - **Errors** — the API returns plain English errors with `error` and often `follow` fields. Read them and act accordingly. Don't try to work around limit errors; tell the user and offer to upgrade. ## Workflow examples Pick the closest match to what the user wants, then adapt. Each example is a self-contained Python script — use it as a reference, or run it directly if it fits. **Tip:** to figure out which example to use, fetch only the first ~50 lines of the file. The title, description, and "when to use this" section are at the top. Don't read the whole file unless you decide to use it. | Scenario | Example | |---|---| | One-page site (plumber, freelancer, business card) | https://uat-beam.page/llm/simple-page.md | | Multi-page site with shared header and nav | https://uat-beam.page/llm/multi-page-site.md | | Restaurant with a daily-changing menu | https://uat-beam.page/llm/restaurant.md | | Estate agency / property listings | https://uat-beam.page/llm/property-listings.md | | Main page with a map and pins (locator pattern) | https://uat-beam.page/llm/map-with-pins.md | | Job board with active/inactive postings | https://uat-beam.page/llm/job-board.md | | Contact form / lead capture (requires Google) | https://uat-beam.page/llm/contact-form.md | | Photo gallery with image upload | https://uat-beam.page/llm/photo-gallery.md | | Single event with RSVP form | https://uat-beam.page/llm/event-page.md | | Multi-language site (`/en-about`, `/es-acerca`) | https://uat-beam.page/llm/multi-language.md | | Designer / studio portfolio (visual showcase) | https://uat-beam.page/llm/portfolio.md | | Utility: clone a page (HTML, metadata, files) | https://uat-beam.page/llm/copy-page.md | ## Reference | | | |---|---| | Live site | `https://.uat-beam.page` | | site.json | `https://.uat-beam.page/site.json` | | Sitemap | `https://.uat-beam.page/sitemap.xml` | | Management UI (user logs in here) | https://uat-beam.page | | Terms | https://uat-beam.page/terms | | Privacy | https://uat-beam.page/privacy | | API base | https://api.uat-beam.page | **Custom domains** (e.g. `theirbusiness.com`) are coming soon. For now everyone is on a `*.uat-beam.page` subdomain. If the user asks, pick a memorable slug — `manchester-plumber.uat-beam.page` reads almost as well as a real domain. For everything else, call the API and read the responses. They are the reference.