@hanzlaa/rcode 4.3.3 → 4.4.1

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 (118) hide show
  1. package/CONTRIBUTING.md +1 -1
  2. package/README.md +28 -5
  3. package/cli/doctor.js +21 -3
  4. package/cli/generate-command-skills.cjs +1 -1
  5. package/cli/index.js +5 -1
  6. package/cli/install.js +7 -9
  7. package/cli/postinstall.js +22 -2
  8. package/cli/uninstall.js +48 -6
  9. package/dist/rcode.js +202 -203
  10. package/package.json +13 -23
  11. package/rcode/agents/rcode-codebase-mapper.md +12 -0
  12. package/rcode/agents/rcode-phase-researcher.md +13 -0
  13. package/rcode/agents/rcode-project-researcher.md +32 -0
  14. package/rcode/agents/rcode-roadmapper.md +15 -0
  15. package/rcode/agents/rules/planner/common-patterns.md +40 -0
  16. package/rcode/bin/lib/roadmap.cjs +184 -11
  17. package/rcode/bin/rcode-hooks.cjs +102 -151
  18. package/rcode/bin/rcode-tools.cjs +669 -55
  19. package/rcode/commands/lazy.md +10 -0
  20. package/rcode/data/intent-table.json +87 -0
  21. package/rcode/modules/seo.yaml +22 -0
  22. package/rcode/references/project-types.yaml +75 -0
  23. package/rcode/references/verb-dictionary.md +1 -1
  24. package/rcode/skills/SKILLS_INDEX.md +18 -1
  25. package/rcode/skills/actions/1-analysis/rcode-prfaq/SKILL.md +1 -1
  26. package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/SKILL.md +4 -21
  27. package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/templates/heartbeat.sh +0 -0
  28. package/rcode/skills/actions/4-implementation/rcode-scaffold-project/SKILL.md +60 -1
  29. package/rcode/skills/core/rcode-init/scripts/__pycache__/rcode_init.cpython-38.pyc +0 -0
  30. package/rcode/skills/core/rcode-init/scripts/tests/__pycache__/test_rcode_init.cpython-38.pyc +0 -0
  31. package/rcode/skills/seo/module.yaml +20 -0
  32. package/rcode/skills/seo/on-page-seo-auditor/SKILL.md +308 -0
  33. package/rcode/skills/seo/on-page-seo-auditor/references/audit-example.md +109 -0
  34. package/rcode/skills/seo/on-page-seo-auditor/references/audit-templates.md +427 -0
  35. package/rcode/skills/seo/on-page-seo-auditor/references/bulk-audit-playbook.md +116 -0
  36. package/rcode/skills/seo/on-page-seo-auditor/references/scoring-rubric.md +525 -0
  37. package/rcode/skills/seo/rank-and-rent-local-seo/SKILL.md +94 -0
  38. package/rcode/skills/seo/rank-and-rent-local-seo/rules/city-matrix-and-pages.md +76 -0
  39. package/rcode/skills/seo/rank-and-rent-local-seo/rules/monetization.md +70 -0
  40. package/rcode/skills/seo/rank-and-rent-local-seo/rules/niche-selection.md +60 -0
  41. package/rcode/skills/seo/rank-and-rent-local-seo/rules/subniche-discovery.md +66 -0
  42. package/rcode/skills/seo/rank-and-rent-local-seo/templates/service-city-page.md +36 -0
  43. package/rcode/skills/seo/rank-and-rent-local-seo/templates/subniche-research-prompt.md +34 -0
  44. package/rcode/skills/seo/seo-audit/SKILL.md +412 -0
  45. package/rcode/skills/seo/seo-audit/evals/evals.json +136 -0
  46. package/rcode/skills/seo/seo-audit/references/ai-writing-detection.md +200 -0
  47. package/rcode/skills/seo/seo-content-factory/SKILL.md +130 -0
  48. package/rcode/skills/seo/seo-content-factory/rules/agents.md +80 -0
  49. package/rcode/skills/seo/seo-content-factory/rules/herdr-wave-mapping.md +80 -0
  50. package/rcode/skills/seo/seo-content-factory/rules/pipeline.md +102 -0
  51. package/rcode/skills/seo/seo-content-factory/rules/programmatic-pages.md +107 -0
  52. package/rcode/skills/seo/seo-content-factory/rules/quality-gates.md +68 -0
  53. package/rcode/skills/seo/seo-content-factory/rules/weekly-cadence.md +61 -0
  54. package/rcode/skills/seo/seo-content-factory/templates/BACKLOG.md +23 -0
  55. package/rcode/skills/seo/seo-content-factory/templates/agent-prompts/01-funnel-A1-A4.md +63 -0
  56. package/rcode/skills/seo/seo-content-factory/templates/agent-prompts/02-fanout-editorial-A5-A6-A8.md +28 -0
  57. package/rcode/skills/seo/seo-content-factory/templates/agent-prompts/03-fanout-programmatic-A7-A6-A8.md +25 -0
  58. package/rcode/skills/seo/seo-content-factory/templates/agent-prompts/04-loop-A9-A10.md +34 -0
  59. package/rcode/skills/seo/seo-content-factory/templates/article.mdx +39 -0
  60. package/rcode/skills/seo/seo-content-factory/templates/cluster.schema.json +52 -0
  61. package/rcode/skills/seo/seo-content-factory/templates/content-brief.md +51 -0
  62. package/rcode/skills/seo/seo-content-factory/templates/jsonld-builders.ts +49 -0
  63. package/rcode/skills/seo/seo-content-factory/templates/keywords.csv +13 -0
  64. package/rcode/skills/seo/seo-content-factory/templates/programmatic-page.tsx +58 -0
  65. package/rcode/skills/seo/seo-content-writer/SKILL.md +263 -0
  66. package/rcode/skills/seo/seo-content-writer/references/content-structure-templates.md +875 -0
  67. package/rcode/skills/seo/seo-content-writer/references/instructions-detail.md +239 -0
  68. package/rcode/skills/seo/seo-content-writer/references/seo-writing-checklist.md +250 -0
  69. package/rcode/skills/seo/seo-content-writer/references/title-formulas.md +339 -0
  70. package/rcode/skills/seo/seo-growth-orchestrator/SKILL.md +79 -0
  71. package/rcode/skills/seo/seo-growth-orchestrator/rules/backlinks.md +29 -0
  72. package/rcode/skills/seo/seo-growth-orchestrator/rules/content-engine.md +27 -0
  73. package/rcode/skills/seo/seo-growth-orchestrator/rules/dos-and-donts.md +40 -0
  74. package/rcode/skills/seo/seo-growth-orchestrator/rules/goals-protocol.md +34 -0
  75. package/rcode/skills/seo/seo-growth-orchestrator/rules/local-seo-stack.md +35 -0
  76. package/rcode/skills/seo/seo-growth-orchestrator/rules/mrr-sprint.md +27 -0
  77. package/rcode/skills/seo/seo-growth-orchestrator/rules/tools.md +19 -0
  78. package/rcode/skills/seo/seo-growth-orchestrator/templates/backlink-research.md +29 -0
  79. package/rcode/skills/seo/seo-growth-orchestrator/templates/goal-protocol.md +35 -0
  80. package/rcode/skills/seo/seo-growth-orchestrator/templates/local-citations.md +24 -0
  81. package/rcode/skills/seo/seo-growth-orchestrator/templates/local-city-pages.md +27 -0
  82. package/rcode/skills/seo/seo-growth-orchestrator/templates/local-gbp-categories.md +23 -0
  83. package/rcode/skills/seo/seo-growth-orchestrator/templates/local-gsc-goldmine.md +27 -0
  84. package/rcode/skills/seo/seo-growth-orchestrator/templates/local-review-mining.md +26 -0
  85. package/rcode/skills/seo/seo-growth-orchestrator/templates/mrr-30day-plan.md +19 -0
  86. package/rcode/skills/seo/seo-growth-orchestrator/templates/mrr-cut.md +13 -0
  87. package/rcode/skills/seo/seo-growth-orchestrator/templates/mrr-opportunity-finder.md +17 -0
  88. package/rcode/skills/seo/seo-growth-orchestrator/templates/mrr-role-model.md +18 -0
  89. package/rcode/skills/seo/seo-site-builder/SKILL.md +149 -0
  90. package/rcode/skills/seo/seo-site-builder/rules/01-niche-discovery.md +64 -0
  91. package/rcode/skills/seo/seo-site-builder/rules/02-deep-research.md +164 -0
  92. package/rcode/skills/seo/seo-site-builder/rules/03-keyword-strategy.md +82 -0
  93. package/rcode/skills/seo/seo-site-builder/rules/04-content-plan.md +173 -0
  94. package/rcode/skills/seo/seo-site-builder/rules/05-site-build.md +187 -0
  95. package/rcode/skills/seo/seo-site-builder/rules/06-yolo.md +127 -0
  96. package/rcode/skills/seo/seo-site-builder/templates/article-stub.mdx +62 -0
  97. package/rcode/skills/seo/seo-site-builder/templates/image-prompt.md +97 -0
  98. package/rcode/skills/seo/seo-site-builder/templates/keyword-export.md +45 -0
  99. package/rcode/skills/seo/seo-site-builder/templates/niche-scorecard.md +28 -0
  100. package/rcode/skills/seo/technical-seo-checker/SKILL.md +329 -0
  101. package/rcode/skills/seo/technical-seo-checker/references/bulk-audit-playbook.md +118 -0
  102. package/rcode/skills/seo/technical-seo-checker/references/ecommerce-platform-patterns.md +166 -0
  103. package/rcode/skills/seo/technical-seo-checker/references/http-status-codes.md +705 -0
  104. package/rcode/skills/seo/technical-seo-checker/references/llm-crawler-handling.md +257 -0
  105. package/rcode/skills/seo/technical-seo-checker/references/pre-migration-playbook.md +137 -0
  106. package/rcode/skills/seo/technical-seo-checker/references/robots-txt-reference.md +717 -0
  107. package/rcode/skills/seo/technical-seo-checker/references/technical-audit-example.md +169 -0
  108. package/rcode/skills/seo/technical-seo-checker/references/technical-audit-templates.md +436 -0
  109. package/rcode/templates/settings-hooks.json +4 -0
  110. package/rcode/workflows/do.md +16 -0
  111. package/rcode/workflows/execute-sprint.md +22 -0
  112. package/rcode/workflows/execute.md +17 -3
  113. package/rcode/workflows/help.md +0 -2
  114. package/rcode/workflows/new-milestone.md +21 -9
  115. package/rcode/workflows/new-project-create-roadmap.md +2 -0
  116. package/rcode/workflows/new-project-roadmap.md +2 -0
  117. package/rcode/workflows/new-project.md +3 -0
  118. package/rcode/workflows/plan.md +15 -2
