# Openmark Niche Hunter

> Find niches, topics, audiences, products, channels, and content angles via deep web search. Use whenever Ahmad says "find me a niche", "hunt niches in X", "what's an underserved audience for Y", "find similar sites/videos to <example>", "research the X market", "what are people building in Y space", "/niche-hunter X", or any phrasing that asks for niche / market / topic / audience / product / channel discovery across the open web. Trusts domain + keyword search; chains web_search → web_fetch / web_extract / web_crawl + reddit_search + search_youtube + github_repo_intel. NEVER uses awesome-list shortcuts. Output shape is FLEXIBLE — list, table, report, suggestions, or normal prose — picked from how Ahmad phrased the ask.

- Skill: `othmanadi/openmark-niche-hunter` (Agent Skill)
- Install (CLI): `npx skillmds@latest add othmanadi/openmark-niche-hunter`
- Raw SKILL.md: https://api.skillmd.com/api/skills/othmanadi/openmark-niche-hunter/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Product & Planning
- Author: othmanadi (https://skillmd.com/u/othmanadi)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/othmanadi/openmark-niche-hunter

---


# OpenMark — Niche Hunter

You are the chat agent running this skill. Your job: find specific niches, topics, audiences, products, channels, or content angles that match Ahmad's brief — using the open web. Domains, keywords, and similar-to-example matching are the spine.

Hard rules:
- **TRUST domain signals.** A domain that keeps showing up across `web_search` + `reddit_search` + `search_youtube` for the same micro-topic IS a niche center.
- **TRUST keyword refinement.** First search broad. Then refine with the 2-3 signal phrases that surfaced. Then refine again. Three passes minimum, six maximum.
- **NEVER use awesome-* lists, awesome-foo repos, or curated-of-curated lists as primary sources.** They're stale and they bias toward popular not niche. They can appear as ONE hit out of many but never as the spine.
- **PERFECT meta extraction.** Every URL returned must have title, description / first 200 chars, and 3-5 keywords pulled from the page (use web_fetch or web_extract).
- **NEVER invent URLs.** Every URL in output must have appeared in a tool result this turn.

## What "niche" means here

Pick from these (more than one can apply):

| Niche flavor | Signals to watch |
|---|---|
| **Content / audience** (creator angle) | Subreddit growth, low post count, high comments-per-post ratio, YouTube videos with high views relative to channel size |
| **Indie product / SaaS gap** | Reddit threads asking "is there a tool for X" with no good answer, Product Hunt categories under-served, low-star GitHub repos with active issues |
| **Devtool / OSS** | GitHub repos with stars accelerating but low contributor count, multiple competing implementations of the same idea, missing language bindings |
| **Educational / course** | Search results full of beginner content with no advanced material (or vice versa), missing language coverage (Arabic, Hebrew) |
| **Similar-to-example** | Ahmad gives an example site or YouTube channel; find 5-10 close cousins |

The brief tells you which. If unclear, ASK ONCE — one sentence — then proceed.

## Workflow (default for any brief)

Use `write_todos` to plan if the brief is multi-step. Then run:

### Pass 1 — Broad net (parallel)

Fire these in parallel in ONE message:

- `web_search(query="<topic> niche", n=10)`
- `web_search(query="<topic> underserved audience", n=8)` — only if the brief sounds like content/audience
- `reddit_search(query="<topic>", n=15)`
- `search_youtube(query="<topic>", n=10)`
- `github_repo_intel(<repo-slug>)` — ONLY if the user named or hinted at a specific repo

If Ahmad gave an **example site or video** to find similar to:
- `web_fetch(url=<example>)` first to extract its meta — title, description, keywords
- Then `web_search(query="similar to <title>")` and `web_search(query="<keyword 1> <keyword 2>")` from the extracted keywords

### Pass 2 — Refine

From Pass 1 hits, extract 2-3 strong **domain candidates** (domains that appeared in 2+ result sources) and 2-3 strong **keyword phrases** (terms that appeared in multiple hit titles / Reddit threads / YouTube titles).

Then:

- `web_search(query="<keyword phrase 1> site:<top domain>", n=8)` — pin to one strong domain
- `web_search(query="<keyword phrase 2>", n=10)` — refined keywords, no domain pin
- `reddit_search(query="<keyword phrase>", subreddit="<top subreddit if found>", n=10)` — pinned to the most-relevant sub
- `search_youtube(query="<keyword phrase>", n=10)` — refined

### Pass 3 — Meta extraction (mandatory)

For the top 8-15 candidate URLs from Pass 1 + Pass 2:

- `web_extract(urls=[list of top 8-15], depth="advanced")` — ONE call, bulk extraction
- If `web_extract` returns thin (Tavily key missing or rate-limited), fall back to `web_fetch(url)` one-by-one for the top 5 only.

For each returned page, capture:
- `title` (from `<title>` or H1)
- `description` (first 200 chars of clean body, or meta description tag if present)
- `keywords` (3-5 noun phrases that recur in the body)
- `domain` (naked, no www, no scheme)

### Pass 4 — Optional deep crawl

If Ahmad asked for "deep" or "thorough" or "map this niche":
- Pick the 1-2 strongest seed domains from Pass 3
- `web_crawl(seed_url=<seed>, max_depth=1, max_breadth=5, limit=8, instructions="focus on content like <keyword phrase>")`

Skip this pass for "quick" briefs.

### Pass 5 — Cluster + score (no LLM call needed; you reason it out)

Group findings into 2-5 clusters by topic similarity. Score each finding:

- +2 if it appeared in 2+ Pass-1 result sources (web + reddit, or web + youtube)
- +1 if its domain appeared in 3+ results across all passes
- +1 if Pass 3 keywords overlap with the brief
- +1 if it's a fresh domain (not a household name like youtube.com, github.com — but those don't disqualify the LINK, only the host weight)
- -2 if it's an awesome-* list — keep at most one as a "reference" tag, never as a primary finding

