@rubytech/create-maxy-code 0.1.341 → 0.1.342

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy-code",
3
- "version": "0.1.341",
3
+ "version": "0.1.342",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy-code": "./dist/index.js"
@@ -32,6 +32,7 @@ The plugin registers no agent-facing MCP tools. Every Cloudflare operation is th
32
32
  | Skill | Purpose |
33
33
  |---|---|
34
34
  | [cloudflare/SKILL.md](skills/cloudflare/SKILL.md) | The entry point for every Cloudflare operation. Routes each operation class to its reference, names the outcome contracts (tunnel external HTTP 200; hosting deployed URL; D1 round-trip), and states the tool-discipline + secret-redaction rules that bind the agent. |
35
+ | [site-deploy/SKILL.md](skills/site-deploy/SKILL.md) | Assemble one canonical content tree into a live Pages deployment on its custom domain that survives the install device being offline. Names the single-source-tree convention, the reused per-scope token, the form-to-D1 trigger, Open Graph correctness, and the cache-busted live-`200` done-gate; defers the command blocks to `hosting-sites.md` and `d1-data-capture.md`. Admin-run; a content specialist hands the deploy off to it. |
35
36
 
36
37
  ### References
37
38
 
@@ -16,6 +16,7 @@ This is the entry point for every Cloudflare task on the install. Pick the opera
16
16
  | Tear down corrupt tunnel state and start clean | `references/reset-guide.md` | a fresh `manual-setup.md` run reaches `200` |
17
17
  | Call the Cloudflare API (DNS, zones, tunnels, Access, token list/reuse/revoke) | `references/api.md` | the API call returns success and the change is observable |
18
18
  | Deploy a static / Next.js site to Cloudflare Pages | `references/hosting-sites.md` | the deployed URL serves the new build |
19
+ | Take an approved content tree to a live site on its custom domain (canonical source, OG, optional D1 form, live verify) | `Skill site-deploy` | cache-busted `200` on the custom domain with correct content + `og:*`; a form site records a test POST to D1 |
19
20
  | Capture form/waitlist submissions into a database | `references/d1-data-capture.md` | a test POST appears in `SELECT … WHERE swept = 0` |
20
21
  | Diagnose / enable Web Analytics on a site (0 visitors, no data) | `references/web-analytics.md` | beacon present in live HTML (`curl -s https://<host>/ \| grep cloudflareinsights`) |
21
22
 
