supportgeni.us · a Factory Zero venture
This repository is the marketing site for SupportGenius: one page, one
stylesheet and one script, served by Cloudflare Pages. There is no framework,
no bundler, no build step and no runtime dependency. It was designed in Claude
Design (SupportGenius.dc.html) and ported to static HTML by hand, the same
way as colonizer.dev and
findsyou.work.
Two things are being described, and the site is careful about which is which. The split is the same one the organisation profile makes:
| What it is | Status | |
|---|---|---|
| The site | This repository: supportgeni.us, one page on Cloudflare Pages, MIT. | Shipping |
| SupportGenius | The product: the agent, its surfaces and integrations, the escalation pipeline, the Rust core, and the waitlist. | Planned |
Support that answers. When it can't, it routes the issue to the right people, where they already work.
Nothing is built. There is no agent, no widget, no SDK, no phone line, no API, no MCP server and no integration. Every capability carries one of two labels, and the label sets the tense of the sentence around it.
- Shipping: built, deployed, usable now. Present tense is allowed only here. Today that is this page and its waitlist, and nothing else.
- Planned: named, unbuilt. Conditional tense, and a
plannedchip wherever it appears on the page.
A banner at the top of the page says so in the first sentence a visitor reads,
and llms.txt repeats it for machine readers, so an answer engine
cannot describe a planned feature as available.
The conversations, issue numbers, judge scores, SLA table and on-call phone view are illustrations with sample data, and each is labelled as such where it appears.
| Anchor | Section | Job |
|---|---|---|
/ |
Hero | The claim, the planned embed snippet, the planned surfaces |
#demo |
Illustration | One widget, three scenes on a 32 s loop: answered from docs, escalated to engineering, passed to sales |
#how |
How it would work | Three steps: sources, surface, destinations |
#features |
Features | Fourteen planned capabilities, each with a chip |
#pipeline |
Escalations | Drafting model, judge model, router, lifecycle; the judge's three outcomes; an example SLA policy |
#human |
Human in the loop | Six steps from customer to correction, beside the on-call phone view |
#integrations |
Integrations | Sixteen planned destinations and surfaces |
#pricing |
Pricing | The tiers being planned, without prices |
#waitlist |
Waitlist | Posts to the waitlist Worker at api.supportgeni.us with a Turnstile token; a mail address without JavaScript |
Plus 404.html, llms.txt, sitemap.xml, robots.txt, site.webmanifest
and .well-known/security.txt.
.
├── index.html the page
├── 404.html
├── privacy.html the waitlist privacy notice (draft, pending legal review)
├── assets/
│ ├── supportgenius.css the whole design system, tokens and @font-face at the top
│ ├── fonts/ Geist and Geist Mono, Latin woff2 subsets (variable, weights limited), OFL licence
│ ├── supportgenius.js demo stage scale, reduced motion for its SVG, the waitlist
│ ├── favicon.svg the mark, still
│ ├── og.png Open Graph card (1200×630)
│ ├── apple-touch-icon.png icon-512.png
│ ├── org-avatar.png GitHub organisation avatar, uploaded by hand; not deployed
│ └── readme-banner.png the banner above, also the org profile's; not deployed
├── llms.txt the structured summary for machine readers
├── robots.txt AI crawlers welcomed by name
├── _headers _redirects Cloudflare Pages
├── COPY.md every claim on the page, with its source
└── tools/
├── check.py structure + house-rule checks; deploy.sh runs it
├── render-og.sh renders every PNG above with headless Chrome, from *-render.html
├── build-dist.sh assembles dist/ from an allowlist, stamps cache hashes
└── deploy.sh deploys origin/main from a clean worktree
No build step, but the page uses root-relative paths, so serve it rather than
opening it as file://:
python3 -m http.server 8000 # then http://localhost:8000/
python3 tools/check.py # before every commit_headers (including the Content-Security-Policy) only applies on Cloudflare
Pages. A local server does not send it, so check a change that loads anything
new on a Pages preview too.
tools/render-og.sh renders og.png, readme-banner.png, org-avatar.png and
the two app icons from tools/og-render.html, tools/banner-render.html,
tools/avatar-render.html and assets/favicon.svg, with headless Chrome. The
same shape as colonizer.dev. The images carry the "in design" chip, and no
third-party logos, because an image travels without the page's trademark line.
readme-banner.png is also the banner of the organisation profile in
SupportGenius/.github: copy it there when it changes. GitHub has no API for
organisation avatars, so org-avatar.png is uploaded by hand at
github.com/organizations/SupportGenius/settings/profile.
The hero illustration is a fixed 1120×520 canvas, positioned in canvas pixels so
the SVG paths and the HTML cards line up, then scaled to the column width by
supportgenius.js (the --s custom property). Without JavaScript the CSS
breakpoints approximate the same scale.
Everything runs on one 32 s loop (--loop), and every keyframe percentage is
the design canvas's own. The destination cards light up one after another
through --d, a fraction of the loop.
Under prefers-reduced-motion the whole scene freezes on one readable frame
(42% of the loop: the iOS conversation, escalated, with the issue filed) rather
than collapsing to its invisible end state. CSS cannot reach SMIL, so the script
pauses the SVG packets on the same frame.
Under 640px the canvas is hidden and a stacked version shows instead
(.stage__phone, a sibling of the canvas inside the same aria-hidden stage).
It holds the same widget, channel chips, engine row and destination cards, and
reuses the canvas's keyframe classes, so it runs on the same 32 s timing. One
destination shows at a time: GitHub in scene B, Salesforce in scene C, none in
scene A. Every text node in it is 11px or larger. Edit the two copies together:
the widget markup appears once in the canvas and once in .stage__phone.
The form is open. It posts { email, product: "supportgenius", captchaToken }
to https://api.supportgeni.us/v1/waitlist, a Cloudflare Worker running the
Cratefield harness waitlist module with its own D1
database (SupportGenius/waitlist-backend). captchaToken is a Cloudflare
Turnstile token from the managed widget (sitekey 0x4AAAAAAFRBObOIEtlONvJt,
action: "waitlist"), rendered explicitly by assets/supportgenius.js. The
Worker binds the token to the apex hostname supportgeni.us, so www must
redirect to the apex (a Cloudflare Redirect Rule on the zone).
The Worker sends a double opt-in confirmation link through Owlpost, from
no-reply@send.supportgeni.us, so the form's success copy says to check the
inbox (data-double-opt-in="true"). Answers: 202 joined (also for an address
already on the list), 400 with problem type …/captcha-failed for the human
check, 400 for a bad address, 429 too many tries. With JavaScript off the
form stays hidden and the page offers hello@supportgeni.us instead.
The CSP in _headers allows https://api.supportgeni.us (connect-src) and
https://challenges.cloudflare.com (script-src, frame-src). Deploy the Worker
before the site, or joins fail until it answers.
Cloudflare Pages, project supportgenius, on the Factory0 account, which
also holds the supportgeni.us zone:
tools/deploy.sh --dry-run # what would ship
tools/deploy.sh # ship origin/maindeploy.sh never deploys the working copy. It checks origin/main out into a
temporary worktree, runs tools/check.py, builds dist/, and deploys that with
the commit hash recorded on the Pages deployment. Merge first, then deploy.
Use a login or API token for the Factory0 account. Another account's
wrangler login fails with Authentication error [code: 10000].
- Invent nothing. No metrics, customer logos, testimonials, uptime figures, response times, user counts or benchmarks. The design canvas said the core gives "sub-millisecond routing, low memory"; that is not on the page.
- Present tense is earned. Only what is deployed and usable is described as working. Today that is this page.
- No price for anything planned. The canvas had $49 and $249 tiers, an
annual discount and "99 voice minutes"; none of them are on the page.
tools/check.pyfails on anything that looks like a price. - Nothing says Available. The canvas marked integrations Available, Beta or Planned. All of them are planned, and the check fails on the other two.
- The demo says it is a demo. The stage carries an
illustrationchip and a caption. Keep both. - No dead controls. The canvas had a Copy button for a snippet that does not
work, a disabled "Live demo" button and footer links that went nowhere. The
snippet carries a
plannedchip instead, the bubble links to the waitlist, and the footer lists only links that resolve. - Logos only where the brand allows it. A planned integration is not a
true "integrates with". Salesforce, Slack and Apple get line icons until their
terms are met;
tools/check.pyholds the allowlist. SeeCOPY.md. - No dark patterns. No fake urgency, no pre-checked boxes, and nothing gated behind an email.
Claims are tracked in COPY.md.
The backlog is written for a Colonizer colony, or any
agent, to take one issue at a time. Start at the pinned tracking issue,
#13, which gives the order
and the rules. In short: touch only the files the issue lists, run
python3 tools/check.py before every commit, open a PR with Closes #N, and
never deploy. A person merges, then runs tools/deploy.sh. Labels:
colony-ready (take it), needs-decision (ask the one question it names),
human-step / human-only (needs account access), blocked.
Motion is decoration. The hero illustration is aria-hidden and described in
prose for screen readers. Under reduced motion every animation stops. Nothing is
hidden until JavaScript runs. The canvas's #6b7382 label colour failed WCAG AA
at the sizes it was used; it is #7b8394 here (5.1:1 on the page background).
Checks that are not in tools/check.py, because they need npm and a headless
browser (check.py stays dependency-free and offline):
-
axe-core. Serve the repository root (
python3 -m http.server 8000), then in a scratch folder outside the repo run:mkdir -p ~/sg-a11y && cd ~/sg-a11y && npm i playwright @axe-core/playwright && npx playwright install chromium
Save this as
axe.mjsin that folder, then runnode axe.mjs http://127.0.0.1:8000. It scansindex.htmland404.htmlat 1440px and 390px, with and without reduced motion, and exits non-zero on any serious or critical violation.import { chromium } from 'playwright'; import { AxeBuilder } from '@axe-core/playwright'; const base = process.argv[2] || 'http://127.0.0.1:8000'; const browser = await chromium.launch(); let failures = 0; for (const path of ['/', '/404.html']) for (const width of [1440, 390]) for (const reducedMotion of ['no-preference', 'reduce']) { const context = await browser.newContext({ viewport: { width, height: 900 }, reducedMotion }); const page = await context.newPage(); await page.goto(base + path, { waitUntil: 'load' }); await page.waitForTimeout(1000); // let the hero's entrance fade finish const { violations } = await new AxeBuilder({ page }) .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa']).analyze(); for (const v of violations.filter((x) => ['serious', 'critical'].includes(x.impact))) { failures += v.nodes.length; console.log(path, width, reducedMotion, v.impact, v.id, v.nodes.map((n) => n.target.join(' '))); } await context.close(); } await browser.close(); console.log(failures ? `${failures} serious or critical node(s)` : 'axe: 0 serious or critical'); process.exitCode = failures ? 1 : 0;
-
Keyboard. Tab from the top reaches "Skip to content" first; Enter moves to
#main. Every link and button shows a 2px focus ring. Nothing in thearia-hiddendemo stage can take focus. The page has no menu, popover or modal, so there is nothing for Escape to close. Below 880px the section links are hidden from the nav, and the footer's "On this page" list covers them. -
Overflow. No horizontal page scroll at 320, 360 or 390px. The SLA table scrolls inside its own focusable region.
-
Touch. On phones and touch screens (
pointer: coarse, or under 640px), buttons, nav and footer links, and the built-with pills are at least 44px tall.
The code in this repository is MIT. The SupportGenius name and mark are not.
No cookies · no analytics · Built by Factory Zero