@@ -0,0 +1,107 @@
1
+ # Programmatic Pages — marketing/ wiring
2
+
3
+ This is the concrete Next.js 16 App Router implementation for the canonical `marketing/`
4
+ site (`/home/hanzla/development/teaching/schedule-manager/marketing`). It honors the site's
5
+ existing conventions: **TS data files in `src/data/` (programmatic) + MDX (editorial)**.
6
+ Do NOT add a CMS, contentlayer, gray-matter-DB, or runtime fetching — the site is SSG.
7
+
8
+ ## Two output channels
9
+
10
+ | Channel | Source | Route | Scale | Use for |
11
+ |---------|--------|-------|-------|---------|
12
+ | **Programmatic** | `src/data/seo/*.ts` (typed) | `src/app/(seo)/[...]/page.tsx` + `generateStaticParams` | 1,000s | service×city, service×industry, location pages |
13
+ | **Editorial (MDX)** | `src/content/<type>/*.mdx` | `src/app/blog/[slug]` (already a shell) + new `alternatives`/`comparisons` | ~100 | alternatives, comparisons, cornerstone, statistics, questions |
14
+
15
+ ## Programmatic: the 2,000-page pattern
16
+
17
+ 100 cities × 20 services = 2,000 pages from **~5 files**, not 2,000 files.
18
+
19
+ ### 1. Dimension registries — `src/data/seo/` (matches existing `src/data/*.ts`)
20
+ ```ts
21
+ // src/data/seo/services.ts
22
+ export interface SeoService {
23
+ slug: string; name: string; h1: string;
24
+ benefits: string[]; painPoints: string[]; faqs: { q: string; a: string }[];
25
+ }
26
+ export const services: SeoService[] = [ /* 20 records, A7-generated */ ]
27
+
28
+ // src/data/seo/cities.ts
29
+ export interface SeoCity { slug: string; name: string; region: string; country: string }
30
+ export const cities: SeoCity[] = [ /* 100 records */ ]
31
+ ```
32
+
33
+ ### 2. One dynamic route for the cross-product
34
+ ```tsx
35
+ // src/app/(seo)/[service]/[city]/page.tsx
36
+ import { services } from '@/data/seo/services'
37
+ import { cities } from '@/data/seo/cities'
38
+ import { notFound } from 'next/navigation'
39
+
40
+ export function generateStaticParams() {
41
+ return services.flatMap(s => cities.map(c => ({ service: s.slug, city: c.slug })))
42
+ }
43
+
44
+ export async function generateMetadata({ params }) {
45
+ const { service, city } = await params
46
+ const s = services.find(x => x.slug === service); const c = cities.find(x => x.slug === city)
47
+ if (!s || !c) return {}
48
+ return {
49
+ title: `${s.name} in ${c.name} | LeadLyze`,
50
+ description: `${s.name} for ${c.name} businesses — ${s.benefits[0]}. Book more meetings with LeadLyze.`,
51
+ alternates: { canonical: `https://leadlyze.com/${service}/${city}` },
52
+ }
53
+ }
54
+
55
+ export default async function Page({ params }) {
56
+ const { service, city } = await params
57
+ const s = services.find(x => x.slug === service); const c = cities.find(x => x.slug === city)
58
+ if (!s || !c) notFound()
59
+ // Hero → Benefits → Case Studies → Pricing → FAQ → CTA, all composed from s + c
60
+ // ...
61
+ }
62
+ ```
63
+ Full route template: `templates/programmatic-page.tsx`.
64
+
65
+ ### 3. Thin-content guard (mandatory — see quality-gates.md)
66
+ Templated pages are the #1 thin-content / doorway-page risk. Each page MUST inject ≥2
67
+ **city-specific or service-specific** unique elements (local stat, named local use-case,
68
+ varied intro sentence keyed off `c.region`/`s.painPoints`) so no two pages are near-duplicates.
69
+ A page that's pure boilerplate with the city name swapped ships as `noindex`.
70
+
71
+ ## Editorial: the MDX channel
72
+
73
+ The blog `[slug]` shell already says *"fetch MDX/CMS content by slug"*. Wire it minimally:
74
+
75
+ ```ts
76
+ // src/lib/mdx.ts — tiny loader, no DB
77
+ import { compileMDX } from 'next-mdx-remote/rsc' // add dep ONLY with user consent
78
+ import fs from 'node:fs/promises'
79
+ export async function getDoc(type: string, slug: string) { /* read src/content/<type>/<slug>.mdx, compile */ }
80
+ export async function listSlugs(type: string) { /* readdir, strip .mdx */ }
81
+ ```
82
+ > **DECIDED (2026-06-14):** use `next-mdx-remote` for the editorial channel. It's a new dep —
83
+ > add it at Phase 0 (`pnpm add next-mdx-remote`) and confirm `pnpm build` still passes before
84
+ > wave 1. (Zero-dep fallback, only if the user reverses: structured TS bodies rendered via the
85
+ > existing `src/components/blog` components.)
86
+
87
+ `generateStaticParams` for blog/alternatives/comparisons then returns `listSlugs(type)`.
88
+
89
+ ## Schema (A8) — extend the existing helper
90
+
91
+ `src/lib/jsonld.ts` already exists. Add typed builders (`faqPage`, `softwareApplication`,
92
+ `product`, `breadcrumbList`, `aggregateRating`) and render via a `<JsonLd>` component —
93
+ never hand-write `<script type="application/ld+json">` strings inline.
94
+
95
+ ## Sitemap
96
+
97
+ `next-sitemap` is already configured (`next-sitemap.config.js`, siteUrl leadlyze.com). It
98
+ crawls the built `.next` output, so all `generateStaticParams` pages are included
99
+ automatically on `pnpm build && next-sitemap`. For 2,000+ URLs, enable sitemap splitting:
100
+ add `sitemapSize: 5000` (default already chunks at 5k) — verify `robots.txt` references the
101
+ index. No per-page sitemap code needed.
102
+
103
+ ## Establishing the content layer (Phase 0, once)
104
+
105
+ If `src/data/seo/` and `src/app/(seo)/` don't exist yet, the orchestrator scaffolds them
106
+ before wave 1: create the dirs, drop the route template + empty typed registries, confirm
107
+ `pnpm build` still passes (baseline). Only THEN do fan-out waves populate them.
@@ -0,0 +1,68 @@
1
+ # Quality Gates — the firewall against AI slop & thin pages
2
+
3
+ Scaling to 2,000 pages is worthless if Google classifies them as thin/doorway/spam. These
4
+ gates are non-negotiable. A page that fails ships as `noindex`, never as raw indexable content.
5
+
6
+ ## Gate 1 — Briefs before prose (hard)
7
+
8
+ The Writer (A5) **refuses to run** for any slug without `briefs/<slug>.md` marked
9
+ `status: approved`. Rationale: a brief forces real-SERP research, an outline, entities, and a
10
+ unique angle BEFORE generation — which is the difference between a ranked page and generic
11
+ filler. Orchestrator enforces: when dispatching a Writer pane, it verifies the brief exists
12
+ first; if missing, it routes the cluster back to A4, not forward to A5.
13
+
14
+ ## Gate 2 — Anti-generic-AI content rules (A5 must obey)
15
+
16
+ BANNED in any generated page:
17
+ - Filler openers: "In today's fast-paced world", "In the digital age", "When it comes to…".
18
+ - Empty hedging: "can help", "may be able to", "is a great way to" with no specifics.
19
+ - Unsupported stats: every number is cited (source + year) or cut.
20
+ - Restated headings as the first sentence of each section.
21
+ - Conclusion that summarizes with no new CTA/next step.
22
+
23
+ REQUIRED in any generated page:
24
+ - ≥1 concrete LeadLyze example or named use-case.
25
+ - ≥1 data table or comparison matrix.
26
+ - Real statistics with citations.
27
+ - An FAQ section answering the People-Also-Ask questions from the brief.
28
+ - Inline internal links from the brief (not dumped at the bottom).
29
+ - A specific CTA tied to the page's funnel stage.
30
+
31
+ ## Gate 3 — Thin / duplicate-content gate (programmatic pages)
32
+
33
+ The doorway-page killer. For templated pages each MUST have:
34
+ - Unique `<title>`, `<h1>`, and **first 2 sentences** (keyed off the varying dimension).
35
+ - ≥2 dimension-specific unique blocks (local stat, named local use-case, region-keyed copy).
36
+ - ≥ the cluster's `min_words` floor of genuinely varying text (boilerplate doesn't count).
37
+ - Pairwise similarity < 0.8 vs sibling pages (cheap check: shingle/Jaccard on body text).
38
+
39
+ Fail → `noindex` + queue for enrichment. NEVER ship a city-swap-only page indexable.
40
+
41
+ ## Gate 4 — Indexability gate (every page, pre-ship)
42
+
43
+ Before a page moves `linked → shipped`:
44
+ - [ ] Unique title + meta description (≤60 / ≤155 chars), self-referencing canonical.
45
+ - [ ] ≥10 inbound + ≥10 outbound internal links recorded in `link-map.json` (no orphans).
46
+ - [ ] Valid JSON-LD matching page type (A8), validates against schema.org.
47
+ - [ ] Word count ≥ cluster floor; passes Gate 2/3.
48
+ - [ ] No broken internal links (every link target exists in the route set).
49
+ - [ ] `pnpm build` static-generates it; no tsc error introduced.
50
+
51
+ ## Gate 5 — Build/type baseline (per wave, orchestrator)
52
+
53
+ Capture `pnpm tsc --noEmit | grep -c "error TS"` at campaign start. After each wave merge,
54
+ re-run; any wave that raises the count is reverted from the integration branch and the
55
+ offending cluster re-dispatched. (Children never run tsc — orchestrator-only, per
56
+ `feedback_no_build_in_child_agents`.)
57
+
58
+ ## Gate 6 — Evidence gate (A1/A2/A9/A10)
59
+
60
+ No keyword enters `keywords.csv` without a real Semrush volume+KD. AI-estimated metrics are
61
+ a hypothesis flagged `est=true`, never treated as ground truth, and must be confirmed against
62
+ a live SERP or Semrush pull before a money page is built on them.
63
+
64
+ ## What "shipped" means
65
+
66
+ `shipped` = merged into the integration branch, passed Gates 1–6, recorded in `BACKLOG.md`.
67
+ It does **not** mean pushed to master or deployed — that's a separate, explicit,
68
+ user-consented step (see all three skills' push rules).
@@ -0,0 +1,61 @@
1
+ # Weekly Cadence + 90-Day Plan + the A9/A10 Loop
2
+
3
+ The factory has a one-shot ramp (build the backlog of pages) and a steady-state loop (keep
4
+ discovering + refreshing). Both are encoded here. In AUTO mode the orchestrator can run the
5
+ whole week's stages back-to-back across waves; the day labels are the *logical* order, not a
6
+ requirement to wait 24h between them.
7
+
8
+ ## Weekly logical order (one full turn of the crank)
9
+
10
+ | Stage | Agents | Output |
11
+ |-------|--------|--------|
12
+ | Research | A1, A10 | competitor pages + net-new keyword opportunities |
13
+ | Expand | A2 | `keywords.csv` grows |
14
+ | Architect | A3 | `clusters.json` updated, new clusters → BACKLOG |
15
+ | Brief | A4 | `briefs/<slug>.md` for the wave's editorial clusters |
16
+ | Write | A5 (fan-out waves) | `src/content/**.mdx` |
17
+ | Interlink | A6 | `link-map.json` ≥10/≥10 per page |
18
+ | Programmatic | A7 + A8 | `src/data/seo/*.ts` + routes + schema |
19
+ | Publish | gates + merge | clusters → `shipped` (push only on consent) |
20
+ | Analyze | A9 | GSC deltas → refresh decaying pages, feed A10 |
21
+
22
+ ## 90-day target (state honestly to the user)
23
+
24
+ | Month | Cumulative pages | Emphasis |
25
+ |-------|------------------|----------|
26
+ | 1 | 200 | programmatic location/industry (fast to index) + 20 cornerstone editorial |
27
+ | 2 | 500 | + alternative + comparison money pages |
28
+ | 3 | 1,000+ | + statistics/template/tool/question pages; refresh cycle steady-state |
29
+
30
+ Reality check to set with the user: programmatic pages can index in **weeks**; cornerstone
31
+ editorial is a **60–180 day** payoff. New content rarely ranks in 30 days. Don't promise
32
+ rankings on a 30-day horizon — promise *production throughput* + a compounding curve.
33
+
34
+ ## The recurring loop (A9 + A10 — never "done")
35
+
36
+ These are cron-shaped. Under `/loop` or `/schedule`, the orchestrator wakes them:
37
+
38
+ **A10 Opportunity Finder — daily**
39
+ 1. Semrush `organic_research` diff: keywords competitors now rank for that aren't in `keywords.csv`.
40
+ 2. Score: `volume × intent_weight × winnability`. Dedupe vs existing keywords.
41
+ 3. Auto-brief the top N → append clusters to `BACKLOG.md` as `pending`.
42
+ 4. Next fan-out wave picks them up. No human in the loop unless a money cluster needs sign-off.
43
+
44
+ **A9 Content Refresh — weekly**
45
+ 1. Pull `gsc-deltas.csv` (pages with falling position over 28 days) via browser-harness/GSC.
46
+ 2. For each decayer: diff vs current top-3 SERP. Update stale stats, add new competitors,
47
+ add fresh internal links + examples, bump `dateModified`.
48
+ 3. Record the diff; re-run gates; mark refreshed.
49
+
50
+ ## Backlog states (the frontier)
51
+
52
+ `BACKLOG.md` tracks each cluster through: `pending → briefed → written → linked → shipped`
53
+ (+ `noindex` for gate failures awaiting enrichment). This is the durable memory that
54
+ survives auto-compact — the orchestrator always resumes from the file, never from chat
55
+ recollection. Commit it at Phase 0 and after every wave.
56
+
57
+ ## Heartbeat honesty (inherited from autonomous-fix-campaign)
58
+
59
+ `ScheduleWakeup` only fires under `/loop`. Outside it, saying "I'll wake in 20 min" is a lie.
60
+ At Phase 0 confirm the heartbeat path with the user — `/loop`, `/schedule` cron, or manual
61
+ ping — and act accordingly. Never go silent while panes are `working`.
@@ -0,0 +1,23 @@
1
+ # SEO Content Factory — BACKLOG (durable frontier)
2
+ # Commit at Phase 0 and after every wave. The orchestrator resumes from THIS file,
3
+ # never from chat memory. States: pending → briefed → written → linked → shipped (+ noindex).
4
+
5
+ ## Campaign config
6
+ - target_site: /home/hanzla/development/teaching/schedule-manager/marketing
7
+ - integration_branch: seo-factory-integration
8
+ - tsc_baseline: <fill: `pnpm tsc --noEmit | grep -c "error TS"`>
9
+ - push_policy: LOCAL ONLY — no push/deploy without explicit user consent
10
+ - heartbeat: <fill: /loop | /schedule cron | manual ping>
11
+ - seeds: ["lead generation software", "cold email", "ai cold calling", "sales sequences"]
12
+ - competitors: ["apollo.io", "instantly.ai", "lemlist.com", "smartlead.ai"]
13
+
14
+ ## Clusters
15
+ | cluster_id | hub | page_kind | spokes | state | wave | notes |
16
+ |---|---|---|---|---|---|---|
17
+ | alt-apollo | alternatives | editorial | 1 | pending | – | money page |
18
+ | ind-roofers | lead-generation | editorial | 1 | pending | – | |
19
+ | loc-grid | lead-generation×city | programmatic | 2000 | pending | – | 100 cities × 20 services |
20
+ | stat-coldemail | statistics | editorial | 1 | pending | – | linkable asset |
21
+
22
+ ## Wave log
23
+ <!-- append: wave N | clusters | merged SHA | pages shipped | tsc delta -->
@@ -0,0 +1,63 @@
1
+ # Funnel prompts (A1→A4) — run SEQUENTIALLY, one agent, before any fan-out.
2
+
3
+ Common footer appended to EVERY prompt below:
4
+ > Pull REAL data from Semrush MCP / live SERP before asserting any number — never invent volume/KD/traffic.
5
+ > Write output to the canonical file path under `.planning/seo-factory/`. Do not print results only to chat.
6
+ > You are working in the `marketing/` repo. Commit your output file with a clear message.
7
+
8
+ ---
9
+
10
+ ## A1 — Competitor Research
11
+ ```
12
+ You are an SEO competitor analyst for LeadLyze (a lead-generation / sales-outreach platform:
13
+ email + LinkedIn + AI cold calling sequences).
14
+
15
+ Competitors: apollo.io, instantly.ai, lemlist.com, smartlead.ai.
16
+
17
+ Using Semrush MCP (organic_research, overview_research) + web search, for EACH competitor pull
18
+ their highest-traffic organic pages. For each page produce a CSV row:
19
+ keyword,type,intent,traffic,funnel,source_url,competitor
20
+ - type ∈ industry | location | alternative | comparison | statistics | template | tool | blog
21
+ - intent ∈ informational | commercial | transactional | navigational
22
+ - funnel ∈ learn | compare | buy
23
+ Keep only rows where LeadLyze could plausibly compete. ≥200 rows.
24
+ Write to .planning/seo-factory/competitors.csv.
25
+ ```
26
+
27
+ ## A2 — Keyword Expansion
28
+ ```
29
+ Read .planning/seo-factory/competitors.csv. Seeds: "lead generation software", "cold email",
30
+ "ai cold calling", "sales sequences".
31
+
32
+ Expand every seed across all 8 modifier axes: industry, location, alternative, comparison,
33
+ template, statistics, question, tool. Use Semrush keyword_research (related + questions +
34
+ broad match) to pull REAL volume and KD for each. Drop volume<10 OR KD>70 unless it is a clear
35
+ money term. De-dupe. Thousands of rows.
36
+ Write to .planning/seo-factory/keywords.csv with columns:
37
+ keyword,parent_seed,modifier_type,volume,kd,intent,funnel,cluster_id (leave cluster_id blank)
38
+ ```
39
+
40
+ ## A3 — Sitemap Architect
41
+ ```
42
+ Read .planning/seo-factory/keywords.csv. Cluster keywords by SERP overlap (use the
43
+ claude-seo:seo-cluster skill / serp-analysis) into hub-and-spoke topics.
44
+
45
+ For each cluster decide page_kind:
46
+ - programmatic = high-volume templated dimensions (service×city, service×industry) → declare dimensions
47
+ - editorial = where prose ranks (alternatives, comparisons, cornerstone, statistics)
48
+ Mark each spoke type (money|supporting|blog) and min_words.
49
+ Write .planning/seo-factory/clusters.json (validate against templates/cluster.schema.json) and
50
+ write each keyword's cluster_id back into keywords.csv. Append new clusters to BACKLOG.md as pending.
51
+ ```
52
+
53
+ ## A4 — Content Brief Generator (the GATE feeder)
54
+ ```
55
+ Read .planning/seo-factory/clusters.json. For EACH editorial cluster (skip programmatic ones),
56
+ read the LIVE top-5 Google results for its primary keyword (serp-analysis) and produce a brief
57
+ following templates/content-brief.md EXACTLY:
58
+ title, meta, search intent, full H2/H3 outline (mirror the winning structure + 1 unique
59
+ LeadLyze angle the top-5 lack), FAQ from People-Also-Ask, entities, inline internal links,
60
+ CTA, schema types, min_words.
61
+ Write each to .planning/seo-factory/briefs/<slug>.md with status: approved.
62
+ Do NOT write any article — briefs only. Mark each cluster `briefed` in BACKLOG.md.
63
+ ```
@@ -0,0 +1,28 @@
1
+ # Fan-out pane prompt — EDITORIAL cluster (runs A5→A6→A8 in one worktree).
2
+ # One pane per cluster. Orchestrator fills {{CLUSTER_ID}}, {{BRANCH}}, {{SLUGS}}.
3
+
4
+ ```
5
+ You are an SEO content agent in an ISOLATED git worktree on branch {{BRANCH}}, inside the
6
+ LeadLyze `marketing/` repo. Work and commit ONLY here. Do NOT run pnpm build / tsc / dev /
7
+ install — use `node --check` only. Do NOT push.
8
+
9
+ Your cluster: {{CLUSTER_ID}}. Its approved briefs: {{SLUGS}} (under .planning/seo-factory/briefs/).
10
+
11
+ GATE: For each slug, confirm .planning/seo-factory/briefs/<slug>.md exists with status: approved.
12
+ If a brief is missing, STOP that slug and report it — never write an article without a brief.
13
+
14
+ For each slug:
15
+ 1. (A5 Writer) Write src/content/<type>/<slug>.mdx STRICTLY to its brief, using
16
+ templates/article.mdx frontmatter. MANDATORY quality rules (quality-gates.md Gate 2):
17
+ - real LeadLyze examples + named use-cases, ≥1 data table, cited statistics, FAQ section
18
+ - inline internal links from the brief (not dumped at bottom), funnel-matched CTA
19
+ - BANNED: "in today's fast-paced world", empty hedging, uncited numbers, restated headings.
20
+ 2. (A6 Interlinker) Add ≥10 inbound + ≥10 outbound internal links with KEYWORD-VARIED anchors
21
+ (never the same anchor twice). Prefer same-cluster + hub↔spoke. Record in
22
+ .planning/seo-factory/link-map.json (write ONLY your cluster's keys).
23
+ 3. (A8 Schema) Inject JSON-LD via src/lib/jsonld.ts builders (FAQPage + the page's type +
24
+ BreadcrumbList). No hand-written <script> strings.
25
+
26
+ Commit each page separately. Log what you shipped to .planning/seo-factory/AUDIT-{{CLUSTER_ID}}.md
27
+ (page list, word counts, link counts). When done, give a one-line recap.
28
+ ```
@@ -0,0 +1,25 @@
1
+ # Fan-out pane prompt — PROGRAMMATIC cluster (runs A7→A6→A8 in one worktree).
2
+ # Skips the Writer (no per-page prose). Orchestrator fills {{CLUSTER_ID}}, {{BRANCH}}, {{DIMENSIONS}}.
3
+
4
+ ```
5
+ You are a programmatic-SEO agent in an ISOLATED git worktree on branch {{BRANCH}}, inside the
6
+ LeadLyze `marketing/` repo. Work and commit ONLY here. Do NOT run pnpm build / tsc / dev /
7
+ install — `node --check` only. Do NOT push.
8
+
9
+ Cluster: {{CLUSTER_ID}}. Dimensions: {{DIMENSIONS}} (e.g. service × city → services.ts × cities.ts).
10
+
11
+ 1. (A7) Build/extend the typed registries under src/data/seo/ (e.g. services.ts, cities.ts,
12
+ industries.ts) — typed TS exports matching the existing src/data/*.ts convention. Populate
13
+ real records (real city names/regions; real service benefits/painPoints/faqs from the cluster).
14
+ 2. (A7) Create/confirm ONE dynamic route per pattern under src/app/(seo)/... using
15
+ generateStaticParams over the cross-product (see templates/programmatic-page.tsx). 100×20 = 2000
16
+ pages from ~5 files — never 2000 separate files.
17
+ THIN-CONTENT GATE (quality-gates.md Gate 3): every page MUST inject ≥2 dimension-specific
18
+ unique blocks (region-keyed intro, local stat, named local use-case). A pure city-swap page
19
+ is a doorway page — forbidden. Keyword-vary the title, H1, and first 2 sentences.
20
+ 3. (A6) Wire hub↔spoke + cross-links; record your cluster's keys in link-map.json.
21
+ 4. (A8) Add typed JSON-LD builders to src/lib/jsonld.ts for this page type; render via <JsonLd/>.
22
+
23
+ `node --check` every touched .ts/.tsx. Commit. Log page count + sample slugs to
24
+ .planning/seo-factory/AUDIT-{{CLUSTER_ID}}.md. One-line recap when done.
25
+ ```
@@ -0,0 +1,34 @@
1
+ # Loop prompts (A9 weekly, A10 daily) — the recurring engine. Never "done".
2
+
3
+ Common footer:
4
+ > Pull REAL data (Semrush / GSC / live SERP). Write to canonical files. Dedupe against existing.
5
+
6
+ ---
7
+
8
+ ## A10 — Opportunity Finder (daily)
9
+ ```
10
+ You are an SEO opportunity scout for LeadLyze. Competitors: apollo.io, instantly.ai,
11
+ lemlist.com, smartlead.ai.
12
+
13
+ Using Semrush organic_research, find keywords competitors NOW rank for that are NOT in
14
+ .planning/seo-factory/keywords.csv (diff vs the file). Score each by volume × intent_weight ×
15
+ winnability (lower KD + topical fit = higher). Dedupe against keywords.csv.
16
+
17
+ For the top N: append them to keywords.csv, create cluster stubs, and append those clusters to
18
+ BACKLOG.md as `pending` so the next fan-out wave picks them up. For money clusters, flag for
19
+ human sign-off rather than auto-shipping. Report the top opportunities with scores.
20
+ ```
21
+
22
+ ## A9 — Content Refresh (weekly)
23
+ ```
24
+ You are an SEO refresh agent for LeadLyze. Read .planning/seo-factory/gsc-deltas.csv (pages
25
+ whose position fell over the last 28 days; pull via browser-harness/GSC if the file is stale).
26
+
27
+ For each decaying page:
28
+ 1. Diff the page against the CURRENT top-3 Google results (serp-analysis).
29
+ 2. Update stale statistics (re-cite), add newly-relevant competitors/examples, add fresh
30
+ internal links, and bump dateModified in the frontmatter.
31
+ 3. Re-run the indexability gate (quality-gates.md Gate 4). Record the diff (what changed +
32
+ why) to .planning/seo-factory/AUDIT-refresh.md.
33
+ Do NOT rewrite pages wholesale — incremental refresh only. Commit each page separately.
34
+ ```
@@ -0,0 +1,39 @@
1
+ ---
2
+ # A5 output frontmatter — keep keys stable; the MDX loader + schema (A8) read these.
3
+ title: "The Best Apollo Alternative in 2026: LeadLyze vs Apollo"
4
+ description: "Looking for an Apollo alternative? See how LeadLyze beats Apollo on price, deliverability, and AI outreach."
5
+ slug: apollo-alternative
6
+ cluster_id: alt-apollo
7
+ type: alternatives # blog | alternatives | comparisons → maps to src/content/<type>/
8
+ keyword: apollo alternative
9
+ intent: commercial
10
+ published: 2026-06-14
11
+ dateModified: 2026-06-14
12
+ schema: [SoftwareApplication, FAQPage, BreadcrumbList]
13
+ internalLinks:
14
+ - { to: instantly-alternative, anchor: "compared to Instantly" }
15
+ - { to: ai-cold-calling, anchor: "AI cold calling" }
16
+ - { to: pricing, anchor: "LeadLyze pricing" }
17
+ faq:
18
+ - q: "Is there a free Apollo alternative?"
19
+ a: "Yes — LeadLyze offers a free tier that includes…"
20
+ - q: "Can I import my Apollo data into LeadLyze?"
21
+ a: "Yes, via CSV or the migration importer…"
22
+ ---
23
+
24
+ {/* Body: written STRICTLY to briefs/apollo-alternative.md. Obeys quality-gates.md Gate 2.
25
+ No "in today's fast-paced world". Real table. Cited stats. Inline internal links. */}
26
+
27
+ Sales teams switch off Apollo for three concrete reasons: per-credit pricing that scales
28
+ badly, [deliverability complaints](/blog/cold-email-deliverability), and no native dialer.
29
+ Here's how LeadLyze handles each.
30
+
31
+ ## LeadLyze vs Apollo — side by side
32
+
33
+ | Capability | Apollo | LeadLyze |
34
+ |---|---|---|
35
+ | AI cold calling | ❌ | ✅ |
36
+ | Email + LinkedIn sequences | ✅ | ✅ |
37
+ | Per-credit pricing | Yes | Flat seats |
38
+
39
+ <!-- … rest of body per brief outline … -->
@@ -0,0 +1,52 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "clusters.json — A3 output",
4
+ "type": "object",
5
+ "required": ["hubs"],
6
+ "properties": {
7
+ "hubs": {
8
+ "type": "array",
9
+ "items": {
10
+ "type": "object",
11
+ "required": ["id", "title", "hub_page", "spokes", "page_kind"],
12
+ "properties": {
13
+ "id": { "type": "string" },
14
+ "title": { "type": "string" },
15
+ "hub_page": {
16
+ "type": "object",
17
+ "required": ["slug", "type", "keyword"],
18
+ "properties": {
19
+ "slug": { "type": "string" },
20
+ "type": { "enum": ["money", "supporting", "blog"] },
21
+ "keyword": { "type": "string" }
22
+ }
23
+ },
24
+ "page_kind": { "enum": ["programmatic", "editorial"] },
25
+ "dimensions": {
26
+ "type": "object",
27
+ "description": "Required when page_kind=programmatic",
28
+ "properties": {
29
+ "service": { "type": "string" },
30
+ "vary_by": { "type": "string", "description": "registry file e.g. industries.ts" }
31
+ }
32
+ },
33
+ "spokes": {
34
+ "type": "array",
35
+ "items": {
36
+ "type": "object",
37
+ "required": ["slug", "type", "keyword", "page_kind", "min_words", "cluster_id"],
38
+ "properties": {
39
+ "slug": { "type": "string" },
40
+ "type": { "enum": ["money", "supporting", "blog"] },
41
+ "keyword": { "type": "string" },
42
+ "page_kind": { "enum": ["programmatic", "editorial"] },
43
+ "min_words": { "type": "integer", "minimum": 600 },
44
+ "cluster_id": { "type": "string" }
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
@@ -0,0 +1,51 @@
1
+ ---
2
+ # A4 output — the brief-before-prose GATE artifact.
3
+ # A5 Writer REFUSES to run unless this file exists and status: approved.
4
+ slug: apollo-alternative
5
+ cluster_id: alt-apollo
6
+ type: money # money | supporting | blog
7
+ keyword: apollo alternative
8
+ secondary_keywords: [apollo io alternative, apollo competitor, cheaper than apollo]
9
+ intent: commercial # informational | commercial | transactional | navigational
10
+ funnel: buy # learn | compare | buy
11
+ min_words: 1600
12
+ schema: [SoftwareApplication, FAQPage, BreadcrumbList]
13
+ status: approved # draft | approved
14
+ ---
15
+
16
+ # Title (≤60 chars, keyword-leading)
17
+ The Best Apollo Alternative in 2026: LeadLyze vs Apollo
18
+
19
+ # Meta description (≤155 chars)
20
+ Looking for an Apollo alternative? See how LeadLyze beats Apollo on price, deliverability, and AI outreach — with a side-by-side breakdown.
21
+
22
+ # Search intent (one paragraph from the live top-5 SERP)
23
+ Buyers comparing tools; want a concrete feature+price comparison and a reason to switch, not a generic listicle. Top-5 are all comparison pages with tables.
24
+
25
+ # Outline (mirror the winning SERP structure + 1 unique angle)
26
+ ## H2: Why teams look for an Apollo alternative
27
+ ### H3: Pricing pain points
28
+ ### H3: Deliverability / data accuracy complaints
29
+ ## H2: LeadLyze vs Apollo — side by side ← REQUIRED data table
30
+ ## H2: Feature-by-feature breakdown
31
+ ### H3: AI cold calling (LeadLyze unique angle — Apollo lacks this)
32
+ ## H2: Pricing comparison ← REQUIRED table
33
+ ## H2: When Apollo is still the better choice (honesty builds trust)
34
+ ## H2: How to migrate from Apollo to LeadLyze
35
+
36
+ # Entities to cover (from top-5 + gap analysis)
37
+ email deliverability, data enrichment, sequences, CRM sync, credits model, AI dialer, GDPR
38
+
39
+ # FAQ (from People-Also-Ask — becomes FAQPage schema)
40
+ - Is there a free Apollo alternative?
41
+ - Is LeadLyze cheaper than Apollo?
42
+ - Can I import my Apollo data into LeadLyze?
43
+ - Which has better email deliverability?
44
+
45
+ # Internal links (inject inline, not at the bottom)
46
+ - → /instantly-alternative (anchor: "compared to Instantly")
47
+ - → /ai-cold-calling (anchor: "AI cold calling")
48
+ - → /pricing (anchor: "LeadLyze pricing")
49
+
50
+ # CTA (funnel: buy)
51
+ "Start free — migrate your Apollo lists in minutes." → /signup
@@ -0,0 +1,49 @@
1
+ // A8 — extend the EXISTING src/lib/jsonld.ts with these typed builders.
2
+ // Render via a <JsonLd data={...} /> component, never hand-written <script> strings.
3
+ // Do not duplicate if equivalents already exist in src/lib/jsonld.ts — extend, don't fork.
4
+
5
+ export function softwareApplication() {
6
+ return {
7
+ '@context': 'https://schema.org',
8
+ '@type': 'SoftwareApplication',
9
+ name: 'LeadLyze',
10
+ applicationCategory: 'BusinessApplication',
11
+ operatingSystem: 'Web',
12
+ offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },
13
+ aggregateRating: { '@type': 'AggregateRating', ratingValue: '4.8', reviewCount: '120' },
14
+ }
15
+ }
16
+
17
+ export function faqPage(faqs: { q: string; a: string }[]) {
18
+ return {
19
+ '@context': 'https://schema.org',
20
+ '@type': 'FAQPage',
21
+ mainEntity: faqs.map((f) => ({
22
+ '@type': 'Question',
23
+ name: f.q,
24
+ acceptedAnswer: { '@type': 'Answer', text: f.a },
25
+ })),
26
+ }
27
+ }
28
+
29
+ export function breadcrumbList(items: { name: string; url: string }[]) {
30
+ return {
31
+ '@context': 'https://schema.org',
32
+ '@type': 'BreadcrumbList',
33
+ itemListElement: items.map((it, i) => ({
34
+ '@type': 'ListItem',
35
+ position: i + 1,
36
+ name: it.name,
37
+ item: `https://leadlyze.com${it.url}`,
38
+ })),
39
+ }
40
+ }
41
+
42
+ export function product(name: string, rating = '4.8', reviews = '120') {
43
+ return {
44
+ '@context': 'https://schema.org',
45
+ '@type': 'Product',
46
+ name,
47
+ aggregateRating: { '@type': 'AggregateRating', ratingValue: rating, reviewCount: reviews },
48
+ }
49
+ }
@@ -0,0 +1,13 @@
1
+ keyword,parent_seed,modifier_type,volume,kd,intent,funnel,cluster_id
2
+ lead generation for dentists,lead generation software,industry,720,34,commercial,buy,ind-dentists
3
+ lead generation for roofers,lead generation software,industry,590,29,commercial,buy,ind-roofers
4
+ lead generation for lawyers,lead generation software,industry,880,41,commercial,buy,ind-lawyers
5
+ lead generation dubai,lead generation software,location,480,22,commercial,buy,loc-dubai
6
+ lead generation london,lead generation software,location,1300,38,commercial,buy,loc-london
7
+ apollo alternative,lead generation software,alternative,2900,61,commercial,buy,alt-apollo
8
+ instantly alternative,cold email,alternative,1600,48,commercial,buy,alt-instantly
9
+ apollo vs leadlyze,lead generation software,comparison,90,12,commercial,compare,cmp-apollo
10
+ cold email templates,cold email,template,5400,52,informational,learn,tpl-coldemail
11
+ cold email open rate statistics,cold email,statistics,1300,18,informational,learn,stat-coldemail
12
+ how to generate leads for saas,lead generation software,question,210,27,informational,learn,q-saas
13
+ free lead generation tool,lead generation software,tool,1900,55,transactional,buy,tool-leadgen