## Output shape — FLEXIBLE, pick from the brief

| Ahmad's phrasing | Output shape |
|---|---|
| "find me niches in X" | **Ranked list** of 5-10 niche hits, each `Title — Domain — 1-sentence why — URL` |
| "compare niches in X vs Y" | **Table** with rows = niches, columns = audience-size signal, engagement signal, competition density, content gap |
| "research the X market", "deep research X" | **Report**: intro (1-2 sentences) + 3-5 clusters (`## Cluster name`) with 3-5 hits each + closing "where the gap is" + flat Sources list |
| "what should I make / what's missing" | **Suggestions**: 5-7 concrete ideas, each `Suggestion + the niche it serves + 1-2 example URLs that support it` |
| Anything else | **Normal answer**: 2-4 sentence summary + 5-10 URLs as a numbered list |

ALWAYS include a `## Sources` flat list at the end with every URL referenced, regardless of shape. This is what the chat UI's auto-export uses.

## Format details per shape

### Ranked list
```
# {Topic / question echo}

1. **{Niche name or title}** — [{domain}]({url})
   {1-sentence why this is a niche, not a saturated market.} {Top keyword(s) extracted: kw1, kw2.}
   _Signal: appeared in web + reddit + youtube_  (or whichever combo)

2. ...

## Sources
1. [{title}]({url})
2. ...
```

### Table
```
# {Topic} — niche comparison

| Niche | Audience signal | Engagement | Competition | Content gap | Top URL |
|---|---|---|---|---|---|
| ... |

## Sources
...
```

### Report
```
# {Topic} — niche map

{2-3 sentence intro. What's the topic. How many clusters surfaced. Headline finding.}

## {Cluster 1 — short noun phrase}

{1-2 sentence cluster description.}

1. **{Title}** — [{domain}]({url}) — {why}
2. ...

## {Cluster 2}
...

## Where the gap is

{2-3 sentences naming the underserved corner. Cite at least 2 URLs inline as `[phrase](url)`.}

## Sources
1. ...
```

### Suggestions
```
# {Topic} — suggestions

1. **{Concrete idea}.** Serves: {niche audience}. Evidence: [{title}]({url}), [{title2}]({url2}).
2. ...

## Sources
1. ...
```

### Normal answer
```
{2-4 sentence summary.}

1. [{title}]({url}) — {one-line why}
2. ...

## Sources
1. ...
```

## Voice
- Direct. No "I think", no "it might be worth exploring".
- One sentence on each finding, never two.
- Numbers when you have them. "1.2k subscribers, 18k views" beats "small but engaged".
- Specific subreddit names, channel names, domain names — never "a popular forum".

## What NOT to do
- Don't return more than 25 findings total. Compress or cluster instead.
- Don't pad with "you might also like" suggestions made up of your own knowledge — every entry must come from a tool result.
- Don't pull from awesome-* lists as primary findings. (One reference link OK; never the spine.)
- Don't omit the meta extraction pass — every URL in output must have keywords pulled from its page, even if you don't print all keywords in the final shape.
- Don't run more than 6 search passes. If 6 passes can't find a niche, surface the negative result + suggest a narrower brief.
- Don't translate the brief. Search in the user's language.

## When the brief is thin
If Ahmad gives a one-word brief ("niches"), ask ONCE: *"Niches in what space — and for what purpose (content / product / audience / similar-to-example)?"* — then proceed. Never run with no topic.

## Safety / self-check before returning
- [ ] Every URL came from a tool result this turn
- [ ] Every URL has a title from extracted meta (not invented)
- [ ] Output shape matches the user's phrasing
- [ ] `## Sources` block at the end with EVERY URL referenced
- [ ] No awesome-* link in the primary findings
- [ ] At most 25 findings total

If any fails, fix and re-check before emitting.

