Next.js Internationalization

I18n

by OpenClaudia · MIT license · ★ 705 on GitHub

I18n cover

Add full internationalization (i18n) to a Next.js project using next-intl. Supports 14+ languages, SEO-friendly locale routing, hreflang sitemaps, and bulk translation.

---
name: i18n
description: Add full internationalization (i18n) to a Next.js project using next-intl. Supports 14+ languages, SEO-friendly locale routing, hreflang sitemaps, and bulk translation. Use when the user asks to "internationalize", "add i18n", "add translations", "multi-language", "localize", "add language support", or "translate my site".
user_invocable: true
---

# Internationalize a Next.js Project

Add complete internationalization to a Next.js (App Router) project using **next-intl v4**. This skill handles routing, translation files, sitemap hreflang, and bulk translation across all locales.

## Step 1: Assess the Project

1. Check the Next.js version (`package.json`) — must be 13+ with App Router
2. Check if i18n is already partially set up (look for `next-intl`, `next-i18next`, `[locale]` routes)
3. Identify all pages/routes that need translation
4. Identify all user-facing strings (hardcoded text in components)
5. Ask the user which locales to support (default recommendation: en, es, fr, de, pt, ja, ar, zh, zh-tw, id, vi, ms, ru, hi)

Overview

Add complete internationalization to a Next.js (App Router) project using next-intl v4. This skill handles routing, translation files, sitemap hreflang, and bulk translation across all locales.

Manual install (npx, ZIP)
Claude Codenpx skills add OpenClaudia/openclaudia-skills --skill i18n -g -a claude-code
Claude Code (degit)npx degit OpenClaudia/openclaudia-skills/skills/i18n#main ~/.claude/skills/i18n
Claude.ai / desktopZip the folder and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md9.2 KB
Read SKILL.md here
OpenClaudia/main1 file shown
SKILL.md
Show the full text273 lines

Internationalize a Next.js Project

Add complete internationalization to a Next.js (App Router) project using next-intl v4. This skill handles routing, translation files, sitemap hreflang, and bulk translation across all locales.

Step 1: Assess the Project

  1. Check the Next.js version (package.json) — must be 13+ with App Router
  2. Check if i18n is already partially set up (look for next-intl, next-i18next, [locale] routes)
  3. Identify all pages/routes that need translation
  4. Identify all user-facing strings (hardcoded text in components)
  5. Ask the user which locales to support (default recommendation: en, es, fr, de, pt, ja, ar, zh, zh-tw, id, vi, ms, ru, hi)

Step 2: Install Dependencies

npm install next-intl

Step 3: Create i18n Configuration Files

Create 4 files under src/i18n/:

src/i18n/config.ts
export const locales = ['en', 'es', 'fr', 'de', 'pt', 'ja', 'ar', 'zh', 'zh-tw', 'id', 'vi', 'ms', 'ru', 'hi'] as const

export type Locale = (typeof locales)[number]
export const defaultLocale: Locale = 'en'

export const localeNames: Record<Locale, string> = {
  en: 'English',
  es: 'Espanol',
  fr: 'Francais',
  de: 'Deutsch',
  pt: 'Portugues',
  ja: '日本語',
  ar: 'العربية',
  zh: '简体中文',
  'zh-tw': '繁體中文',
  id: 'Bahasa Indonesia',
  vi: 'Tieng Viet',
  ms: 'Bahasa Melayu',
  ru: 'Русский',
  hi: 'हिन्दी',
}

export const rtlLocales: Locale[] = ['ar']
src/i18n/routing.ts
import { defineRouting } from 'next-intl/routing'
import { defaultLocale, locales } from './config'

export const routing = defineRouting({
  locales,
  defaultLocale,
  localePrefix: 'as-needed', // English URLs stay clean, other locales get /es/, /fr/, etc.
})
src/i18n/navigation.ts
import { createNavigation } from 'next-intl/navigation'
import { routing } from './routing'

export const { Link, redirect, usePathname, useRouter } = createNavigation(routing)
src/i18n/request.ts
import { getRequestConfig } from 'next-intl/server'
import { routing } from './routing'

export default getRequestConfig(async ({ requestLocale }) => {
  let locale = await requestLocale
  if (!locale || !routing.locales.includes(locale as any)) {
    locale = routing.defaultLocale
  }
  return {
    locale,
    messages: (await import(`../messages/${locale}.json`)).default,
  }
})

Step 4: Create Middleware

