Add live HTTPS door cards and screenshots to the catalog.
Some checks are pending
offline / test (push) Waiting to run

Homepage bottom of zapier.georgelambert.org lists each public
service with a description, screenshot, and link. UI-REVIEW.pdf
and the walkthrough document those doors.
This commit is contained in:
George Lambert 2026-09-11 20:15:53 -04:00
parent acf902e361
commit d31c4317af
21 changed files with 696 additions and 108 deletions

File diff suppressed because one or more lines are too long

View file

@ -125,3 +125,39 @@ Dashboard: API key is **masked**. **Reveal**, **Copy** (full key to clipboard),
**https://zapier.georgelambert.org/** — system-ui on the indigo header (not Georgia).
![Catalog](screenshots/22-catalog.png)
## 13. Live HTTPS doors (NS1)
Public names on **NS1.GEORGELAMBERT.ORG** with Let's Encrypt. Caddy file: `packages/verae-ops/caddy/zapier-services.georgelambert.org.caddy`. NATS, keep, and archive workers stay on loopback.
| Door | URL |
|------|-----|
| Customer portal | https://portal.zapier.georgelambert.org/portal/ |
| Customer API | https://api.zapier.georgelambert.org/ |
| S2S leaf | https://leaf.zapier.georgelambert.org/ |
| Zapier plane | https://zap.zapier.georgelambert.org/ |
| Staff plane | https://staff.zapier.georgelambert.org/ |
| Staff IAM | https://iam.zapier.georgelambert.org/ |
| Staff session | https://login.zapier.georgelambert.org/ |
| Customer service | https://cs.zapier.georgelambert.org/ |
| Sales | https://sales.zapier.georgelambert.org/ |
| Accounting | https://acct.zapier.georgelambert.org/ |
| Middleware | https://mw.zapier.georgelambert.org/ |
| Operator console | https://fleet.zapier.georgelambert.org/ |
| This catalog | https://zapier.georgelambert.org/ |
| Forgejo | https://git.georgelambert.org/ |
Staff HTML redirects to IAM login (`https://iam.zapier.georgelambert.org/login?next=…`).
![Portal live](screenshots/live/portal.png)
![IAM live](screenshots/live/iam.png)
![Fleet live](screenshots/live/fleet.png)
![Zapier plane live](screenshots/live/zap.png)
![CS live](screenshots/live/cs.png)
![Catalog live](screenshots/live/docs.png)

View file

@ -6,6 +6,7 @@
"description": "UI walkthrough, screenshots, and review PDF for Verae Time × Zapier",
"scripts": {
"walk": "node scripts/walkthrough.mjs",
"live": "node scripts/capture-live.mjs",
"pdf": "python3 scripts/build-review-pdf.py"
},
"dependencies": {

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -76,6 +76,34 @@ PAGES = [
"Left as vendor Swagger. Do not treat it as the customer portal."),
("22-catalog.png", "PDF catalog",
"https://zapier.georgelambert.org/ uses system-ui on the indigo header, not Georgia."),
("live/portal.png", "Live — customer portal",
"https://portal.zapier.georgelambert.org/portal/ — public signup and sign-in. Let's Encrypt. Access-web on NS1."),
("live/api.png", "Live — customer API",
"https://api.zapier.georgelambert.org/health — direct customer API plane (x-api-key)."),
("live/leaf.png", "Live — S2S leaf",
"https://leaf.zapier.georgelambert.org/health — server-to-server leaf. No billing subjects."),
("live/zap.png", "Live — Zapier plane",
"https://zap.zapier.georgelambert.org/health — Zapier Platform HTTPS only. Cloud never talks to NATS."),
("live/staff.png", "Live — staff plane",
"https://staff.zapier.georgelambert.org/ — IAM login, then CS/sales/accounting door."),
("live/iam.png", "Live — staff IAM",
"https://iam.zapier.georgelambert.org/ — named users, roles, sessions. Seed admin / admin-dev-key."),
("live/login.png", "Live — staff session",
"https://login.zapier.georgelambert.org/ — shared staff cookie; proxies IAM."),
("live/cs.png", "Live — customer service",
"https://cs.zapier.georgelambert.org/ — review prepaid and credit in USD after IAM."),
("live/sales.png", "Live — sales",
"https://sales.zapier.georgelambert.org/ — per-customer quote after IAM."),
("live/acct.png", "Live — accounting",
"https://acct.zapier.georgelambert.org/ — QuickBooks IIF / CSV after IAM."),
("live/mw.png", "Live — middleware",
"https://mw.zapier.georgelambert.org/health — /zapier/v1, jobs, archive, MOCK_VERAE in lab."),
("live/fleet.png", "Live — operator console",
"https://fleet.zapier.georgelambert.org/ — Fleet / Trace / Docs. Pause/stop honored by keep."),
("live/docs.png", "Live — documentation catalog",
"https://zapier.georgelambert.org/ — colored PDF catalog. Live service cards at the bottom."),
("live/git.png", "Live — Forgejo",
"https://git.georgelambert.org/ — independent module repos, SSH port 2223."),
]
@ -126,12 +154,13 @@ def main():
"Catalog body font is system-ui. Swagger /docs stays stock with an integrator banner only.",
"CS and access-staff share verae-staff-ui review.html.",
"Staff cookies accept STAFF_COOKIE_DOMAIN for a reverse-proxy host.",
"Public HTTPS doors on *.zapier.georgelambert.org (Caddy + Let's Encrypt). Catalog homepage lists each with a screenshot.",
]
for it in items:
story.append(p("" + it, s["body"]))
story.append(p("How to use each surface", s["h1"]))
story.append(p("Operator: open :3850, Fleet for replicas, Trace to inject a Zap step, Docs for PDFs. Staff: CS :3011 credit in USD; Sales :3012 quote; Accounting :3013 export; Staff plane :3025 after authz. Customers: /portal. Ops: /admin. Lab: simulator :3847.", s["body"]))
story.append(p("Public HTTPS on NS1 (Let's Encrypt): portal.zapier.georgelambert.org/portal/ for customers; zap.zapier.georgelambert.org for Zapier; api.zapier.georgelambert.org for API keys; fleet / cs / sales / acct / staff / iam for operators after IAM login. Loopback still used for NATS, keep, archive workers, and zappier-edge :13000.", s["body"]))
story.append(p("Issues still to consider", s["h1"]))
story.append(p("None. The designer-review backlog is empty.", s["body"]))

