@topy-ai/maggie 0.1.0

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.
Files changed (36) hide show
  1. package/bin/maggie.js +152 -0
  2. package/bundled-references/ai-native-blog-contract.md +310 -0
  3. package/bundled-references/blog-data-contract.md +146 -0
  4. package/bundled-references/blog-implementation.md +46 -0
  5. package/bundled-references/blog-operations-contract.md +68 -0
  6. package/bundled-references/browser-inspection.md +39 -0
  7. package/bundled-references/provider-adapter-contract.md +68 -0
  8. package/bundled-references/seo-technical-contract.md +75 -0
  9. package/bundled-skills/README.md +16 -0
  10. package/bundled-skills/maggie-blog-bootstrap/SKILL.md +243 -0
  11. package/bundled-skills/maggie-clone/SKILL.md +213 -0
  12. package/bundled-skills/maggie-deployment/SKILL.md +61 -0
  13. package/bundled-skills/maggie-deployment/agents/openai.yaml +4 -0
  14. package/bundled-skills/maggie-deployment/references/cloudflare.md +76 -0
  15. package/bundled-skills/maggie-deployment/references/provider-contract.md +32 -0
  16. package/bundled-skills/maggie-project-context/SKILL.md +38 -0
  17. package/bundled-skills/maggie-seo-geo/SKILL.md +53 -0
  18. package/bundled-skills/maggie-social-share/SKILL.md +48 -0
  19. package/bundled-tools/clis/maggie.py +748 -0
  20. package/bundled-tools/clis/maggie_clone.py +82 -0
  21. package/bundled-tools/clis/site_audit.py +99 -0
  22. package/bundled-tools/integrations/analytics.md +34 -0
  23. package/bundled-tools/integrations/maggie-api-pull.md +72 -0
  24. package/bundled-tools/integrations/maggie-project-context.md +62 -0
  25. package/bundled-tools/integrations/maggie-seo-audit.md +16 -0
  26. package/bundled-tools/integrations/maggie-skills-api.md +76 -0
  27. package/bundled-tools/integrations/maggie-social-share.md +23 -0
  28. package/bundled-tools/integrations/maggie-visibility.md +22 -0
  29. package/package.json +29 -0
  30. package/references/ai-native-blog-contract.md +310 -0
  31. package/references/blog-data-contract.md +146 -0
  32. package/references/blog-implementation.md +46 -0
  33. package/references/blog-operations-contract.md +68 -0
  34. package/references/browser-inspection.md +39 -0
  35. package/references/provider-adapter-contract.md +68 -0
  36. package/references/seo-technical-contract.md +75 -0