Create src/middleware.ts:

import createMiddleware from 'next-intl/middleware'
import { routing } from '@/i18n/routing'

export default createMiddleware({
  ...routing,
  localeDetection: false, // Don't auto-redirect based on Accept-Language
})

export const config = {
  matcher: ['/((?!_next|api|images|fonts|favicon|sitemap|robots).*)'],
}

Key decision: localeDetection: false prevents auto-redirecting users based on browser language. This keeps English URLs stable for SEO. Users can manually switch languages via a language selector.

Step 5: Update next.config

Wrap the existing config with createNextIntlPlugin:

import createNextIntlPlugin from 'next-intl/plugin'
const withNextIntl = createNextIntlPlugin('./src/i18n/request.ts')

// ... existing config ...
export default withNextIntl(nextConfig)

Step 6: Add [locale] Dynamic Route

Move all page content under src/app/[locale]/:

  1. Create src/app/[locale]/layout.tsx with:

    • generateStaticParams() returning all locales
    • setRequestLocale(locale) call
    • <NextIntlClientProvider> wrapping children
    • <html lang={locale} dir={rtlLocales.includes(locale) ? 'rtl' : 'ltr'}>
    • Hreflang <link> tags in <head> for all locales + x-default
  2. Move existing pages into src/app/[locale]/

  3. Each page should call setRequestLocale(locale) for static generation

Step 7: Extract Strings into Translation Files

  1. Create src/messages/en.json with all user-facing strings organized by section:

    {
      "common": { "signIn": "Sign In", ... },
      "tools": { "tool-slug": { "title": "...", "description": "..." } },
      "faq": { "tool-slug": [{ "question": "...", "answer": "..." }] }
    }
    
  2. Replace all hardcoded strings in components with useTranslations():

    const t = useTranslations('common')
    return <button>{t('signIn')}</button>
    
  3. For server components, use getTranslations():

    const t = await getTranslations('common')
    

Step 8: Translate to All Locales

For each non-English locale, create src/messages/{locale}.json with the same structure as en.json.

Translation Strategy

Use parallel Codex agents via the codex-tasks skill to save Claude credits:

  1. Launch one Codex task per locale (up to 7 in parallel) using /codex-tasks
  2. Each task reads en.json, translates all strings, writes {locale}.json
  3. Codex prompt should include:
    • The full en.json content (or path to read it)
    • Target language name and locale code
    • Instructions:
      • Translate naturally, not literally
      • Keep technical terms in English (PowerPoint, PDF, API, etc.)
      • Preserve JSON structure exactly (same keys, same nesting)
      • Preserve interpolation variables like {count}, {name} unchanged
      • Write the result to src/messages/{locale}.json
  4. After Codex tasks complete, verify the results using the verification script below — Codex output quality varies and must be checked
Verification

After translation, run a verification script to catch issues:

import json

locales = ['es', 'fr', 'de', 'pt', 'ja', 'ar', 'zh', 'zh-tw', 'id', 'vi', 'ms', 'ru', 'hi']
english_words = ['the ', 'and ', 'you ', 'your ', 'our ', 'this ', 'that ', 'with ', 'from ', 'will ']

with open('src/messages/en.json') as f:
    en = json.load(f)

for loc in locales:
    with open(f'src/messages/{loc}.json') as f:
        data = json.load(f)

    # Check: missing sections
    missing = [s for s in en if s not in data]

    # Check: residual English content
    eng_count = 0
    def check(d):
        nonlocal eng_count  # won't work in inline script; use list trick
        if isinstance(d, dict):
            for v in d.values(): check(v)
        elif isinstance(d, str):
            if sum(1 for w in english_words if w in d.lower()) >= 3:
                eng_count += 1
    check(data)

    status = 'OK' if not missing and eng_count == 0 else 'ISSUES'
    print(f'{loc}: {status} (missing={len(missing)}, english={eng_count})')

Step 9: Update Sitemap with Hreflang

Update src/app/sitemap.ts to include hreflang alternates:

import { MetadataRoute } from 'next'
import { locales } from '@/i18n/config'

const baseUrl = 'https://www.example.com'

function buildAlternates(path: string): Record<string, string> {
  const alternates: Record<string, string> = {}
  for (const locale of locales) {
    const prefix = locale === 'en' ? '' : `/${locale}`
    alternates[locale] = `${baseUrl}${prefix}${path}`
  }
  return alternates
}