View file

@ -0,0 +1,56 @@
#!/usr/bin/env node
/** Screenshot every public HTTPS door on zapier.georgelambert.org. */
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import puppeteer from 'puppeteer-core';
const ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
const SHOTS = path.join(ROOT, 'screenshots', 'live');
const CHROME =
process.env.CHROME_PATH ||
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
fs.mkdirSync(SHOTS, { recursive: true });
const DOORS = [
{ file: 'portal.png', url: 'https://portal.zapier.georgelambert.org/portal/' },
{ file: 'api.png', url: 'https://api.zapier.georgelambert.org/health' },
{ file: 'leaf.png', url: 'https://leaf.zapier.georgelambert.org/health' },
{ file: 'zap.png', url: 'https://zap.zapier.georgelambert.org/health' },
{ file: 'staff.png', url: 'https://staff.zapier.georgelambert.org/' },
{ file: 'iam.png', url: 'https://iam.zapier.georgelambert.org/' },
{ file: 'login.png', url: 'https://login.zapier.georgelambert.org/' },
{ file: 'cs.png', url: 'https://cs.zapier.georgelambert.org/' },
{ file: 'sales.png', url: 'https://sales.zapier.georgelambert.org/' },
{ file: 'acct.png', url: 'https://acct.zapier.georgelambert.org/' },
{ file: 'mw.png', url: 'https://mw.zapier.georgelambert.org/health' },
{ file: 'fleet.png', url: 'https://fleet.zapier.georgelambert.org/' },
{ file: 'docs.png', url: 'https://zapier.georgelambert.org/' },
{ file: 'git.png', url: 'https://git.georgelambert.org/' },
];
const browser = await puppeteer.launch({
executablePath: CHROME,
headless: 'new',
args: ['--no-sandbox', '--window-size=1280,800', '--disable-dev-shm-usage'],
defaultViewport: { width: 1280, height: 800 },
});
try {
for (const d of DOORS) {
const page = await browser.newPage();
try {
await page.goto(d.url, { waitUntil: 'networkidle2', timeout: 25000 });
} catch {
await page.goto(d.url, { waitUntil: 'domcontentloaded', timeout: 15000 }).catch(() => {});
}
await new Promise((r) => setTimeout(r, 600));
const dest = path.join(SHOTS, d.file);
await page.screenshot({ path: dest, fullPage: false });
process.stdout.write(`wrote ${dest}\n`);
await page.close();
}
} finally {
await browser.close();
}