seo 0.13.3 → 0.14.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 (88) hide show
  1. package/PRIVACY.md +9 -1
  2. package/dist/cli.js +84 -80
  3. package/dist/cli.js.map +1 -1
  4. package/dist/{dist-BbTqJIE_.js → dist-4Yam8ps7.js} +1 -1
  5. package/dist/dist-B_2zww72.js +427 -0
  6. package/dist/dist-B_2zww72.js.map +1 -0
  7. package/dist/{esm-hHlvm1W0.js → esm-BmuxgZyN.js} +95 -188
  8. package/dist/{esm-hHlvm1W0.js.map → esm-BmuxgZyN.js.map} +1 -1
  9. package/dist/index.d.ts +73 -406
  10. package/dist/index.js +1448 -564
  11. package/dist/index.js.map +1 -1
  12. package/dist/mcp.d.ts +0 -14
  13. package/dist/mcp.js +1020 -807
  14. package/dist/mcp.js.map +1 -1
  15. package/dist/provider-sdk.d.ts +0 -2
  16. package/dist/provider-sdk.js +1 -2
  17. package/package.json +6 -5
  18. package/site-kit/README.md +13 -0
  19. package/site-kit/guide/build.md +70 -0
  20. package/site-kit/guide/data.md +49 -0
  21. package/site-kit/guide/golden-page.md +50 -0
  22. package/site-kit/guide/grow.md +58 -0
  23. package/site-kit/guide/launch.md +55 -0
  24. package/site-kit/guide/market.md +57 -0
  25. package/site-kit/guide/plan.md +49 -0
  26. package/site-kit/guide/scale.md +41 -0
  27. package/site-kit/guide/setup.md +59 -0
  28. package/site-kit/guide/writing.md +55 -0
  29. package/site-kit/starter/.github/workflows/refresh-data.yml +88 -0
  30. package/site-kit/starter/.node-version +1 -0
  31. package/site-kit/starter/AGENTS.md +65 -0
  32. package/site-kit/starter/README.md +11 -0
  33. package/site-kit/starter/astro.config.mjs +31 -0
  34. package/site-kit/starter/gitignore +7 -0
  35. package/site-kit/starter/llms.config.mjs +38 -0
  36. package/site-kit/starter/package.json +31 -0
  37. package/site-kit/starter/pnpm-workspace.yaml +5 -0
  38. package/site-kit/starter/public/_headers +5 -0
  39. package/site-kit/starter/public/favicon.svg +1 -0
  40. package/site-kit/starter/public/fonts/InterLatinVF.woff2 +0 -0
  41. package/site-kit/starter/public/fonts/JetBrainsMonoLatinVF.woff2 +0 -0
  42. package/site-kit/starter/public/fonts/LICENSE-inter.txt +93 -0
  43. package/site-kit/starter/public/fonts/LICENSE-jetbrains-mono.txt +93 -0
  44. package/site-kit/starter/scripts/deploy.mjs +60 -0
  45. package/site-kit/starter/scripts/markdown-rewrites.mjs +33 -0
  46. package/site-kit/starter/scripts/refresh-data.mjs +60 -0
  47. package/site-kit/starter/scripts/validate-data.mjs +47 -0
  48. package/site-kit/starter/site.config.json +9 -0
  49. package/site-kit/starter/src/components/Breadcrumbs.astro +27 -0
  50. package/site-kit/starter/src/components/Button.astro +46 -0
  51. package/site-kit/starter/src/components/Card.astro +54 -0
  52. package/site-kit/starter/src/components/CodeBlock.astro +62 -0
  53. package/site-kit/starter/src/components/FactTable.astro +45 -0
  54. package/site-kit/starter/src/components/FaqAccordion.astro +143 -0
  55. package/site-kit/starter/src/components/Footer.astro +34 -0
  56. package/site-kit/starter/src/components/FormInput.astro +18 -0
  57. package/site-kit/starter/src/components/FormSelect.astro +34 -0
  58. package/site-kit/starter/src/components/Header.astro +17 -0
  59. package/site-kit/starter/src/components/HugeIcon.astro +36 -0
  60. package/site-kit/starter/src/components/Logo.astro +21 -0
  61. package/site-kit/starter/src/components/PageHeader.astro +33 -0
  62. package/site-kit/starter/src/components/SectionHeading.astro +18 -0
  63. package/site-kit/starter/src/components/ui/button.ts +51 -0
  64. package/site-kit/starter/src/data/parks.json +106 -0
  65. package/site-kit/starter/src/data/sources.json +11 -0
  66. package/site-kit/starter/src/integrations/og-images.ts +49 -0
  67. package/site-kit/starter/src/integrations/sitemaps.ts +104 -0
  68. package/site-kit/starter/src/layouts/Base.astro +69 -0
  69. package/site-kit/starter/src/lib/cn.ts +5 -0
  70. package/site-kit/starter/src/lib/narrative.ts +115 -0
  71. package/site-kit/starter/src/lib/og/card.ts +85 -0
  72. package/site-kit/starter/src/lib/og/path.ts +14 -0
  73. package/site-kit/starter/src/lib/og/render.ts +30 -0
  74. package/site-kit/starter/src/lib/parks.ts +84 -0
  75. package/site-kit/starter/src/lib/seo.ts +97 -0
  76. package/site-kit/starter/src/pages/404.astro +30 -0
  77. package/site-kit/starter/src/pages/about.astro +39 -0
  78. package/site-kit/starter/src/pages/index.astro +52 -0
  79. package/site-kit/starter/src/pages/parks/[slug].astro +95 -0
  80. package/site-kit/starter/src/pages/regions/[region].astro +58 -0
  81. package/site-kit/starter/src/pages/robots.txt.ts +16 -0
  82. package/site-kit/starter/src/site.ts +29 -0
  83. package/site-kit/starter/src/styles/globals.css +561 -0
  84. package/site-kit/starter/tsconfig.json +5 -0
  85. package/site-kit/starter/wrangler.jsonc +16 -0
  86. package/skills/seo/SKILL.md +19 -1
  87. package/dist/dist-DBI-BioS.js +0 -420
  88. package/dist/dist-DBI-BioS.js.map +0 -1