export default function sitemap(): MetadataRoute.Sitemap {
  return pages.map((path) => ({
    url: `${baseUrl}${path}`,
    lastModified: new Date(),
    alternates: { languages: buildAlternates(path) },
  }))
}

Important: Generate one canonical URL per page with hreflang alternates, NOT one URL per locale. This prevents duplicate content in search results.

Step 10: Add Language Selector (Optional)

Add a language switcher component that uses useRouter and usePathname from @/i18n/navigation to switch locales while preserving the current path.

Step 11: Verify

  1. Build the project: npm run build — check that all static pages generate correctly
  2. Test English URLs have no prefix: https://example.com/tools
  3. Test locale URLs have prefix: https://example.com/es/tools
  4. Verify sitemap has hreflang alternates
  5. Check RTL rendering for Arabic
  6. Run the translation verification script from Step 8

Common Pitfalls

  • public/sitemap.xml conflicts with dynamic src/app/sitemap.ts in dev mode — delete the static one or rename it
  • Middleware matcher must exclude _next, api, sitemap, robots, and static asset paths
  • localePrefix: 'as-needed' is critical — it keeps default locale URLs clean for SEO continuity
  • localeDetection: false prevents unwanted redirects that break SEO and confuse users
  • Large translation files (5000+ lines per locale) can make git pushes fail — use git config http.postBuffer 524288000
  • Verify translations thoroughly — automated translation often produces mixed-language output; always verify with the English word detection script after Codex tasks complete

Locale Count Reference

  • 14 locales x N pages = 14N static pages at build time
  • Each locale JSON file is typically 2-5x the size of en.json (CJK characters, verbose languages)
  • Build time increases linearly with locale count