@@ -0,0 +1,84 @@
1
+ ---
2
+ name: site-deploy
3
+ description: Assemble an approved content tree into a live Cloudflare Pages deployment on its custom domain that survives the install device being offline. This is the skill behind "deploy this site", "put this landing page / investor site / microsite live on its own domain", "publish the waitlist site", and "the live site is stale / shows the wrong brand". It takes one canonical source tree, reuses the per-scope Pages-and-D1 token from the account secrets file, runs `wrangler pages deploy` to the production alias, attaches the custom domain, wires a contact or waitlist form to D1 when the tree carries one, and gates "done" on a cache-busted live `200` with correct content and Open Graph metadata on the production domain. Admin-run; it holds Bash and the account secrets surface. Distinct from `admin:publish-site` (device-tunnel hosting that dies when the device goes offline) and from `sitedesk:microsite` (single-page builder that stops before deploy).
4
+ ---
5
+
6
+ # Deploy a site to Cloudflare Pages
7
+
8
+ Run by the admin/main session, the operator-infra surface that holds the `Bash` tool and reads the account secrets file. A content specialist authors and approves the site tree; the deploy itself is admin work because it touches the Cloudflare account credentials. When a `content-producer` finishes a site, it hands the deploy off to admin, which loads this skill.
9
+
10
+ This skill is an outcome contract, not a second copy of the Pages mechanics. The mechanics live in the cloudflare references; this skill names the canonical source convention, the auth discipline, the form-to-D1 wiring trigger, the Open Graph correctness check, and the live done-gate, then defers each command block to the matching reference. Read `references/hosting-sites.md` (build, `wrangler pages deploy`, custom domain) and `references/d1-data-capture.md` (form to Pages Function to D1) via `plugin-read` before issuing those commands; read `references/api.md` for the token discipline.
11
+
12
+ ## When this skill, not another
13
+
14
+ | Situation | Skill |
15
+ |---|---|
16
+ | A standalone site (landing, investor, waitlist, microsite output) goes live on its own custom domain, hosted on Cloudflare's edge, surviving the install device being offline | **this skill** |
17
+ | Serve content that the install device itself renders, at a custom domain over the brand tunnel | `admin:publish-site` (device-tunnel `/sites/` path) |
18
+ | Build a single-page site from a brief | `sitedesk:microsite` (it stops before deploy; its output tree is then deployed by this skill) |
19
+
20
+ `admin:publish-site` serves from the install device through the brand tunnel: when the device is offline the site is unreachable. This skill puts the site on Cloudflare Pages, so it stays up independent of the device. Name the distinction when the operator's intent is ambiguous, and pick by whether the site must survive the device going offline.
21
+
22
+ ## One canonical source tree
23
+
24
+ Each site is driven by exactly one source tree at:
25
+
26
+ ```
27
+ <accountDir>/pages/<project>/
28
+ ```
29
+
30
+ `<project>` is the slug of the site's graph node (the `:Organization` or site entity the site represents), so there is one deterministic path per site and no second copy to reconcile. The tree holds the framework source, `wrangler.toml`, the built output directory, and `functions/api/contact.ts` when the site captures form data.
31
+
32
+ There is never a `sites/<brand>/` versus `output/<brand>-site/` pair, a `.bak` clone, or a stale sibling. If more than one candidate tree exists when you start, reconcile to the single canonical path first: confirm which tree is current, move it to `<accountDir>/pages/<project>/`, and remove the others before deploying. Deploying from an unreconciled tree is the root cause of the dev/live drift this skill exists to prevent. `<accountDir>/pages/` is distinct from `<accountDir>/sites/`, which belongs to the device-tunnel `admin:publish-site` path; the two never share a directory.
33
+
34
+ ## Auth: reuse the per-scope token, never mint ad hoc
35
+
36
+ A Pages deploy needs **Account · Cloudflare Pages · Edit**. A site with a D1-backed form also needs **Account · D1 · Edit** on the same token. Load the stable `<brand>-pages-d1` token from the account secrets file, minting it once only if absent and persisting it, exactly as `references/api.md` § Provisioning and reusing a stable per-scope token and `references/d1-data-capture.md` § 0 prescribe. The token is never written into the project tree, never committed, never echoed into chat. The master token stays in the secrets file. Surface every command as verb plus target ("deploying Pages project `<project>`"); `wrangler` prints the deployment URL, which is what gets relayed.
37
+
38
+ ## Deploy and attach the custom domain
39
+
40
+ Follow `references/hosting-sites.md`: build the framework output, write `wrangler.toml` (the project name is `<project>`, the output dir is the framework default), and `wrangler pages deploy <output-dir> --project-name <project> --branch=main` to the production alias. Attach the custom domain to the Pages project via the Cloudflare API with the reused `<brand>-pages-d1` token (the operator clicks **Workers & Pages → project → Custom domains** in the dashboard only when they prefer to do it by hand), so the site answers on the operator's domain, not only on `<project>.pages.dev`.
41
+
42
+ Attaching the custom domain to the project is not the same as the domain resolving. The attach leaves validation **pending** until a DNS record in the zone points the hostname at the Pages site; until that record exists the domain returns `NXDOMAIN` and the page is unreachable. Confirm the record exists and create it when it does not:
43
+
44
+ - A **subdomain** custom domain (`investors.example.com`) needs a `CNAME` to `<project>.pages.dev`.
45
+ - An **apex** custom domain (`example.com`) cannot hold a literal CNAME, so it needs a **proxied (flattened) CNAME** at the apex to `<project>.pages.dev`, plus a `www` CNAME if `www` is also served. This is the case the attach most often leaves pending.
46
+
47
+ Creating that DNS record is a **DNS-scope** operation, not a Pages-scope one: the `<brand>-pages-d1` token returns a `10000 Authentication error` on the DNS endpoint. Use the DNS-scoped `<brand>-dns` token, exactly as `cloudflare/SKILL.md` § Apex hostnames and `references/api.md` § DNS records prescribe, minting it once if absent. The hostname's zone must be on the same Cloudflare account; a hostname whose zone lives in a different account is reached with that account's own `<brand>-dns` token, never by probing a drawer of ad-hoc `CF_DNS_TOKEN_*` strays (that token sprawl is what the `references/api.md` reconcile pass exists to clear). The custom domain is the surface the done-gate checks, so a missing record fails the gate rather than passing silently.
48
+
49
+ ## Wire the form to D1 when one exists
50
+
51
+ When the canonical tree carries a contact or waitlist form, the deploy is not complete until that form records to D1. Follow `references/d1-data-capture.md`: create the database, add the `[[d1_databases]]` binding to `wrangler.toml`, create the table, and ship `functions/api/contact.ts`. The token from the auth step already carries D1 Edit, so the form does not silently 500 at the insert. A site with no form skips this section.
52
+
53
+ ## Open Graph correctness
54
+
55
+ The live page must carry brand-correct Open Graph metadata: `<meta property="og:title">`, `og:description`, `og:image`, and `og:url` reflecting this site and this brand, not a leftover from whatever the tree was cloned from. Stale OG (a live card still naming a previous brand) is a recorded failure mode of hand deployment. Confirm the `og:*` tags in the deployed HTML are correct before claiming done; if they are stale, fix them in the source tree, redeploy, and re-check.
56
+
57
+ ## Done-gate: a live cache-busted 200 on the custom domain
58
+
59
+ "Done" is never "I ran deploy". It is a live behavioural signal on the **production custom domain**, surfaced verbatim in chat:
60
+
61
+ ```bash
62
+ curl -s "https://<custom-domain>/?cb=$(date +%s)" -D - -o /tmp/site.html | head -1
63
+ grep -o '<meta property="og:[^>]*>' /tmp/site.html
64
+ ```
65
+
66
+ The done-gate passes only when all hold:
67
+
68
+ - the domain resolves at all: a `NXDOMAIN` or "could not resolve host" means the custom-domain DNS record was never created, so go back to the custom-domain step and create the CNAME with the `<brand>-dns` token; a `522` is the certificate-provisioning window, so wait and re-curl rather than treating it as done,
69
+ - the status line is `HTTP/2 200` (or `HTTP/1.1 200 OK`),
70
+ - the body carries an expected content marker for this site (a brand string or headline you can name in advance), not a stale marker from a previous brand,
71
+ - the `og:*` tags are present and brand-correct,
72
+ - for a form-bearing site, a test POST appears in D1 unswept, per `references/d1-data-capture.md` § Outcome contract. This sub-check reuses the same `${PAGES_D1}` token and `<db-name>` already loaded when the form was wired, not a fresh token:
73
+
74
+ ```bash
75
+ curl -sS -X POST -d "email=test@example.com&name=verify" "https://<custom-domain>/api/contact" -i | head -1
76
+ CLOUDFLARE_API_TOKEN="${PAGES_D1}" wrangler d1 execute <db-name> --remote --command \
77
+ "SELECT email FROM leads WHERE swept = 0;"
78
+ ```
79
+
80
+ Any other status, a missing or stale content marker, an OG mismatch, or a form POST that does not land in D1 blocks "done" and is reported with the exact failing URL. Record the deployment alias and the cache-busted verification command in the result so a later operator re-runs the same check against the custom domain to confirm live state without reading source.
81
+
82
+ ## Tool discipline
83
+
84
+ The permitted surface is `wrangler`, `curl`, and the Cloudflare API via Bash following the cloudflare references, using the reused per-scope token. The agent does not mint a fresh token per deploy, does not drive the dashboard with Playwright or Chrome DevTools, does not synthesise `wrangler` flags from web search, and never writes or echoes a token. When a step fails, report the exact output with secrets redacted, name the failing URL or command, and stop.
@@ -44,6 +44,8 @@ When a brief carries a "host this website" / "publish this site" / "put this onl
44
44
 