@@ -1,5 +1,4 @@
1
1
 
2
- //#region packages/core/src/provider-extensions/sdk.d.ts
3
2
  export declare const SEO_PROVIDER_API_VERSION: 1;
4
3
  export type SeoProviderApiVersion = typeof SEO_PROVIDER_API_VERSION;
5
4
  export type SeoProviderKind = 'traffic-analytics' | 'search-results' | 'keyword-data' | 'domain-data' | 'link-data' | 'local-search' | 'ai-data' | 'other';
@@ -199,5 +198,4 @@ export interface SeoProviderHost {
199
198
  export type SeoProviderActivate = (host: SeoProviderHost) => void | Promise<void>;
200
199
  export type SeoAnalyticsConnection = SeoProviderConnection;
201
200
  export type SeoAnalyticsLandingPageResult = SeoLandingPageVisitsResult;
202
- //#endregion
203
201
  //# sourceMappingURL=provider-sdk.d.ts.map
@@ -1,7 +1,6 @@
1
1
  import { createRequire as __seoCreateRequire } from 'node:module'; const require = __seoCreateRequire(import.meta.url);
2
- //#region packages/core/src/provider-extensions/sdk.ts
2
+ // packages/core/src/provider-extensions/sdk.ts
3
3
  const SEO_PROVIDER_API_VERSION = 1;
4
- //#endregion
5
4
  export { SEO_PROVIDER_API_VERSION };
6
5
 
7
6
  //# sourceMappingURL=provider-sdk.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "seo",
3
- "version": "0.13.3",
3
+ "version": "0.14.0",
4
4
  "mcpName": "dev.seoskill/seo",
5
5
  "description": "The SEO command for AI agents: a free Google Search Console MCP server and CLI. Reads your real Search Console, Google Analytics and Bing data for traffic drops, quick wins, content decay, cannibalization and indexing, plus DataForSEO and Ahrefs keyword research.",
6
6
  "type": "module",
@@ -57,6 +57,7 @@
57
57
  "files": [
58
58
  "dist",
59
59
  "skills",
60
+ "site-kit",
60
61
  "evals",
61
62
  "PRIVACY.md",
62
63
  "SECURITY.md",
@@ -117,7 +118,7 @@
117
118
  "jsonc-parser": "^3.3.1",
118
119
  "libsql": "^0.5.29",
119
120
  "lighthouse": "13.5.0",
120
- "linkedom": "^0.18.13",
121
+ "linkedom": "^0.18.14",
121
122
  "open": "^11.0.4",
122
123
  "p-queue": "^9.3.5",
123
124
  "p-retry": "^8.0.1",
@@ -134,10 +135,10 @@
134
135
  "zod": "^4.6.7"
135
136
  },
136
137
  "devDependencies": {
137
- "@biomejs/biome": "^2.5.15",
138
+ "@biomejs/biome": "^2.6.2",
138
139
  "@modelcontextprotocol/sdk": "^1.32.1",
139
- "tsdown": "^0.23.1",
140
- "turbo": "^2.11.8",
140
+ "tsdown": "^0.23.2",
141
+ "turbo": "^2.11.10",
141
142
  "typescript": "^6.0.3"
142
143
  }
143
144
  }