1---
2name: i18n
3description: Add full internationalization (i18n) to a Next.js project using next-intl. Supports 14+ languages, SEO-friendly locale routing, hreflang sitemaps, and bulk translation. Use when the user asks to "internationalize", "add i18n", "add translations", "multi-language", "localize", "add language support", or "translate my site".
4user_invocable: true
5---
6 
7# Internationalize a Next.js Project
8 
9Add complete internationalization to a Next.js (App Router) project using **next-intl v4**. This skill handles routing, translation files, sitemap hreflang, and bulk translation across all locales.
10 
11## Step 1: Assess the Project
12 
131. Check the Next.js version (`package.json`) — must be 13+ with App Router
142. Check if i18n is already partially set up (look for `next-intl`, `next-i18next`, `[locale]` routes)
153. Identify all pages/routes that need translation
164. Identify all user-facing strings (hardcoded text in components)
175. Ask the user which locales to support (default recommendation: en, es, fr, de, pt, ja, ar, zh, zh-tw, id, vi, ms, ru, hi)
18 
19## Step 2: Install Dependencies
20 
21```bash
22npm install next-intl
23```
24 
25## Step 3: Create i18n Configuration Files
26 
27Create 4 files under `src/i18n/`:
28 
29### `src/i18n/config.ts`
30```typescript
31export const locales = ['en', 'es', 'fr', 'de', 'pt', 'ja', 'ar', 'zh', 'zh-tw', 'id', 'vi', 'ms', 'ru', 'hi'] as const
32 
33export type Locale = (typeof locales)[number]
34export const defaultLocale: Locale = 'en'
35 
36export const localeNames: Record<Locale, string> = {
37 en: 'English',
38 es: 'Espanol',
39 fr: 'Francais',
40 de: 'Deutsch',
41 pt: 'Portugues',
42 ja: '日本語',
43 ar: 'العربية',
44 zh: '简体中文',
45 'zh-tw': '繁體中文',
46 id: 'Bahasa Indonesia',
47 vi: 'Tieng Viet',
48 ms: 'Bahasa Melayu',
49 ru: 'Русский',
50 hi: 'हिन्दी',
51}
52 
53export const rtlLocales: Locale[] = ['ar']
54```
55 
56### `src/i18n/routing.ts`
57```typescript
58import { defineRouting } from 'next-intl/routing'
59import { defaultLocale, locales } from './config'
60 
61export const routing = defineRouting({
62 locales,
63 defaultLocale,
64 localePrefix: 'as-needed', // English URLs stay clean, other locales get /es/, /fr/, etc.
65})
66```
67 
68### `src/i18n/navigation.ts`
69```typescript
70import { createNavigation } from 'next-intl/navigation'
71import { routing } from './routing'
72 
73export const { Link, redirect, usePathname, useRouter } = createNavigation(routing)
74```
75 
76### `src/i18n/request.ts`
77```typescript
78import { getRequestConfig } from 'next-intl/server'
79import { routing } from './routing'
80 
81export default getRequestConfig(async ({ requestLocale }) => {
82 let locale = await requestLocale
83 if (!locale || !routing.locales.includes(locale as any)) {
84 locale = routing.defaultLocale
85 }
86 return {
87 locale,
88 messages: (await import(`../messages/${locale}.json`)).default,
89 }
90})
91```
92 
93## Step 4: Create Middleware
94 
95Create `src/middleware.ts`:
96```typescript
97import createMiddleware from 'next-intl/middleware'
98import { routing } from '@/i18n/routing'
99 
100export default createMiddleware({
101 ...routing,
102 localeDetection: false, // Don't auto-redirect based on Accept-Language
103})
104 
105export const config = {
106 matcher: ['/((?!_next|api|images|fonts|favicon|sitemap|robots).*)'],
107}
108```
109 
110**Key decision**: `localeDetection: false` prevents auto-redirecting users based on browser language. This keeps English URLs stable for SEO. Users can manually switch languages via a language selector.
111 
112## Step 5: Update next.config
113 
114Wrap the existing config with `createNextIntlPlugin`:
115 
116```typescript
117import createNextIntlPlugin from 'next-intl/plugin'
118const withNextIntl = createNextIntlPlugin('./src/i18n/request.ts')
119 
120// ... existing config ...
121export default withNextIntl(nextConfig)
122```
123 
124## Step 6: Add `[locale]` Dynamic Route
125 
126Move all page content under `src/app/[locale]/`:
127 
1281. Create `src/app/[locale]/layout.tsx` with:
129 - `generateStaticParams()` returning all locales
130 - `setRequestLocale(locale)` call
131 - `<NextIntlClientProvider>` wrapping children
132 - `<html lang={locale} dir={rtlLocales.includes(locale) ? 'rtl' : 'ltr'}>`
133 - Hreflang `<link>` tags in `<head>` for all locales + `x-default`
134 
1352. Move existing pages into `src/app/[locale]/`
1363. Each page should call `setRequestLocale(locale)` for static generation
137 
138## Step 7: Extract Strings into Translation Files
139 
1401. Create `src/messages/en.json` with all user-facing strings organized by section:
141 ```json
142 {
143 "common": { "signIn": "Sign In", ... },
144 "tools": { "tool-slug": { "title": "...", "description": "..." } },
145 "faq": { "tool-slug": [{ "question": "...", "answer": "..." }] }
146 }
147 ```
148 
1492. Replace all hardcoded strings in components with `useTranslations()`:
150 ```typescript
151 const t = useTranslations('common')
152 return <button>{t('signIn')}</button>
153 ```
154 
1553. For server components, use `getTranslations()`:
156 ```typescript
157 const t = await getTranslations('common')
158 ```
159 
160## Step 8: Translate to All Locales
161 
162For each non-English locale, create `src/messages/{locale}.json` with the same structure as `en.json`.
163 
164### Translation Strategy
165 
166Use **parallel Codex agents** via the `codex-tasks` skill to save Claude credits:
167 
1681. Launch one Codex task per locale (up to 7 in parallel) using `/codex-tasks`
1692. Each task reads `en.json`, translates all strings, writes `{locale}.json`
1703. Codex prompt should include:
171 - The full `en.json` content (or path to read it)
172 - Target language name and locale code
173 - Instructions:
174 - Translate naturally, not literally
175 - Keep technical terms in English (PowerPoint, PDF, API, etc.)
176 - Preserve JSON structure exactly (same keys, same nesting)
177 - Preserve interpolation variables like `{count}`, `{name}` unchanged
178 - Write the result to `src/messages/{locale}.json`
1794. After Codex tasks complete, **verify the results** using the verification script below — Codex output quality varies and must be checked
180 
181### Verification
182 
183After translation, run a verification script to catch issues:
184 
185```python
186import json
187 
188locales = ['es', 'fr', 'de', 'pt', 'ja', 'ar', 'zh', 'zh-tw', 'id', 'vi', 'ms', 'ru', 'hi']
189english_words = ['the ', 'and ', 'you ', 'your ', 'our ', 'this ', 'that ', 'with ', 'from ', 'will ']
190 
191with open('src/messages/en.json') as f:
192 en = json.load(f)
193 
194for loc in locales:
195 with open(f'src/messages/{loc}.json') as f:
196 data = json.load(f)
197 
198 # Check: missing sections
199 missing = [s for s in en if s not in data]
200 
201 # Check: residual English content
202 eng_count = 0
203 def check(d):
204 nonlocal eng_count # won't work in inline script; use list trick
205 if isinstance(d, dict):
206 for v in d.values(): check(v)
207 elif isinstance(d, str):
208 if sum(1 for w in english_words if w in d.lower()) >= 3:
209 eng_count += 1
210 check(data)
211 
212 status = 'OK' if not missing and eng_count == 0 else 'ISSUES'
213 print(f'{loc}: {status} (missing={len(missing)}, english={eng_count})')
214```
215 
216## Step 9: Update Sitemap with Hreflang
217 
218Update `src/app/sitemap.ts` to include hreflang alternates:
219 
220```typescript
221import { MetadataRoute } from 'next'
222import { locales } from '@/i18n/config'
223 
224const baseUrl = 'https://www.example.com'
225 
226function buildAlternates(path: string): Record<string, string> {
227 const alternates: Record<string, string> = {}
228 for (const locale of locales) {
229 const prefix = locale === 'en' ? '' : `/${locale}`
230 alternates[locale] = `${baseUrl}${prefix}${path}`
231 }
232 return alternates
233}
234 
235export default function sitemap(): MetadataRoute.Sitemap {
236 return pages.map((path) => ({
237 url: `${baseUrl}${path}`,
238 lastModified: new Date(),
239 alternates: { languages: buildAlternates(path) },
240 }))
241}
242```
243 
244**Important**: Generate one canonical URL per page with hreflang alternates, NOT one URL per locale. This prevents duplicate content in search results.
245 
246## Step 10: Add Language Selector (Optional)
247 
248Add a language switcher component that uses `useRouter` and `usePathname` from `@/i18n/navigation` to switch locales while preserving the current path.
249 
250## Step 11: Verify
251 
2521. Build the project: `npm run build` — check that all static pages generate correctly
2532. Test English URLs have no prefix: `https://example.com/tools`
2543. Test locale URLs have prefix: `https://example.com/es/tools`
2554. Verify sitemap has hreflang alternates
2565. Check RTL rendering for Arabic
2576. Run the translation verification script from Step 8
258 
259## Common Pitfalls
260 
261- **`public/sitemap.xml`** conflicts with dynamic `src/app/sitemap.ts` in dev mode — delete the static one or rename it
262- **Middleware matcher** must exclude `_next`, `api`, `sitemap`, `robots`, and static asset paths
263- **`localePrefix: 'as-needed'`** is critical — it keeps default locale URLs clean for SEO continuity
264- **`localeDetection: false`** prevents unwanted redirects that break SEO and confuse users
265- **Large translation files** (5000+ lines per locale) can make git pushes fail — use `git config http.postBuffer 524288000`
266- **Verify translations thoroughly** — automated translation often produces mixed-language output; always verify with the English word detection script after Codex tasks complete
267 
268## Locale Count Reference
269 
270- 14 locales x N pages = 14N static pages at build time
271- Each locale JSON file is typically 2-5x the size of en.json (CJK characters, verbose languages)
272- Build time increases linearly with locale count
273 
View all files on GitHub →

