Skip to content

Commit 1e7482a

Browse files
chore: port SEO audit skill from gitbook to Astro Starlight (#21)
- Update seo_audit.py URL-to-source-file mapping for src/content/docs/ flat structure (.mdx, index.mdx instead of .md, README.md) - Update sitemap URL to /sitemap-index.xml and add 308 redirect handling - Rewrite SKILL.md: replace all SUMMARY.md refs with src/sidebar.ts, update file paths in title exceptions, document frontmatter title + sidebar.label pattern for fixing duplicate titles - Rename references/gitbook-seo.md to starlight-seo.md and rewrite with full title resolution precedence documentation Co-authored-by: Oz <oz-agent@warp.dev>
1 parent 4f53585 commit 1e7482a

4 files changed

Lines changed: 137 additions & 78 deletions

File tree

.agents/skills/docs-seo-audit/SKILL.md

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ Crawl the live docs.warp.dev sitemap to find SEO issues and fix them in the sour
1717
From the docs repo root:
1818

1919
```bash
20-
python3 .warp/skills/docs-seo-audit/scripts/seo_audit.py \
20+
python3 .agents/skills/docs-seo-audit/scripts/seo_audit.py \
2121
--repo-root . \
2222
--output /tmp/seo-report.json
2323
```
2424

25-
The script fetches all pages listed in `https://docs.warp.dev/sitemap.xml` (a sitemap index including sub-sitemaps), extracts SEO metadata from each page's HTML, and checks for issues.
25+
The script fetches all pages listed in `https://docs.warp.dev/sitemap-index.xml` (a sitemap index including sub-sitemaps), extracts SEO metadata from each page's HTML, and checks for issues.
2626

2727
### Options
2828

@@ -34,7 +34,7 @@ The script fetches all pages listed in `https://docs.warp.dev/sitemap.xml` (a si
3434
### Quick test with a small sample
3535

3636
```bash
37-
python3 .warp/skills/docs-seo-audit/scripts/seo_audit.py --repo-root . --max-pages 20 --output /tmp/seo-sample.json
37+
python3 .agents/skills/docs-seo-audit/scripts/seo_audit.py --repo-root . --max-pages 20 --output /tmp/seo-sample.json
3838
```
3939

4040
## Reading the report
@@ -109,38 +109,77 @@ After reporting, ask the user which issues they want to fix before making change
109109
## Fixing issues
110110

111111
Before making any changes, read these references:
112-
1. `references/gitbook-seo.md` in this skill directory — explains the non-obvious way Astro Starlight generates title tags from astro.config.mjs (sidebar config) link text (not the H1 heading).
112+
1. `references/starlight-seo.md` in this skill directory — explains the non-obvious way Astro Starlight generates title tags from sidebar config label text (not the H1 heading).
113113
2. `AGENTS.md` at the docs repo root — the single source of truth for documentation style, voice, terminology, and formatting. All titles and descriptions you write must follow these conventions (terminology, sentence case, active voice, frontmatter description format).
114114

115115
### Key principles
116116

117-
1. **Title tags come from astro.config.mjs (sidebar config) link text**, not the H1 heading. To fix a title, change the link text in the relevant space's `astro.config.mjs (sidebar config)`.
117+
1. **Title tags come from the frontmatter `title` field if present, otherwise from sidebar config labels in `src/sidebar.ts`**not the H1 heading. To fix a title without changing the sidebar label, add or update the `title` field in the page's frontmatter (and optionally add `sidebar.label` to preserve the short nav label). To fix a title by changing the nav label, change the `label` property in `src/sidebar.ts`. For pages listed as bare slugs (e.g., `'terminal/windows/tabs'`), add an explicit `{ slug, label }` object to override the label.
118118
2. **Meta descriptions come from frontmatter**. To fix a description, edit the `description:` field in the page's YAML frontmatter.
119119
3. **OG and Twitter tags mirror title and description** automatically. No separate fix needed.
120-
4. **Changing astro.config.mjs (sidebar config) link text has side effects**: it also changes the sidebar label, breadcrumbs, and prev/next pagination. URLs are NOT affected.
120+
4. **Changing a sidebar config label has side effects**: it also changes the sidebar label, breadcrumbs, and prev/next pagination. URLs are NOT affected (URLs are based on the file path/slug).
121121
5. **When changing a title, also update the H1** in the markdown file for consistency.
122122

123123
### Title exceptions
124124

125125
Some page titles are intentionally short or specific and must **not** be changed, even if they trigger a `title_too_short` warning. Skip these pages and note them as intentional exceptions in your report:
126126

127-
- **`src/content/docs/changelog/README.md`** (`Changelog`) — "Changelog" is a clear, universally understood industry term. Branding prefixes like "Warp changelog" or "Release changelog" add no descriptive value and this title should remain as-is.
128-
- **`src/content/docs/terminal/appearance/app-icons.md`** (`App icons`) — The article explicitly explains that *custom* app icons are not available to users. Renaming to "Custom app icons" directly contradicts the page content and must be avoided.
129-
- **`src/content/docs/university/README.md`** (`Guides`) — "Guides" is the landing page for the Guides space. The title is clear and matches the space name; prefixing it (e.g., "Developer Guides") adds no value and creates a mismatch with the space title shown in breadcrumbs.
127+
- **`src/content/docs/changelog/index.mdx`** (`Changelog`) — "Changelog" is a clear, universally understood industry term. Branding prefixes like "Warp changelog" or "Release changelog" add no descriptive value and this title should remain as-is.
128+
- **`src/content/docs/terminal/appearance/app-icons.mdx`** (`Custom app icons`) — The article explicitly explains that *custom* app icons are not available to users. The sidebar label is intentional and must not be changed.
129+
- **`src/content/docs/guides/index.mdx`** (`Guides`) — "Guides" is the landing page for the Guides section. The title is clear and matches the section name; prefixing it (e.g., "Developer Guides") adds no value and creates a mismatch with the section title shown in breadcrumbs.
130+
- **`src/content/docs/terminal/windows/tabs.mdx`** (`Tabs`) — The sidebar section header ("Windows and Tabs") already provides terminal context; adding a "Terminal" prefix creates a name not used in the UI or anywhere else in the docs. The `title_too_short` warning is intentionally suppressed — the title is short by design. Do not rename to "Terminal tabs".
131+
- **`src/content/docs/terminal/windows/vertical-tabs.mdx`** (`Vertical Tabs`) — Same rationale: the section header disambiguates the terminal context. The `title_too_short` warning is intentionally suppressed. Do not rename to "Terminal vertical tabs".
132+
- **`src/content/docs/terminal/windows/split-panes.mdx`** (`Split panes`) — Same rationale: the section header disambiguates the terminal context. The `title_too_short` warning is intentionally suppressed. Do not rename to "Terminal split panes".
133+
- **`src/content/docs/terminal/windows/tab-configs.mdx`** (`Tab Configs`) — Same rationale: the section header disambiguates the terminal context. Additionally, "Tab Configs" is a proper feature name and should not be prefixed. The `title_too_short` warning is intentionally suppressed. Do not rename to "Terminal Tab Configs".
134+
- **`src/content/docs/terminal/sessions/index.mdx`** (`Sessions`) — The sidebar section header ("Sessions") already provides terminal context. The `title_too_short` warning is intentionally suppressed. Do not rename to "Terminal sessions".
130135

131136
When the audit flags these pages for `title_too_short`, exclude them from your fix list and include a note in your report explaining they are intentional exceptions.
132137

133138
If you believe a new title should be added to this exceptions list, flag it for human review before proceeding.
134139

140+
### Sidebar config labels vs. H1 headings
141+
142+
Sidebar config labels (the `label` property in `src/sidebar.ts`) and H1 page headings are **intentionally different** in some cases. Do not change either to match the other unless you are fixing a genuine duplicate title collision. Specifically:
143+
144+
- Do **not** add section-context prefixes (like "Terminal", "Warp", or "Agent") to short but accurate titles just because the title appears generic in isolation. Sidebar context already provides that disambiguation.
145+
- Do **not** rename sidebar config labels for pages in the exceptions list above.
146+
- Do **not** sync sidebar config label text to match H1 headings (or vice versa) as a standalone change — the two are allowed to differ.
147+
135148
### Fixing duplicate titles
136149

137150
This is the most impactful issue. Common causes:
138-
- Multiple pages named `[Overview](...)` under different sections of the same space
139-
- Generic names like `[Getting Started](...)` or `[FAQs](...)` repeated across sections
151+
- Multiple pages with `label: 'Overview'` under different sections — these all produce the same `<title>` tag
152+
- Generic labels like `'Getting Started'` or `'FAQs'` repeated across sections
153+
154+
There are two ways to fix duplicate titles, depending on whether the short sidebar label is intentional:
155+
156+
#### Preferred: frontmatter `title` + `sidebar.label` (keep short nav labels)
157+
158+
When a page intentionally uses a short sidebar label like "Overview" because the section header provides context, **do not rename the sidebar config label**. Instead, add a descriptive `title` in the page's frontmatter and use `sidebar.label` to preserve the short nav label:
159+
160+
```yaml
161+
---
162+
title: Capabilities overview
163+
sidebar:
164+
label: "Overview"
165+
---
166+
```
167+
168+
Astro Starlight uses `title` for the `<title>` tag and `sidebar.label` for the sidebar. This gives each page a unique, SEO-friendly title while keeping the sidebar clean.
169+
170+
Example:
171+
- `agent-platform/capabilities/index.mdx`: `title: 'Capabilities overview'` + `sidebar.label: 'Overview'`
172+
- `agent-platform/cloud-agents/integrations/index.mdx`: `title: 'Integrations overview'` + `sidebar.label: 'Overview'`
173+
174+
When using this approach, also update the H1 in the markdown file to match the new `title`.
175+
176+
#### Alternative: rename the sidebar config label
177+
178+
If the short label is not intentional, rename the `label` in `src/sidebar.ts` to be unique and descriptive. Use sentence case and correct terminology per `AGENTS.md` (e.g., capitalize proper feature names like "Agent Mode", "Warp Drive", "Codebase Context" — but not generic terms like "overview", "quickstart", or "agents"). Example:
179+
- Before: `{ slug: 'agent-platform/local-agents', label: 'Overview' }` + `{ slug: 'agent-platform/cloud-agents', label: 'Overview' }`
180+
- After: `{ slug: 'agent-platform/local-agents', label: 'Local agents overview' }` + `{ slug: 'agent-platform/cloud-agents', label: 'Cloud agents overview' }`
140181

141-
Fix by making each astro.config.mjs (sidebar config) link text unique and descriptive. The link text should identify the specific topic, not just the page type. Use sentence case and correct terminology per `AGENTS.md` (e.g., capitalize product feature names like "Agent Mode", "Warp Drive", "Codebase Context"). Example:
142-
- Before: `[Overview](local-agents/overview.mdx)` + `[Overview](cloud-agents/overview.md)`
143-
- After: `[Local Agents Overview](local-agents/overview.mdx)` + `[Cloud Agents Overview](cloud-agents/overview.md)`
182+
When changing a sidebar config label, also update the H1 in the markdown file for consistency.
144183

145184
### Fixing missing descriptions
146185

@@ -165,12 +204,13 @@ Write descriptions that:
165204
After making fixes, review every change before presenting to the user. Run through this checklist, and if anything fails, fix it and re-run the checklist from the top. Only present changes when everything passes.
166205

167206
- **Does this still mean the same thing?** Titles and descriptions must accurately represent the page content. Read the actual page before writing or rewriting anything. Never invent features, capabilities, or details that aren't on the page. If unsure what the page covers, read it first.
168-
- **Did I introduce a new duplicate?** Scan the full astro.config.mjs (sidebar config) for the space you edited. Verify every link text is unique. This is the most common mistake — fixing one duplicate by picking a name that collides with an existing entry.
169-
- **Does the H1 match?** Every astro.config.mjs (sidebar config) title change needs a corresponding H1 update in the markdown file. Mismatches between sidebar label and page heading confuse readers.
207+
- **Did I introduce a new duplicate?** Scan the full sidebar config in `src/sidebar.ts`. Verify every label is unique within the site. This is the most common mistake — fixing one duplicate by picking a name that collides with an existing entry.
208+
- **Does the H1 match?** Every sidebar config label change needs a corresponding H1 update in the markdown file. Mismatches between sidebar label and page heading confuse readers.
170209
- **Is the terminology right?** Cross-check against `AGENTS.md` and how the feature is actually referred to in the existing docs. Don't rename things to terms that aren't used elsewhere in the docs.
171-
- **Does this read naturally in context?** Consider how the title appears (a) as a sidebar label under its section header, and (b) as a search result: `{Title} | {Space} | Warp`. If it sounds awkward or uses internal jargon that users wouldn't recognize, rephrase.
210+
- **Is the casing right?** All labels and H1 headings must use sentence case. Proper product feature names (e.g., "Agent Mode", "Codebase Context", "Admin Panel", "Remote Control", "Warp Drive") retain their capitalization, but generic terms ("overview", "quickstart", "agents", "notifications") are lowercase. Never use title case.
211+
- **Does this read naturally in context?** Consider how the title appears (a) as a sidebar label under its section header, and (b) as a search result: `{Title} | {Topic} | Warp`. If it sounds awkward or uses internal jargon that users wouldn't recognize, rephrase.
172212
- **Are descriptions grounded in page content?** Don't write descriptions based on the title alone. Read the page, then summarize what's actually there.
173-
- **Any other improvements nearby?** Look at adjacent entries in the astro.config.mjs (sidebar config). Are there other generic titles ("Overview", "Getting Started", "FAQ") that could become duplicates in the future? Flag them proactively.
213+
- **Any other improvements nearby?** Look at adjacent entries in `src/sidebar.ts`. Are there other generic labels ("Overview", "Getting Started", "FAQ") that could become duplicates in the future? Flag them proactively.
174214

175215
### Delivering changes
176216

.agents/skills/docs-seo-audit/references/gitbook-seo.md

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# How Astro Starlight generates SEO title tags
2+
3+
Astro Starlight constructs the HTML `<title>` tag as: `{Page Title} | {Site Title}` (e.g., `Skills | Warp`).
4+
5+
**The page title is resolved in this order of precedence:**
6+
1. The `title` field in the page's YAML frontmatter (if present)
7+
2. The `label` property in the sidebar config (`src/sidebar.ts`)
8+
3. The slug-derived title (auto-generated from the file name)
9+
10+
The H1 heading does **not** affect the `<title>` tag.
11+
12+
For example, if `src/sidebar.ts` has `{ slug: 'agent-platform/capabilities', label: 'Overview' }` and the page has no frontmatter `title`, the rendered title is `<title>Overview | Warp</title>`. But if the page has `title: Capabilities overview` in frontmatter, that takes precedence and produces `<title>Capabilities overview | Warp</title>`.
13+
14+
## Decoupling sidebar label from page title
15+
16+
To give a page a unique SEO title while keeping a short sidebar label, use both `title` and `sidebar.label` in frontmatter:
17+
18+
```yaml
19+
---
20+
title: Capabilities overview
21+
sidebar:
22+
label: "Overview"
23+
---
24+
```
25+
26+
This produces `<title>Capabilities overview | Warp</title>` while displaying "Overview" in the sidebar.
27+
28+
## Side effects of changing sidebar config labels
29+
30+
Changing the `label` in `src/sidebar.ts` also changes the sidebar label, breadcrumbs, and prev/next pagination. It does NOT change the URL (URLs are based on the file path/slug).
31+
32+
## Meta descriptions
33+
34+
Meta descriptions come from the `description` field in YAML frontmatter — this part is straightforward.

0 commit comments

Comments
 (0)