@@ -0,0 +1,13 @@
1
+ # Site kit
2
+
3
+ The files behind `seo site`. They ship in the npm package.
4
+
5
+ - `starter/` is the Astro site on Cloudflare that `seo site new <folder>`
6
+ copies. `gitignore` becomes `.gitignore` in the copy, because npm drops
7
+ `.gitignore` files from packages.
8
+ - `guide/` holds one Markdown file per step that `seo site guide <step>`
9
+ prints. The list and order of steps is `SITE_GUIDE_STEPS` in
10
+ `packages/cli/src/commands/site.ts`.
11
+
12
+ `seo site check` lives in `packages/core/src/site-check`. Change the starter
13
+ and the check together: the starter's own build must pass the check.
@@ -0,0 +1,70 @@
1
+ # Step 5 of 10: build
2
+
3
+ Goal: the site runs from the starter, deploys to a private preview on
4
+ Cloudflare and passes `seo site check`.
5
+
6
+ ## Start the site
7
+
8
+ If the project does not exist yet, create it in a new folder:
9
+
10
+ ```sh
11
+ seo site new <folder> --name "<Site name>" --domain <domain>
12
+ cd <folder>
13
+ pnpm build
14
+ ```
15
+
16
+ The starter is a static Astro site on Cloudflare Workers static assets. It
17
+ already does the parts every page needs:
18
+
19
+ - One layout (`src/layouts/Base.astro`) writes the title, description,
20
+ canonical, sharing tags and one JSON-LD graph per page.
21
+ - A Markdown copy of every page, `llms.txt` and `agent-routes.json`, from
22
+ `agentMarkdown()`.
23
+ - A sharing image for every page, drawn at build time from its H1.
24
+ - A sitemap index with files of up to 5,000 URLs, listed in `robots.txt`.
25
+ - `robots.txt` open to every crawler, with a Content-Signal line. Set
26
+ `aiTraining` in `site.config.json` to the person's choice.
27
+ - `pnpm build` ends with `seo site check`, so a broken build never ships.
28
+
29
+ ## Use the components
30
+
31
+ The starter has a clean blank theme for the person to make their own.
32
+ `AGENTS.md` lists the components: header, footer, page header,
33
+ breadcrumbs, section heading, cards with a destination label, fact table,
34
+ FAQ accordion, buttons, form inputs, code block and `site-prose` text.
35
+ Build every page from them. Make a new component only for something none
36
+ of them shows, in the same style: token classes from
37
+ `src/styles/globals.css`, muted panels, no borders, shadows or raw
38
+ colours. Change the look by changing the tokens, never page by page.
39
+
40
+ ## Deploy a private preview
41
+
42
+ 1. Create a GitHub repository and push: `gh repo create --private --source
43
+ . --push`.
44
+ 2. In the Cloudflare dashboard, open Workers & Pages, create an
45
+ application, import the repository and keep the build command
46
+ `pnpm build`. Set the deploy command to `pnpm run deploy`.
47
+ 3. Until launch the site lives on its workers.dev address. Protect it with
48
+ Cloudflare Access (in the Worker's settings, under Domains & Routes,
49
+ turn on Cloudflare Access for workers.dev) so only the person can open
50
+ it. Never use noindex for this: it is too easy to forget.
51
+ 4. Send the person the preview link and a screenshot of the home page on
52
+ desktop and phone.
53
+
54
+ ## Rules
55
+
56
+ - Static first. Run code on the server only for a route that needs it,
57
+ such as a search box over a large dataset, and keep it under `/api/*`.
58
+ Never set `run_worker_first` for anything else.
59
+ - Every word of content and the H1 is in the built HTML. Most AI systems
60
+ do not run JavaScript.
61
+ - One URL form everywhere: no trailing slash, and canonicals drop query
62
+ strings.
63
+ - Missing pages return a real 404. Never redirect them to the home page.
64
+ - Keep the data in committed JSON or R2. Never query a database on a page
65
+ request.
66
+
67
+ Done when: the preview is live behind Cloudflare Access, `pnpm build`
68
+ passes and the person has seen the screenshots.
69
+
70
+ Next: `seo site guide golden-page`
@@ -0,0 +1,49 @@
1
+ # Step 3 of 10: data
2
+
3
+ Goal: a clean dataset that is hard to copy, with a source and a checked
4
+ date for every fact, rebuilt from scratch by one command.
5
+
6
+ The data is what makes the site worth visiting. A site built on one copied
7
+ dataset gets no traction. Data that is combined, cleaned and worked out
8
+ into something new does.
9
+
10
+ ## What the agent does
11
+
12
+ 1. Find sources in this order: government and open data, then public pages
13
+ that can be collected, then data people add themselves. Check each
14
+ source's licence and terms before using it.
15
+ 2. Write the import as a script that gives the same result every run, such
16
+ as `scripts/build-data.mjs`, from raw files in `data/raw` to JSON in
17
+ `src/data`. It reports any name it cannot match instead of guessing.
18
+ 3. Join and enrich the sources: clean names, units and plurals, add places
19
+ and work out comparisons or a score. Formatting is a quality signal, so
20
+ "LLC" never becomes "Llc".
21
+ 4. List every source in `src/data/sources.json` with its URL and the date
22
+ it was checked. `pnpm data:refresh` records each source's ETag, date and
23
+ hash, so a change opens a pull request.
24
+ 5. Add a rule to `scripts/validate-data.mjs` for each kind of mistake the
25
+ data can contain, and run `pnpm data:validate`.
26
+ 6. Replace the example parks data and the parks pages as the plan says.
27
+
28
+ ## What the person does
29
+
30
+ - Decide how often the data is refreshed. Ask how often it changes at the
31
+ source before anything is built: daily for tides, yearly for statistics.
32
+ Set the cron in `.github/workflows/refresh-data.yml` to match.
33
+ - Spot-check 20 rows like an expert in the subject.
34
+
35
+ ## Rules
36
+
37
+ - Keep an unknown value unknown. Never guess opening hours, rules or
38
+ prices. Store facts and work totals out from them.
39
+ - Never use a competitor as the source.
40
+ - Money and health numbers change only through a pull request a person
41
+ reviews. The refresh workflow does this for you.
42
+ - A score or index the site owns, explained on a methodology page, makes
43
+ pages worth linking to.
44
+
45
+ Done when: the dataset builds from nothing with one command, every fact
46
+ has a source and a checked date, `pnpm data:validate` passes and the
47
+ refresh workflow is scheduled.
48
+
49
+ Next: `seo site guide plan`
@@ -0,0 +1,50 @@
1
+ # Step 6 of 10: golden page
2
+
3
+ Goal: one page that is the best answer on the web for its search, built
4
+ from real data before any template exists.
5
+
6
+ ## What the agent does
7
+
8
+ 1. Build the first page of the main page type with real data, in the page
9
+ template the plan names. The starter's park page
10
+ (`src/pages/parks/[slug].astro`) shows the shape.
11
+ 2. Take screenshots on desktop, at phone width and in dark mode. Review
12
+ them against the rules below before the person sees them.
13
+ 3. Show the person the screenshots and the preview link, then change the
14
+ page from their feedback until they approve it.
15
+
16
+ ## What the person does
17
+
18
+ Judge the page as a user, not as a builder. Do I know what this is at a
19
+ glance? Does it answer my question? Is every part there for a reason?
20
+ Would I send it to a friend who asked?
21
+
22
+ ## How a good page is laid out
23
+
24
+ - A clear H1 and a short answer at the top that makes sense on its own.
25
+ Never "see below".
26
+ - The tool or the main data next, then a well designed table of the
27
+ details.
28
+ - A fact block for each set of facts, with the source and the checked date
29
+ (`src/components/FactTable.astro`).
30
+ - Questions people really ask, answered on the page. The FAQ markup
31
+ repeats them word for word, which `seo site check` tests.
32
+ - Links to related pages in the body, with words that name the page they
33
+ lead to. One link per target per page, never in the H1.
34
+ - Assumptions and caveats at the bottom, in plain words.
35
+
36
+ Charts, maps and calculators earn their place when they help. Every chart
37
+ also has its data in a table and a sentence that says what it shows.
38
+
39
+ ## Design rules
40
+
41
+ Simple and quiet. The system font or Inter, plenty of space, one link
42
+ colour. `seo site check` fails the build on uppercase or letter-spaced
43
+ labels, gradients, shadows, coloured left borders and card grids wider
44
+ than two columns. Also avoid stat boxes, eyebrow labels above headings and
45
+ slogans made of three short phrases. Attention to detail is what
46
+ separates a good page: capitals, units, plurals and empty states.
47
+
48
+ Done when: the person approves the page and `pnpm build` passes.
49
+
50
+ Next: `seo site guide writing`
@@ -0,0 +1,58 @@
1
+ # Step 10 of 10: grow
2
+
3
+ Goal: know what is working from the site's own data, improve one thing at
4
+ a time, and keep the data current with minutes of the person's time a
5
+ week.
6
+
7
+ ## Measure every week
8
+
9
+ Search Console data starts a few days after launch. Run the report each
10
+ week and treat each section as a list to review, never a forecast:
11
+
12
+ ```sh
13
+ seo report --site <domain>
14
+ seo report --site <domain> --section quick-wins
15
+ seo report --site <domain> --section striking-distance
16
+ seo report --site <domain> --section ai-queries
17
+ seo index --site <domain>
18
+ ```
19
+
20
+ - Quick wins and low CTR: pages near the top with fewer clicks than their
21
+ position should get. Review the title and description.
22
+ - Striking distance and second page: pages close to page one. Improve the
23
+ section that answers the search.
24
+ - AI queries: long questions people ask, which may need a section or an
25
+ FAQ answer.
26
+ - Content decay and traffic drop: what lost clicks, and the Google updates
27
+ around that date.
28
+ - `seo index`: why Google left pages out of its index.
29
+
30
+ Use `seo page --url <url>` for one page's searches and status. Your own
31
+ Search Console data is the only data that is about your site. Keyword
32
+ tools are estimates.
33
+
34
+ ## Change one thing at a time
35
+
36
+ Note the date and what changed. Compare equal windows four and eight weeks
37
+ later with `seo compare --site <domain> --date <date>`. A change in the
38
+ same week as a Google update proves nothing on its own.
39
+
40
+ ## Keep the data current
41
+
42
+ - The refresh workflow opens a pull request when a source changes. The
43
+ person checks the numbers and merges it.
44
+ - When a refresh fails, find out why and fix the import, then let the next
45
+ run open the pull request.
46
+
47
+ ## Become known
48
+
49
+ Keep the name and description the same on the site, in its JSON-LD and on
50
+ every profile. Publish the site's own data and statistics, because those
51
+ are what people link to and AI answers cite. Never buy links or post fake
52
+ mentions.
53
+
54
+ At six months, a steady few hundred visits a day means keep going. Much
55
+ less means rebuild it smaller and better, or try the next idea.
56
+
57
+ Done when: the weekly report runs, and each item has an action or a clear
58
+ "no action".
@@ -0,0 +1,55 @@
1
+ # Step 9 of 10: launch
2
+
3
+ Goal: the site is live on its domain, Google and Bing know about it, and
4
+ the most important pages are found quickly.
5
+
6
+ ## What the agent does
7
+
8
+ 1. Add the domain to `wrangler.jsonc` and push:
9
+
10
+ ```jsonc
11
+ "routes": [{ "pattern": "<domain>", "custom_domain": true }]
12
+ ```
13
+
14
+ Redirect `www` to the bare domain with a Cloudflare redirect rule.
15
+ Take Cloudflare Access off the live domain.
16
+ 2. Add the two Markdown rewrite rules, so an agent that asks for
17
+ `Accept: text/markdown` at a normal URL gets the Markdown copy. Print
18
+ them with `pnpm rewrites` and add them in the Cloudflare dashboard under
19
+ Rules, URL rewrite. They run before the site, so no code runs per
20
+ request.
21
+ 3. Check production: the home page, a page of each type, `robots.txt`,
22
+ `sitemap.xml`, `llms.txt`, a sharing image, a 404 and a Markdown
23
+ request:
24
+
25
+ ```sh
26
+ seo crawl --url https://<domain>
27
+ curl -sI -H "Accept: text/markdown" https://<domain>/
28
+ ```
29
+
30
+ 4. From now on `pnpm run deploy` (the Cloudflare deploy command) sends the
31
+ pages that changed to IndexNow after each deploy.
32
+ 5. Pick the 100 most important URLs: hubs, the pages with the most data
33
+ and the pages that link to everything else. Check each one is built,
34
+ canonical and in a sitemap.
35
+
36
+ ## What the person does
37
+
38
+ 1. Add the domain to Google Search Console as a Domain property and
39
+ verify it through Cloudflare. Submit `https://<domain>/sitemap.xml`.
40
+ 2. Import the site into Bing Webmaster Tools from Search Console.
41
+ 3. Add Clicky, on the production domain only.
42
+ 4. Run `seo start` again if the new property should show up in SEO Skill.
43
+
44
+ ## Rules
45
+
46
+ - Publish every page at once. A site built for people does not drip feed
47
+ pages.
48
+ - Found is not indexed. Expect impressions within days if the site is
49
+ good, and judge it at six months.
50
+ - Never change a live URL without a 301 to the closest page.
51
+
52
+ Done when: the domain serves the site, Search Console and Bing have the
53
+ sitemap, and `seo crawl` reports no errors.
54
+
55
+ Next: `seo site guide grow`
@@ -0,0 +1,57 @@
1
+ # Step 2 of 10: market
2
+
3
+ Goal: a niche with real search demand and data the site can own, where the
4
+ pages that rank today are weak. The step ends with a plan file and a go or
5
+ no-go from the person.
6
+
7
+ ## What the agent does
8
+
9
+ 1. Ask the person for the idea, in their words. Good ideas come from their
10
+ own life and hobbies, open data, forums, and sites that look weak.
11
+ 2. Find the head term and its modifiers. Searches usually take the shape
12
+ head term plus modifier, such as "{club} {season} home shirt".
13
+ 3. Read the live search results for each pattern: who ranks, what kind of
14
+ page wins (tool, list, directory item, guide) and how strong those sites
15
+ look.
16
+ 4. With a keyword data key, get the numbers:
17
+
18
+ ```sh
19
+ seo research keyword_metrics --keywords "<term>,<term>"
20
+ seo research serp --keywords "<head term>"
21
+ seo research competitors --target <a competitor domain>
22
+ seo research ranked_keywords --target <a competitor domain>
23
+ ```
24
+
25
+ Then look at the competitors of those competitors for pockets of
26
+ demand. Without a key, use the search results, autocomplete and "people
27
+ also ask", and say that the volumes are unknown.
28
+ 5. Write `plan.md` in the project with the head terms, the modifiers, who
29
+ ranks, the data sources, how often the data changes, the page types and
30
+ a page count estimate.
31
+
32
+ ## What the person does
33
+
34
+ Read `plan.md` and say go or no-go. Their judgement of the market matters
35
+ more than any number.
36
+
37
+ ## Signs a market is winnable
38
+
39
+ - Forum threads, thin directories or old pages in the top results.
40
+ - Sites with few links and low authority ranking on page one.
41
+ - Searches with buyers behind them. 100 searches from people about to buy
42
+ beat 4,400 from people who want something free. A real cost per click
43
+ shows the market pays.
44
+
45
+ ## Walk away when
46
+
47
+ - The data is too hard to get, too hard to keep current or too costly to
48
+ host.
49
+ - Every result is a household brand with years of links.
50
+ - The only pages you could make are thin rewrites of one source.
51
+
52
+ Build five ideas to find one that works. A quiet, boring market is fine.
53
+
54
+ Done when: `plan.md` names the head terms, the page types, the data
55
+ sources and a page count, and the person said go.
56
+
57
+ Next: `seo site guide data`
@@ -0,0 +1,49 @@
1
+ # Step 4 of 10: plan
2
+
3
+ Goal: a page list where every page has real demand and one clear job, and
4
+ the domain to put it on.
5
+
6
+ ## What the agent does
7
+
8
+ 1. Map each search pattern to a page type and a URL pattern.
9
+ 2. Check the demand for each page type before building it. With a keyword
10
+ data key, run `seo research keyword_metrics` on a sample of each
11
+ pattern. Without one, check that the search results show pages of that
12
+ type.
13
+ 3. Group searches that share the same top results into one page, so pages
14
+ never compete with each other.
15
+ 4. When the data allows two sizes, propose both (for example about 700
16
+ pages or about 9,000) and let the person choose by risk.
17
+ 5. Add a route list to `plan.md`: page type, URL pattern, target search
18
+ pattern and expected count.
19
+ 6. Suggest three domains: two words, no hyphens, about the subject. Check
20
+ they are free on Cloudflare Registrar.
21
+
22
+ ## What the person does
23
+
24
+ Approve the page list and the URL pattern, then buy the domain on
25
+ Cloudflare Registrar. Then put the domain in `site.config.json`.
26
+
27
+ ## Rules
28
+
29
+ - Use the smallest page type that fully answers the search: a tool, a
30
+ landing page, then a guide.
31
+ - Every search intent gets one URL. Never make a second page for the same
32
+ job.
33
+ - Small and focused wins: hundreds of rich pages, never tens of thousands
34
+ of thin ones. Directories are the exception, because people search for
35
+ each item by name.
36
+ - Long variants of a search become sections on one strong page. They do
37
+ not get thin pages of their own.
38
+ - Never make one page per question or per wording of a search. Google
39
+ treats that as scaled content abuse.
40
+ - Build a page only when the data has enough to make it useful. A URL that
41
+ does not qualify is never built.
42
+ - URLs are lowercase and lead with the subject, one or two folders deep,
43
+ with no IDs, no source names and no trailing slash.
44
+ - Hub pages are real pages with their own data, not lists of 500 links.
45
+
46
+ Done when: `plan.md` has the route list, the person approved it, and the
47
+ domain is bought and set in `site.config.json`.
48
+
49
+ Next: `seo site guide build`
@@ -0,0 +1,41 @@
1
+ # Step 8 of 10: scale
2
+
3
+ Goal: every page as good as the golden page.
4
+
5
+ ## What the agent does
6
+
7
+ 1. Turn the golden page into the template for its page type. Each block
8
+ shows only when the data has enough for it.
9
+ 2. Build every page, then screenshot a sample of each page type: the
10
+ pages with the most data, the least data and the strangest data.
11
+ 3. Review the sample with a second agent that did not build it.
12
+ 4. Link the pages in the build: hubs to their pages, pages to their
13
+ siblings, and every page within three clicks of the home page.
14
+ `seo site check` fails on pages nothing links to.
15
+ 5. Update `llms.config.mjs` so `llms.txt` lists the hubs and page types.
16
+
17
+ ## What the person does
18
+
19
+ Review the sample from every page type, most of all the pages with the
20
+ least data. A thin page gets better data, gets merged into a stronger page
21
+ or is not built.
22
+
23
+ ## Rules
24
+
25
+ - Fix a problem in the template or the data, never page by page. Fixing
26
+ pages one at a time hides the real fault.
27
+ - Reuse the starter's components. Do not invent a new one for each page
28
+ type.
29
+ - Rigid templates with thin data make bad pages. Leave a block out rather
30
+ than fill it with filler.
31
+ - `seo site check` checks every page before deploy: titles and
32
+ descriptions present, unique and the right length, one H1, canonicals,
33
+ JSON-LD, FAQ markup that matches the page, links that work, every page in
34
+ a sitemap, no noindex, a sharing image and a Markdown copy for each page,
35
+ the copy and design rules, and a source and date on every fact block.
36
+ It stops at 10,000 pages.
37
+
38
+ Done when: a random sample of pages passes the person's review and
39
+ `pnpm build` passes.
40
+
41
+ Next: `seo site guide launch`
@@ -0,0 +1,59 @@
1
+ # Step 1 of 10: setup
2
+
3
+ Goal: the person has every account the site needs, signed in on this
4
+ machine, and knows what each one costs.
5
+
6
+ Work through this with the person one account at a time. For each one, say
7
+ where to click, what it costs and what to paste back. Logins that open a
8
+ browser come before API keys. Never ask for a password, and never ask the
9
+ person to paste a key into the chat. Keys go into the tool that uses them.
10
+
11
+ ## Check the machine
12
+
13
+ Check for Node.js 22.12 or newer, pnpm and git, and install what is
14
+ missing. Then install `seo`:
15
+
16
+ ```sh
17
+ node --version
18
+ pnpm --version || npm i -g pnpm
19
+ git --version
20
+ npm i -g seo
21
+ ```
22
+
23
+ ## Sign in to each account, in this order
24
+
25
+ | Order | Account | How | Cost |
26
+ | --- | --- | --- | --- |
27
+ | 1 | GitHub | `gh auth login`, then choose the browser login | Free |
28
+ | 2 | Cloudflare | `npx wrangler login` | The free plan is enough |
29
+ | 3 | Domain | Buy it later, in the plan step, on Cloudflare Registrar | About $10 a year |
30
+ | 4 | Google Search Console | After the domain exists, add a Domain property and verify it through Cloudflare | Free |
31
+ | 5 | Bing Webmaster Tools | Import the site from Search Console | Free |
32
+ | 6 | SEO Skill | `seo start` signs in with Google and adds the MCP server and skill | Free |
33
+ | 7 | Keyword data (optional) | A DataForSEO or Ahrefs key, saved on the account page at https://seoskill.dev/account, then `seo login` | Free without a key, the provider bills you with one |
34
+ | 8 | Analytics | Clicky, on the production site only | Free tier |
35
+
36
+ Accounts 3 to 5 need the domain, so they wait until the plan is approved.
37
+ Note each one as a to-do for the launch step.
38
+
39
+ ## Keyword data is the person's choice
40
+
41
+ Without a key, the market and plan steps use free sources: the live search
42
+ results, autocomplete, forums and, once the site is live, its own Search
43
+ Console data. With a DataForSEO or Ahrefs key, `seo research` adds search
44
+ volumes, difficulty, the pages that rank and competitor keywords. Explain
45
+ both, give the price page of each provider, and let the person choose.
46
+ DataForSEO bills per request. Ahrefs needs a plan that includes API units.
47
+
48
+ ## Rules
49
+
50
+ - One account at a time. Wait for the person to finish before the next.
51
+ - If a login fails, read the error to them in plain words and try once more
52
+ before moving on.
53
+ - Write what was set up in the project notes, never the keys themselves.
54
+
55
+ Done when: `gh auth status`, `npx wrangler whoami` and `seo doctor` all
56
+ show a signed-in account, and the person has chosen free or paid keyword
57
+ data.
58
+
59
+ Next: `seo site guide market`
@@ -0,0 +1,55 @@
1
+ # Step 7 of 10: writing
2
+
3
+ Goal: copy a person enjoys reading and an AI answer can lift out and quote
4
+ correctly.
5
+
6
+ ## What the agent does
7
+
8
+ 1. Write in two passes. First collect the facts for a page from the data
9
+ and its sources. Then write only from those facts.
10
+ 2. Put sentences that depend on the data in `src/lib/narrative.ts`. Each
11
+ sentence is shown only when its fact exists, and the wording changes
12
+ with the numbers, so pages read differently.
13
+ 3. Check every claim against its source before it ships.
14
+ 4. Run `pnpm build`. `seo site check` fails on the copy rules below.
15
+
16
+ ## What the person does
17
+
18
+ Plan the sections of the main page type, because sections an AI plans come
19
+ out generic. Read a few pages like a visitor, and turn every pattern they
20
+ dislike into a rule.
21
+
22
+ ## Rules for people
23
+
24
+ - Clear, direct, full sentences. Say what the reader gets.
25
+ - The length is whatever answers the question. No word count targets, and
26
+ no "what is X" opening when the reader already knows.
27
+ - The title tag is for the search result: the words people search for
28
+ first, short enough not to be cut off. The H1 says the same thing in
29
+ plainer words.
30
+ - Questions in an FAQ come from real searches or common sense.
31
+ - Never write about the build, the tools, collecting data, search terms or
32
+ "coming soon".
33
+
34
+ `seo site check` fails on: dashes used as punctuation, semicolons, "it's
35
+ not X, it's Y" lines, hype words such as seamless, robust and unlock,
36
+ openings such as "in this guide" and "did you know", tool and process
37
+ words, and "coming soon". When a banned word is part of the subject (a
38
+ site about Cloudflare, say), add it to `allowWords` in `site.config.json`.
39
+
40
+ ## Rules for being quoted
41
+
42
+ - Every section answers on its own. Name the subject, give the answer in
43
+ the first sentence or two, then the conditions. Test it by reading the
44
+ section alone.
45
+ - Write H2s the way people ask.
46
+ - Keep each number next to its source and date, in visible text.
47
+ - Credit the site's own figures by name: "{Site}'s data shows", never "our
48
+ data".
49
+ - One strong page per claim. Keep price and other fast moving pages fresh,
50
+ with a visible date.
51
+
52
+ Done when: every section passes the read-it-alone test, the facts match the
53
+ sources and `pnpm build` passes.
54
+
55
+ Next: `seo site guide scale`