Details

License
MIT
Stars on the repo
★ 705
Checked
Source
OpenClaudia/openclaudia-skills ↗
Creator
OpenClaudia · 78 listings
View creator

Similar skills

See all →
SkillBook Translatordeusyu/translate-book · by deusyuTranslate books (PDF/DOCX/EPUB) into any language using parallel sub-agents. Converts input -> Markdown chunks -> translated chunks -> HTML/DOCX/EPUB/PDF.★ 2.1k GitHub starsSkillArabic Marketing Copy Localizergrowthack88/growth-marketing-os · by growthack88Marketing copy localization skill that converts English marketing copy (ads, landing pages, emails, CTAs) into native Egyptian Arabic عامية — or GCC dialect on request — with natural English code-switching for business terms. Use whenever marketing copy needs an Arabic version, an Arabic draft "sounds translated", or a bilingual campaign is being built. Rebuilds meaning per line instead of translating words; never outputs فصحى for performance marketing contexts.★ 117 GitHub starsSkillMulti-Language TranslatorJimLiu/baoyu-skills · by JimLiuThis skill should be used when the user asks to "translate", "翻译", "精翻", "translate article", translate to Chinese", "translate to English", "改成中文", "改成英文", "convert to Chinese", localize", "本地化", "refined translation", "精细翻译", "proofread translation", "快速翻译", "快翻", 这篇文章翻译一下", or provides a URL/file with translation intent. Supports three modes (quick/normal/refined) with custom glossary support.★ 26.6k GitHub starsAgentDesign Implementation BridgeVoltAgent/awesome-claude-code-subagents · by VoltAgentUse this agent when you need to translate a DESIGN.md from the VoltAgent/awesome-design-md repository into polished Claude Code instructions for building user interfaces that faithfully match the chosen brand. Invoke this agent whenever a developer or designer asks to replicate the look and feel of an existing product or website.★ 25.2k GitHub starsSkillMultilingual Blog AuditorAgriciDaniel/claude-blog · by AgriciDanielAudit a directory of multilingual blog content for completeness, consistency, hreflang correctness, meta-tag parity, and freshness. Builds a translation coverage matrix, flags stale translations, validates hreflang and schema, and emits a prioritized report with runnable fix commands. Use when user says "locale audit", "blog locale-audit", "check translations", multilingual audit", "translation check", "hreflang check", Uebersetzungen pruefen".★ 2.2k GitHub starsSkillBlog Localization AdapterAgriciDaniel/claude-blog · by AgriciDanielDeep cultural adaptation of translated blog posts. Run after blog-translate completes. Goes beyond translation to swap brand examples, adapt CTAs, substitute legal references, localize statistic sources where possible, and adjust formality (Sie/du, tu/vous, formal/informal). Built-in profiles for DACH, Francophone, Hispanic, and Japanese markets. Use when user says "localize blog", "blog localize", "cultural adaptation", adapt for Germany", "lokalisieren", "localiser", "adaptar".★ 2.2k GitHub stars

