- name
- underserved-seo-page
- description
- End-to-end workflow for discovering underserved Google search keywords and shipping SEO-optimized /use-case/ pages on fazm.ai. Discovers keywords via SERP analysis, scores them for desktop-agent opportunity gaps, creates rich TSX pages with animated SVGs and comparison tables, builds, pushes, and updates state. Use when: 'next underserved keyword page', 'discover new SEO keywords', 'run underserved keyword pipeline', or when the cron triggers.
- user_invocable
- true
# Underserved SEO Page
Discover underserved Google search keywords where no desktop AI agent content exists, then ship a rich `/use-case/` page on fazm.ai targeting that gap. Unlike the GSC pipeline (which targets queries we already rank for), this pipeline finds *new* opportunities by analyzing SERPs for missing desktop-agent angles.
## Arguments
Either:
1. **Nothing** - skill picks the top pending keyword from `seo/inbox/state/underserved_keywords.json` (sorted by score descending), or discovers new keywords if none are pending.
2. **A specific keyword** - e.g. `"ai tiktok automation"` (manual mode).
## State File (source of truth)
**Path:** `seo/inbox/state/underserved_keywords.json`
Each keyword entry:
```json
{
"keyword": "ai bookkeeping automation",
"slug": "ai-bookkeeping-automation",
"score": 1.65,
"signal1_desktop_gap": 2,
"signal2_result_quality": 2,
"signal3_commercial_fit": 1,
"status": "done",
"page_url": "https://fazm.ai/use-case/ai-bookkeeping-automation",
"scored_at": "2026-04-05T00:00:00",
"completed_at": "2026-04-05T19:11:09",
"notes": "Results are cloud SaaS. None control QuickBooks desktop app."
}
```
| status | meaning |
|---|---|
| `pending` | scored and eligible for next pickup |
| `in_progress` | a run has claimed this keyword |
| `done` | a page has shipped |
| `skip` | too competitive or poor fit |
---
## Phase 1: Pick or Discover Keywords
### If pending keywords exist
Take the first entry where `status == "pending"` (highest score). Skip to Phase 2.
### If no pending keywords: Discovery
Use WebSearch to find new underserved keywords for AI desktop automation use cases.
**Seed patterns:**
- `"ai [app] automation"`
- `"ai [task] automation mac"`
- `"automate [app] with ai"`
- `"ai [workflow] automation desktop"`
**For each candidate keyword:**
1. Search Google for the keyword
2. Score on 3 signals:
| Signal | Weight | 0 | 1 | 2 |
|---|---|---|---|---|
| Desktop Agent Gap | 40% | Desktop agent tools in top 5 | Desktop mentioned but not primary | Zero desktop agent results |
| Result Quality Gap | 35% | Strong, comprehensive results | Mediocre listicles or thin content | Weak, off-topic, or sparse results |
| Commercial Intent Match | 25% | No purchase/tool intent | Some tool comparison intent | Clear "find a tool" intent |
3. **Composite score** = `(S1 * 0.4) + (S2 * 0.35) + (S3 * 0.25)`
4. If >= 1.5, add as `pending`. If < 1.0, add as `skip`. Between 1.0 and 1.5, use judgment.
5. Add to state file with notes explaining what you found in the SERPs.
**Cross-check:** Before adding, verify no existing page covers it: `ls src/app/use-case/`
After discovery, pick the top new pending keyword and continue.
## Phase 2: Claim Keyword
Set the keyword to `in_progress` in the state file immediately. This prevents concurrent runs from racing.
## Phase 3: Build the Page
**Location:** `src/app/use-case/{slug}/page.tsx`
**Reference template:** `src/app/use-case/ai-data-entry-automation/page.tsx`
Read the template before writing. The page is a single TSX file with no external dependencies beyond the shared Navbar and Footer components.
### File structure
```tsx
import { Metadata } from "next";
import Link from "next/link";
import { Navbar } from "@/components/navbar";
import { Footer } from "@/components/footer";
export const metadata: Metadata = { /* ... */ };
export default function PageName() {
const jsonLd = [ /* ... */ ];
return (
<main className="noise-overlay">
<Navbar />
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
<div className="max-w-4xl mx-auto px-6 py-24">
{/* All sections here */}
</div>
<Footer />
</main>
);
}
```
### Required metadata
```tsx
export const metadata: Metadata = {
title: "AI {Topic} Automation for Mac - {Subtitle} | Fazm",
description: "155-160 char meta description with primary keyword naturally included.",
keywords: ["primary keyword", "primary keyword mac", "variation 1", "variation 2", "variation 3", "variation 4"],
alternates: { canonical: "https://fazm.ai/use-case/{slug}" },
openGraph: {
title: "AI {Topic} Automation for Mac - Fazm",
description: "Short OG description.",
type: "website",
url: "https://fazm.ai/use-case/{slug}",
siteName: "Fazm",
},
twitter: {
card: "summary_large_image",
title: "AI {Topic} Automation for Mac - Fazm",
description: "Short Twitter description.",
},
};
```
### Required JSON-LD (4 blocks)
1. **WebPage** - name, description, url
2. **BreadcrumbList** - Home > Use Cases > {This Page}
3. **HowTo** - "How to Automate {X} with Fazm" with exactly 4 steps:
- Step 1: Download Fazm
- Step 2: Open the relevant app(s)
- Step 3: Describe the task
- Step 4: Fazm handles it
4. **FAQPage** - 4 Q&A pairs addressing common questions. First FAQ should always differentiate Fazm from cloud/SaaS competitors.
### Required sections (in order)
Every page MUST have all of these sections, in this exact order:
#### 1. Breadcrumbs
```tsx
<nav aria-label="Breadcrumb" className="mb-8">
<ol className="flex items-center gap-2 text-sm text-muted">
<li><Link href="/" className="hover:text-white transition-colors">Home</Link></li>
<li>/</li>
<li><Link href="/use-case" className="hover:text-white transition-colors">Use Cases</Link></li>
<li>/</li>
<li className="text-white">AI {Topic} Automation</li>
</ol>
</nav>
```
#### 2. H1 + Lede
```tsx
<h1 className="text-4xl sm:text-5xl font-bold text-white mb-6">
AI {Topic} Automation for macOS
</h1>
<p className="text-lg text-muted max-w-3xl mb-8">
{2-4 sentences. Open with a concrete stat or pain point. Explain why every
existing tool is cloud/SaaS. Position Fazm as the desktop agent alternative.}
</p>
```
#### 3. Animated SVG Diagram
A flow diagram showing: Source Data -> Fazm Agent -> Target App(s). Must include animated dots using SMIL `<animate>` elements.
**Color palette (mandatory):**
- Box fill: `#1e293b`
- Primary stroke: `#14b8a6` (teal)
- Agent stroke/text: `#2dd4bf` (bright teal)
- Accent stroke: `#0d9488` (dark teal)
- Text primary: `#e2e8f0`
- Text secondary: `#94a3b8`
- Connection lines: `#0d9488` with `strokeDasharray="4 3"` and `opacity="0.5"`
**Pattern:**
```tsx
<div className="my-8 max-w-lg mx-auto">
<svg viewBox="0 0 400 120" className="w-full" xmlns="http://www.w3.org/2000/svg">
{/* Source box */}
<rect x="10" y="35" width="90" height="50" rx="10" fill="#1e293b" stroke="#14b8a6" strokeWidth="2" />
<text x="55" y="58" textAnchor="middle" fill="#e2e8f0" fontSize="11" fontFamily="sans-serif">{Source}</text>
{/* Fazm agent box - slightly larger, brighter stroke */}
<rect x="155" y="30" width="90" height="60" rx="10" fill="#1e293b" stroke="#2dd4bf" strokeWidth="2.5" />
<text x="200" y="57" textAnchor="middle" fill="#2dd4bf" fontSize="12" fontWeight="bold" fontFamily="sans-serif">Fazm</text>
<text x="200" y="73" textAnchor="middle" fill="#94a3b8" fontSize="9" fontFamily="sans-serif">AI Agent</text>
{/* Target boxes (2-3 apps) */}
<rect x="300" y="10" width="90" height="30" rx="6" fill="#1e293b" stroke="#14b8a6" strokeWidth="1.5" />
<text x="345" y="30" textAnchor="middle" fill="#e2e8f0" fontSize="10" fontFamily="sans-serif">{App1}</text>
{/* ... more target boxes ... */}
{/* Dashed connection lines */}
<line x1="100" y1="60" x2="155" y2="60" stroke="#0d9488" strokeWidth="1.5" strokeDasharray="4 3" opacity="0.5" />
<line x1="245" y1="50" x2="300" y2="25" stroke="#0d9488" strokeWidth="1.5" strokeDasharray="4 3" opacity="0.5" />
{/* Animated dots - 2 dots with staggered timing */}
<circle r="4" fill="#2dd4bf">
<animate attributeName="cx" values="100;155;245;300" dur="2.5s" repeatCount="indefinite" />
<animate attributeName="cy" values="60;60;50;25" dur="2.5s" repeatCount="indefinite" />
<animate attributeName="opacity" values="1;0.8;0.6;1" dur="2.5s" repeatCount="indefinite" />
</circle>
<circle r="4" fill="#14b8a6">
<animate attributeName="cx" values="100;155;245;300" dur="2.5s" repeatCount="indefinite" begin="0.8s" />
<animate attributeName="cy" values="60;60;60;63" dur="2.5s" repeatCount="indefinite" begin="0.8s" />
<animate attributeName="opacity" values="1;0.8;0.6;1" dur="2.5s" repeatCount="indefinite" begin="0.8s" />
</circle>
</svg>
</div>
```
#### 4. Problem Section with Comparison Table
H2 that names the pain point. 2 paragraphs explaining the problem and why cloud tools miss the desktop angle.
Then a comparison table with 3 columns: Manual, Cloud SaaS (name the competitors), Fazm Desktop Agent. 5-6 rows comparing key dimensions.
```tsx
<div className="overflow-x-auto rounded-xl border border-white/5">
<table className="w-full text-sm text-left">
<thead>
<tr className="border-b border-white/10 bg-surface-light/50">
<th className="px-4 py-3 text-muted font-medium"></th>
<th className="px-4 py-3 text-muted font-medium">Manual</th>
<th className="px-4 py-3 text-muted font-medium">Cloud SaaS ({Competitor})</th>
<th className="px-4 py-3 text-accent font-semibold">Fazm Desktop Agent</th>
</tr>
</thead>
<tbody className="divide-y divide-white/5">
<tr className="bg-surface-light/30">
<td className="px-4 py-3 text-white font-medium">{Dimension}</td>
<td className="px-4 py-3 text-muted">{Manual answer}</td>
<td className="px-4 py-3 text-muted">{Cloud answer}</td>
<td className="px-4 py-3 text-white">{Fazm answer}</td>
</tr>
{/* Alternate bg-surface-light/30 and no bg on rows */}
</tbody>
</table>
</div>
```
#### 5. Example Prompts (7 items)
Real commands a user would give Fazm. Specific, actionable, mentioning real app names.
```tsx
<section className="mb-16">
<h2 className="text-2xl font-bold text-white mb-6">
{Topic} Commands You Can Give Fazm
</h2>
<div className="space-y-3">
{[
"Open this contract PDF in Preview, add my signature on page 3...",
// ... 6 more
].map((prompt) => (
GitHubで見る