45
45
  Confirm the slug with the operator before publishing. The slug is one or more `/`-separated segments under `<accountDir>/sites/`. Refusals are loud-fail; relay the tool's `Operator action:` line verbatim and stop. On success, take the `pathSlug` from the tool response, call `mcp__plugin_admin_admin__public-hostname`, and surface `https://<hostname><pathSlug>` to the operator as one line.
46
46
 
47
+ `publish-site` serves from the install device through the brand tunnel: when the device is offline the site is unreachable. When the brief instead wants a site live on its **own custom domain that survives the device being offline** (a Cloudflare Pages deployment), that is a different hosting model and a different seat. You do not hold Cloudflare account authority, so you do not deploy it yourself. Assemble and approve the one canonical source tree at `<accountDir>/pages/<project>/` (`<project>` = the slug of the site's graph node; no `sites/`-vs-`output/` duplicate), then hand the deploy back to the admin session to run `Skill site-deploy`, which owns the Cloudflare credentials, the form-to-D1 wiring, the Open Graph check, and the live cache-busted done-gate on the custom domain. Return to admin naming the canonical tree path and the expected custom domain.
48
+
47
49
  ## File delivery
48
50
 
49
51
  To deliver a generated file, write it under `accounts/<accountId>/output/` (any depth) and report its full `output/` path in your result. As a subagent you do not send the file yourself; the main session delivers it, and the path you report is what it delivers. On a turn that arrived over a message channel (web chat, WhatsApp, Telegram) the main session calls `SendUserFile` with the path and the platform forwards the file to that conversation as an attachment. On the admin dashboard the same `output/` file appears in the Artefacts panel and is reachable on the file share. See the `file-presentation` skill for the wording.