More from OpenClaudia

SkillA/B Testing FrameworkOpenClaudia/openclaudia-skills · by OpenClaudiaDesign, plan, and analyze A/B tests with statistical rigor. Use when the user asks about A/B testing, split testing, experiment design, statistical significance, sample size calculation, test duration, multivariate testing, or conversion experiments. Trigger phrases include "A/B test", "split test", "experiment", "statistical significance", "sample size", "test duration", "which version wins", "conversion experiment", "hypothesis test", "variant testing".★ 705 GitHub starsSkillAffiliate Marketing ProgramOpenClaudia/openclaudia-skills · by OpenClaudiaBuild and manage an affiliate marketing program. Use when the user says "affiliate program", "affiliate marketing", "affiliate partners", "referral commissions", "affiliate network", "partner program", "affiliate tracking", or asks about creating, managing, or growing an affiliate or partner program.★ 705 GitHub starsSkillAhrefs API ManagerOpenClaudia/openclaudia-skills · by OpenClaudiaManages Ahrefs API usage in Python using `ahrefs-python` library. Use when working with SEO / marketing related tasks or with data including backlinks, keywords, domain ratings, organic traffic, site audits, rank tracking, and brand monitoring. Covers `ahrefs-python` usage including AhrefsClient / AsyncAhrefsClient, typed request/response models, error handling, and all API sections.★ 705 GitHub starsSkillAI Citations Report GeneratorOpenClaudia/openclaudia-skills · by OpenClaudiaGenerate an AI Citations Report (GEO) for a domain — which AI-search prompts cite the site across Google AI Overview and ChatGPT, plus organic-traffic context and per-article citation coverage. Use when the user asks for an 'AI citations report', 'GEO citations report', or 'which AI prompts cite <domain>'.★ 705 GitHub starsSkillB2B Lead EnricherOpenClaudia/openclaudia-skills · by OpenClaudiaResearch and enrich B2B leads using the Apollo.io API. Use when the user says "find leads", "prospect research", "company enrichment", "find decision makers", "B2B leads", "lead research", "enrich contacts", "find VP of marketing at", or asks about finding people at specific companies or in specific roles.★ 705 GitHub starsSkillBacklink Health CheckerOpenClaudia/openclaudia-skills · by OpenClaudiaAudit a domain's backlink profile using the SemRush API. Use when the user says "audit backlinks", "check my backlinks", "backlink analysis", "link profile", "toxic links", "disavow", "link building opportunities", "referring domains", "anchor text", or asks about a site's link authority.★ 705 GitHub stars