@@ -0,0 +1,68 @@
1
+ # Maggie Blog Operations Contract
2
+
3
+ The starter keeps blog reading, content operations, migration, and agency
4
+ administration on explicit server-side contracts. Agents may customize UI/UX,
5
+ but must preserve these invariants:
6
+
7
+ ## Content operations
8
+
9
+ - Every scheduled publication is stored in `content_calendar` and is promoted
10
+ only from an approved/review state by `POST /api/ops/calendar/publish-due`.
11
+ - Every revision is a complete immutable post snapshot in `post_revisions`.
12
+ - Every bulk mutation starts as `bulk-preview`; apply operations are limited to
13
+ an allowlist of fields and produce an `audit_events` record.
14
+ - Redirects are unique by source path and accept only 301/308.
15
+ - Media is a first-class `media_assets` record with usage counts, metadata and
16
+ optional folders; remote media is never silently assumed to be local.
17
+
18
+ ## Migration
19
+
20
+ `POST /api/ops/migrations/import` accepts JSON, CSV, WXR, sitemap, or
21
+ `media-archive` input in preview/apply mode. Imported content uses
22
+ `source + source_id` as its identity and a SHA-256 checksum for incremental
23
+ reruns. `syncMode` supports `all`, `new`, and `modified`; `detectDeleted` archives
24
+ source records absent from a full snapshot, and `conflict` supports
25
+ `source-wins`, `target-wins`, or `manual`. Redirect mappings support both JSON
26
+ and CSV import/export. Persisted migrations can resume with
27
+ `POST /api/ops/migrations/:id/resume`; source identity and checksums keep the
28
+ resumed import idempotent. WordPress REST remains the richer adapter for terms,
29
+ authors, featured media and old-path redirects.
30
+
31
+ ## Agency
32
+
33
+ `workspaces`, `clients`, `sites`, and `workspace_members` isolate client data
34
+ and credentials. Workspace-scoped reads and writes use `/api/ops/agency` and
35
+ reject cross-workspace client/site/project relations. Roles are fixed to the
36
+ eight supported agency roles; secrets remain in server
37
+ environment/configuration and are never returned by browser APIs.
38
+ `approval_links` provides expiring, branded-review-compatible handoff tokens
39
+ without storing raw tokens.
40
+
41
+ Entity profiles and `entity_relations` form a small explicit entity graph;
42
+ insights also return refresh recommendations derived from persisted content
43
+ quality signals rather than silently mutating published content.
44
+
45
+ ## Vibe-coding safety
46
+
47
+ Bootstrap confirmation writes the project, decisions, schema, routes,
48
+ integrations, and migration manifests under `.maggie/`. `maggie doctor` and
49
+ `npm run schema:check` are required gates before generated code is considered
50
+ ready. Fixtures are deterministic and must be used for local provider tests.
51
+
52
+ ## API Pull lifecycle
53
+
54
+ The adapter exposes project context, post/update pulls, sitemap matching
55
+ history, rewrite queue/history, and publication-state reporting as separate
56
+ server-only operations. A local write and approval decision must complete
57
+ before `report-state` is called. Batch reporting is bounded to 500 records per
58
+ request, and API credentials are read from server configuration only.
59
+
60
+ ## External providers
61
+
62
+ Email and media are provider-neutral contracts. Resend is the default email
63
+ adapter and Cloudinary is the default media storage/delivery adapter; local or
64
+ webhook adapters can be selected without changing post, report, or media
65
+ records. Provider adapters must expose configuration health, normalize errors,
66
+ and never return credentials through Ops APIs. A new provider should implement
67
+ the relevant interface and register its ID rather than adding provider fields
68
+ to content templates.
@@ -0,0 +1,39 @@
1
+ # Maggie Clone Browser Inspection Contract
2
+
3
+ `maggie-clone` requires an available browser automation capability. The skill
4
+ is intentionally provider-neutral: use the configured Chrome, browser,
5
+ Playwright, Puppeteer, or equivalent MCP tools rather than adding a fake local
6
+ MCP server to the host project.
7
+
8
+ The browser capability must support:
9
+
10
+ - navigation to a target URL and reading the final URL after redirects;
11
+ - desktop, tablet, and mobile viewport sizes;
12
+ - full-page and viewport screenshots saved to the planned artifact directory;
13
+ - DOM/text/attribute queries and JavaScript evaluation;
14
+ - slow scrolling, click, hover, keyboard focus, and back/forward navigation;
15
+ - reading computed CSS, media sources, links, and visible accessibility labels.
16
+
17
+ The minimum extraction result for a target is:
18
+
19
+ ```text
20
+ final URL and redirect chain
21
+ viewport screenshots: 1440, 768, 390
22
+ page sections and destination route
23
+ visible copy and links
24
+ computed design tokens
25
+ asset URLs and media metadata
26
+ interaction states and triggers
27
+ responsive differences
28
+ ```
29
+
30
+ If a target requires login, a bot challenge, a consent interaction, or a
31
+ private browser profile, stop at that boundary and ask the user to provide
32
+ authorized access. Do not bypass access controls or record cookies in project
33
+ artifacts.
34
+
35
+ Use browser evaluation to measure values; do not infer a Tailwind class from
36
+ appearance. For every stateful component capture state A and state B and
37
+ record the trigger and transition. Keep screenshots and extracted data under
38
+ the target's namespaced research root so multiple URLs cannot overwrite one
39
+ another.
@@ -0,0 +1,68 @@
1
+ # Maggie Provider Adapter Contract
2
+
3
+ Third-party services are implementation details behind stable interfaces. Blog
4
+ routes, content records, reports, and Ops screens must depend on capabilities,
5
+ not on a vendor SDK or vendor-specific fields.
6
+
7
+ ## Defaults
8
+
9
+ | Capability | Default | Local/development alternative |
10
+ |---|---|---|
11
+ | Email delivery | `resend` | `webhook` or `disabled` |
12
+ | Media storage and delivery | `cloudinary` | `local` |
13
+
14
+ The default can be changed through environment configuration. Missing
15
+ credentials fail closed: email is queued or reports a provider error, and
16
+ media upload is marked failed. A typo or unknown provider never silently falls
17
+ back to a different external service.
18
+
19
+ ## Email interface
20
+
21
+ An email adapter implements `EmailProvider`:
22
+
23
+ ```ts
24
+ type EmailProvider = {
25
+ id: string;
26
+ send(message: EmailMessage): Promise<EmailResult>;
27
+ health(): { configured: boolean; capabilities: string[]; reason?: string };
28
+ };
29
+ ```
30
+
31
+ `EmailMessage` contains only normalized `from`, `to`, `subject`, `html`,
32
+ optional `text`, and optional `replyTo`. The Resend adapter uses the server-only
33
+ `RESEND_API_KEY` and `EMAIL_FROM`; it never accepts credentials from a request.
34
+ The webhook adapter preserves compatibility with existing mail gateways.
35
+
36
+ ## Media interface
37
+
38
+ An image/video/file adapter implements `MediaStorageProvider`:
39
+
40
+ ```ts
41
+ type MediaStorageProvider = {
42
+ id: string;
43
+ upload(input: MediaUpload): Promise<MediaUploadResult>;
44
+ health(): { configured: boolean; capabilities: string[]; reason?: string };
45
+ };
46
+ ```
47
+
48
+ The normalized result stores provider ID, storage key, delivery URL, byte
49
+ count, and MIME type. Local adapters may additionally return a filesystem path;
50
+ public delivery URL and local path must not be conflated. Cloudinary uploads
51
+ are signed server-side and expose only the resulting delivery URL to public
52
+ rendering.
53
+
54
+ ## Adding a provider
55
+
56
+ 1. Implement the relevant interface in `src/lib/providers/`.
57
+ 2. Normalize provider errors into `sent`, `queued`, `failed`, or upload failure
58
+ states; include a bounded, non-secret error message.
59
+ 3. Implement `health()` with capabilities and required configuration names.
60
+ 4. Register the adapter with `registerEmailProvider()` or
61
+ `registerMediaStorageProvider()`.
62
+ 5. Add env names to `.env.example`, but never add values or credentials to
63
+ generated files, logs, database settings, or browser bundles.
64
+ 6. Add a fixture/mock and a contract test for missing credentials, success,
65
+ retryable failure, and idempotent repeated calls.
66
+
67
+ Provider-specific options belong in provider configuration, not in the
68
+ canonical post or report schema.
@@ -0,0 +1,75 @@
1
+ # Maggie SEO Technical Contract
2
+
3
+ This contract fixes the SEO output that agents should generate. Layout and
4
+ visual design remain flexible; these page-level signals are not optional.
5
+
6
+ ## Required post metadata
7
+
8
+ Every published post response should contain exactly one of each where
9
+ applicable:
10
+
11
+ ```text
12
+ <title>{title} | {site name}</title>
13
+ <meta name="description" content="{excerpt}">
14
+ <link rel="canonical" href="{absolute canonical URL}">
15
+ <meta property="og:type" content="article">
16
+ <meta property="og:title" content="{title}">
17
+ <meta property="og:description" content="{excerpt}">
18
+ <meta property="og:url" content="{absolute canonical URL}">
19
+ <meta property="og:image" content="{absolute image URL}">
20
+ <meta name="twitter:card" content="summary_large_image">
21
+ <meta name="twitter:title" content="{title}">
22
+ <meta name="twitter:description" content="{excerpt}">
23
+ ```
24
+
25
+ Rules:
26
+
27
+ - Escape all values for HTML attributes and JSON-LD.
28
+ - Use the configured site origin; never derive canonical URLs from an
29
+ untrusted `Host` header.
30
+ - Do not index preview, query-string, draft, login, or error URLs.
31
+ - Do not emit empty descriptions, relative canonical URLs, or placeholder image
32
+ URLs.
33
+ - A post page has one visible `h1`; headings in body content start at `h2`.
34
+
35
+ ## Article JSON-LD
36
+
37
+ Emit one `Article` or `BlogPosting` object that agrees with visible content:
38
+
39
+ ```json
40
+ {
41
+ "@context": "https://schema.org",
42
+ "@type": "Article",
43
+ "headline": "Post title",
44
+ "description": "Post excerpt",
45
+ "mainEntityOfPage": { "@type": "WebPage", "@id": "https://example.com/posts/post-title" },
46
+ "url": "https://example.com/posts/post-title",
47
+ "datePublished": "2026-08-28T00:00:00Z",
48
+ "dateModified": "2026-08-28T00:00:00Z",
49
+ "author": { "@type": "Person", "name": "Author" },
50
+ "publisher": { "@type": "Organization", "name": "Site name" },
51
+ "image": ["https://example.com/images/post-title.jpg"]
52
+ }
53
+ ```
54
+
55
+ Never invent an author, date, publisher, review, rating, or image. Omit an
56
+ optional property when the source does not provide it. JSON-LD must not claim
57
+ facts that are absent from the rendered page.
58
+
59
+ ## Crawl surfaces
60
+
61
+ `robots.txt` must be a successful plain-text response and reference the
62
+ absolute sitemap URL. The sitemap must:
63
+
64
+ - contain only canonical, published post URLs;
65
+ - use valid XML and an absolute `<loc>`;
66
+ - include `<lastmod>` only when it is a trustworthy ISO date;
67
+ - exclude drafts, redirects, duplicates, unmatched records, and query URLs;
68
+ - use a sitemap index when the output exceeds the chosen URL limit.
69
+
70
+ ## Acceptance checks
71
+
72
+ The adapter or CLI should fail the build or preview check when a published
73
+ post has a missing title, slug, canonical URL, publication date, metadata,
74
+ JSON-LD, or sitemap eligibility decision. Also test a draft, an unpublished
75
+ post, a missing slug, a changed slug with redirect, and a failed content sync.
@@ -0,0 +1,16 @@
1
+ # Maggie Skills Index
2
+
3
+ Skills are the agent-facing workflows. They compose with the tools in
4
+ `../tools/REGISTRY.md` and the portable host templates in `../templates/`.
5
+
6
+ | Skill | Primary job | Dependencies |
7
+ |---|---|---|
8
+ | `maggie-blog-bootstrap` | Build a complete blog in an existing project | site audit, analytics, API Pull |
9
+ | `maggie-clone` | Reverse-engineer authorized URLs into namespaced blog-project pages | browser MCP, clone planner CLI, bootstrap state |
10
+ | `maggie-deployment` | Deploy and verify a dynamic Maggie blog, Cloudflare-first | Cloudflare Workers, D1, R2, KV, Wrangler |
11
+ | `maggie-project-context` | Sync Project, voice, site and CTA context | project-context CLI/API |
12
+ | `maggie-seo-geo` | Plan, audit, create/rewrite and measure SEO/GEO | visibility, SEO audit, GSC/GA4, content quality |
13
+ | `maggie-social-share` | Repurpose and distribute approved content | Project Context, social adapter, analytics |
14
+
15
+ Read only the selected skill and its linked references for a task. Do not load
16
+ all skills as one undifferentiated prompt.
@@ -0,0 +1,243 @@
1
+ ---
2
+ name: maggie-blog-bootstrap
3
+ description: Build or complete a small SEO/GEO-ready blog in an existing vibe-coded project, including posts, metadata, sitemap, analytics hooks, and optional AI CMO API Pull integration. Use when adding a blog to a custom site, WordPress, Wix, Shopify, or headless stack.
4
+ metadata:
5
+ version: 1.3.0
6
+ ---
7
+
8
+ # Maggie Blog Bootstrap
9
+
10
+ Build or complete a small production blog inside an existing vibe-coded
11
+ project. This skill is for Codex, Claude Code, and compatible coding agents.
12
+
13
+ ## Trigger
14
+
15
+ Use when the user asks to add a blog, posts listing, post pages, sitemap, SEO,
16
+ GA4/GSC, AI CMO API Pull, rewrite delivery, or a basic content system.
17
+
18
+ ## Operating rules
19
+
20
+ 1. Analyze the codebase before proposing a stack or editing files. Every
21
+ recommendation must cite the file, configuration, dependency, or command
22
+ output that supports it.
23
+ 2. Preserve existing conventions. Do not replace a working UI system, icon set,
24
+ font, database, CMS, router, or analytics implementation merely because a
25
+ default is available.
26
+ 3. Separate read-only inspection, recommendation, implementation, external
27
+ write, publish, and measurement actions.
28
+ 4. Keep all credentials in environment variables. Add `.env.example`, never
29
+ real values.
30
+ 5. Ask for confirmation at the decision gates below. A user saying “build a
31
+ blog” is not approval to select an unconfirmed database, visual identity,
32
+ language, or publishing policy.
33
+ 6. Prefer deterministic adapters and idempotent upserts over one-off scripts.
34
+
35
+ ## Required phases
36
+
37
+ ### Phase 1: Codebase analysis
38
+
39
+ This is the most important phase. It is read-only unless the user explicitly
40
+ asks for a fix. Search the whole project, not only the obvious `src/` folder,
41
+ and produce an evidence-backed report covering:
42
+
43
+ - framework, language, package manager, router, build command, runtime, and
44
+ deployment target;
45
+ - user-facing language(s), locale, date/number conventions, and whether the
46
+ existing copy is English, Traditional Chinese, Simplified Chinese, or
47
+ multilingual;
48
+ - UI system: Tailwind, CSS Modules, plain CSS, MUI, shadcn, Chakra, existing
49
+ component library, design tokens, spacing scale, and responsive conventions;
50
+ - icon system: Heroicons, Lucide, Font Awesome, custom SVGs, icon package
51
+ dependencies, and whether icons are used consistently;
52
+ - typography: imported/local fonts, `@font-face`, Google Fonts, CSS variables,
53
+ font weights, fallback stack, and whether the current font should be kept;
54
+ - database: engine, connection configuration, ORM/query layer, schema/migrations,
55
+ hosting, environment variables, seed data, and existing post/content tables;
56
+ - content source: Markdown/MDX, database, CMS, API, JSON, hardcoded data, or
57
+ no existing source; include slug/title/status fields and ownership boundaries;
58
+ - existing `/robots.txt`, `/sitemap.xml`, metadata, JSON-LD, GA4, GSC, auth,
59
+ server/runtime boundaries, and API-key safety;
60
+ - tests, lint/typecheck commands, CI, preview command, and production deploy
61
+ command.
62
+
63
+ Also produce three migration-safety inventories inspired by the website build
64
+ kit workflow:
65
+
66
+ - a route inventory separating public routes from API/Ops/admin routes;
67
+ - a preservation inventory for redirects, robots, sitemap, RSS, verification,
68
+ favicon/brand, social-image, and security-header assets;
69
+ - a reproducibility inventory of dev, build, test, lint/typecheck, preview, and
70
+ deploy commands, including the command that must run before handover.
71
+
72
+ These inventories are evidence, not permission to edit. A missing build gate,
73
+ unknown runtime, or route with unclear public/private ownership becomes an
74
+ explicit risk and decision gate.
75
+
76
+ Use targeted searches such as `package.json`, lockfiles, `src/`, `app/`,
77
+ `pages/`, `server/`, `prisma/`, `drizzle/`, migration folders, CSS files,
78
+ font files, SVG/icon imports, `.env.example`, and deployment configuration.
79
+ Never print secret values. Report variable names and whether they are present,
80
+ missing, or referenced only.
81
+
82
+ The report must distinguish:
83
+
84
+ ```text
85
+ Detected confirmed by code or configuration
86
+ Likely supported by multiple clues but not definitive
87
+ Missing required for the proposed implementation but not found
88
+ Unknown cannot be determined safely from the repository
89
+ ```
90
+
91
+ Use this compact report shape so the user can review the evidence before any
92
+ implementation starts:
93
+
94
+ ```text
95
+ Codebase analysis
96
+ - Framework/runtime: [status] ... (evidence: path or command)
97
+ - Project language: [status] ...
98
+ - Content language/locale: [status] ...
99
+ - UI system: [status] ...
100
+ - Icon set: [status] ...
101
+ - Font/typography: [status] ...
102
+ - Database/ORM/schema: [status] ...
103
+ - Content source/post model: [status] ...
104
+ - SEO/analytics/deployment: [status] ...
105
+
106
+ Maggie's recommendation
107
+ - Primary plan: ...
108
+ - Alternatives: ...
109
+ - What will not change: ...
110
+ - Decisions requiring confirmation: ...
111
+ - Risks or unknowns: ...
112
+ ```
113
+
114
+ Do not call a dependency “detected” only because it appears in a lockfile;
115
+ confirm that it is used by the running application or relevant route. Do not
116
+ call a database “available” only because an environment variable is named;
117
+ inspect the connection code and schema/migration usage without revealing its
118
+ value.
119
+
120
+ ### Phase 2: Recommendation
121
+
122
+ After the inventory, propose one primary plan and at most two alternatives.
123
+ Explain the trade-offs and cite the evidence. Cover each decision separately:
124
+
125
+ | Decision | Recommendation requirement |
126
+ |---|---|
127
+ | Framework | Keep the detected framework; choose one only if the project is empty or the user requests a migration |
128
+ | Programming language | Keep detected TypeScript/JavaScript and conventions |
129
+ | Content language | Infer from existing copy, then confirm the default language and future locales |
130
+ | UI system | Reuse the detected system; default to Tailwind only when no coherent system exists |
131
+ | Icon set | Reuse the detected set; default to Heroicons when using Tailwind and no set exists |
132
+ | Font | Reuse the detected font; otherwise propose a small accessible system stack and ask before adding a web font |
133
+ | Database | Reuse the detected engine and ORM; default to SQLite only for a genuinely new small single-instance project |
134
+ | Production database | Do not assume SQLite is suitable for multi-instance/serverless production; propose the smallest supported hosted database and confirm it |
135
+ | Content source | Prefer the existing source; create a minimal posts table or local content collection only after approval |
136
+ | Deployment | Preserve the existing target and server/runtime boundaries |
137
+
138
+ The recommendation must include a “what will not change” section. If the
139
+ database, language, or visual system is unknown, say so instead of guessing.
140
+
141
+ ### Phase 3: Decision gates
142
+
143
+ Ask the user to confirm the recommendation in small groups before writing code:
144
+
145
+ 1. **Foundation:** framework, programming language, content language, runtime,
146
+ and deployment target.
147
+ 2. **Experience:** UI system, icon set, font, theme, and accessibility baseline.
148
+ 3. **Data:** database engine, ORM, migrations, content source, post fields,
149
+ ownership, and local-vs-production storage.
150
+ 4. **Content and publishing:** initial routes, API Pull, sitemap matching,
151
+ rewrite approval, analytics, GSC, and whether the first run is dry-run.
152
+
153
+ Show the proposed choices, detected evidence, files likely to change, and
154
+ unknowns for each gate. If the user confirms only part of a gate, implement
155
+ only that part and leave the rest pending. Do not ask a single broad “is this
156
+ okay?” question that hides database or publishing choices.
157
+
158
+ Recommended defaults for a new, small project are:
159
+
160
+ ```text
161
+ Tailwind CSS UI foundation
162
+ Heroicons icons when no existing icon set is present
163
+ system font stack font unless the user approves a web font
164
+ SQLite local/single-instance development and deployment only
165
+ TypeScript when the selected framework already supports it cleanly
166
+ English only when existing project language is absent
167
+ ```
168
+
169
+ These are proposals, not automatic permission. SQLite, English, a new font,
170
+ or a new design system must never silently replace detected project choices.
171
+
172
+ ### Phase 4: Contract
173
+
174
+ Implement or map these post fields:
175
+
176
+ ```text
177
+ id, slug, title, excerpt, content, publishedAt, updatedAt,
178
+ canonicalUrl, coverImage, author, tags, status
179
+ ```
180
+
181
+ The public contract must support:
182
+
183
+ - `/posts` with stable pagination or a bounded list;
184
+ - `/posts/:slug` with a real 404 for missing/unpublished posts;
185
+ - canonical, Open Graph, Twitter, and Article metadata;
186
+ - post links that are crawlable plain anchors;
187
+ - `robots.txt` and a post-only sitemap;
188
+ - a stable, server-rendered or statically generated reading path.
189
+
190
+ ### Phase 5: Build
191
+
192
+ Implement the host project's equivalent of:
193
+
194
+ - posts index with title, excerpt, date, image, and accessible links;
195
+ - post detail with heading hierarchy, readable content, related posts where
196
+ justified, and visible updated date;
197
+ - sitemap URL generation from published posts only;
198
+ - canonical URL normalization without duplicate slash/query variants;
199
+ - JSON-LD `Article` or `BlogPosting` with valid dates and image URLs;
200
+ - GA4 page view/event hooks that do nothing when analytics is disabled;
201
+ - GSC verification via a public token or DNS instruction, never a private key.
202
+
203
+ ### Phase 6: Optional AI CMO integration
204
+
205
+ Only when requested and configured, add the adapter described in
206
+ `tools/integrations/maggie-api-pull.md`. It must:
207
+
208
+ - resolve the domain from the API key, not from user input;
209
+ - poll `/posts` and `/updates` on a schedule;
210
+ - upsert by remote content id and preserve the remote canonical URL;
211
+ - never change a slug during rewrite;
212
+ - store delivery state and last error;
213
+ - expose a dry-run/import preview before first publish;
214
+ - report successful local publication with `report-state`.
215
+ - sync the sanitized `/project-context` response into a generated local file;
216
+ map its project CTA into the portable starter's `conversion.ctas` fields.
217
+
218
+ ### Phase 7: Verify
219
+
220
+ Run `python3 tools/clis/site_audit.py <production-url> --json` and host-project
221
+ tests. Manually verify:
222
+
223
+ ```text
224
+ /posts
225
+ /posts/<known-slug>
226
+ /posts/<missing-slug> -> 404
227
+ /robots.txt
228
+ /sitemap.xml
229
+ analytics disabled -> no crash and no analytics request
230
+ ```
231
+
232
+ Report known limitations, especially if the project is client-rendered,
233
+ requires authentication for content, or has no stable post database.
234
+
235
+ ## Completion contract
236
+
237
+ Finish with:
238
+
239
+ - files changed and why;
240
+ - commands/tests run;
241
+ - environment variables added, by name only;
242
+ - whether publishing and API Pull are enabled or still dry-run;
243
+ - remaining risks and the next safe action.