⚠️ Writing adjustments for 2C products
This skill defaults to dev/B2B readers. When writing 2C education/medical/finance (YMYL) content:
- Heavier E-E-A-T: requires verifiable author/reviewer credentials + a methodology transparency page; can't rely on a "team" byline alone (Google: Trust is the core of E-E-A-T).
- Dual-track topic selection: bonus keywords (policy/reform/new version) + long-tail high-conversion keywords (question types/scenarios/score bands).
- The numbers in the Key Stats table must have authoritative sources and be consistent throughout——YMYL categories must not be fabricated, otherwise ranking recovery is extremely difficult.
- Switch distribution channels to 2C communities/short video(Xiaohongshu/Reddit/TikTok/Naver 카페), rather than dev blogs.
For the full 2C channel database + public sources see → gingiris-seo-geo/references/2c-adaptation.md
gr-blog-post — Jekyll blog publishing
The articles produced must conform to
the 5 elements of the Iris style (see references/writing-voice-iris.md)
- Time-anchored opening —— don't say "SEO is important", say "2026-04-10, 3 a.m., backend traffic drops to zero"
- Parenthetical asides —— one sentence in the body, with personal commentary crammed into the parentheses ("...—— don't ask how I know")
- em-dash pivots —— don't use "but", use
—— - Key Stats table —— place a hard-data table, 3-5 rows, at the start of the article or in the first screen below the H2
- GEO direct-answer paragraph —— a 30-50 word paragraph at the top of the article that directly answers the main question, making it easy for AI crawlers to extract
Technical frontmatter template
---
layout: post
title: "主关键词前置,副标题用冒号:不超过 60 字"
date: 2026-04-15 14:30:00 +0800
categories: [seo, growth]
tags: [...]
canonical_url: https://gingiris.tools/blog/2026/04/15/slug/
hreflang_ja: /blog/2026/04/15/slug-ja/
hreflang_ko: /blog/2026/04/15/slug-ko/
post_description: "150-160 字 meta description,含主关键词"
faq:
- q: "直接问句"
a: "30-50 字硬答案"
---
Publishing process
1. Topic selection
- Read
gr-seo-patroloutput, find keywords that are "top 30 but not top 10" - Or read
gr-competitor, find new competitor tactics - ❌ Don't do duplicate topics (first
site:check whether the site already has one)
2. Write the first draft
- Time-anchored opening (current date + specific scenario)
- First screen: GEO direct-answer paragraph (30-50 words) + Key Stats table (hard data)
- H2 structure: problem → framework → case study → pitfalls → next steps
- 200-400 words under each H2, no more than 600 words
3. Internal links
- Backward: link to 2-3 published articles on the same topic (using the main keyword as the anchor)
- Forward: site index / hub pages
- Link equity flow: add internal links from the 3 highest-traffic articles to the new article
4. FAQ Schema
- 3-5 Q&As
- The questions must be real user search queries (pulled from GSC / People also ask)
- Answers must be hard, short, and quotable
5. Canonical strategy
- Default to self-canonical
- If it's a split section of a same-topic series → canonical points to the master
- ja/ko translated versions → self-canonical + hreflang mutual references
6. Multilingual sync
- Use
scripts/sync-i18n.py(roadmap) to automatically produce Japanese and Korean drafts from English - Go through it manually (machine translation rough spots + cultural adaptation)
- JA/KO versions use independent slugs, do not reuse the EN slug
7. Publishing (executable checklist)
Target repo:Gingiris-1031/growth-tools(real site gingiris.tools, Vercel deployment origin/main, auto-builds in ~50-90s after writing)
⚠️ Prerequisite: first pass the Gingiris-1031 GitHub security rules(memory gingiris_1031_safety_rules.md,P0):
- Commit identity =
Iris Wei <iris.wei@gingiris.com>(not the machine name/local hostname) - Single-line commit message:
post: {slug} ({lang})——no Claude trailer, no multi-paragraph body - No burst: merge into 1 commit whenever possible; >10 commits/hour = stop and re-sequence
Publish = GitHub Contents API PUT(do not use local git push):
# token 只从 secrets.env 读,绝不内联/硬编码进脚本或 SKILL.md
source ~/.config/gingiris/secrets.env # 提供 GITHUB_PAT
SLUG="your-post-slug"; LANG="en"
FILE="_posts/$(date +%F)-${SLUG}.md"
curl -s -X PUT \
-H "Authorization: Bearer $GITHUB_PAT" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/Gingiris-1031/growth-tools/contents/${FILE}" \
-d "{\"message\":\"post: ${SLUG} (${LANG})\",
\"content\":\"$(base64 < draft.md | tr -d '\n')\",
\"committer\":{\"name\":\"Iris Wei\",\"email\":\"iris.wei@gingiris.com\"}}"
Updating an existing file: first
GET .../contents/{path}to getsha, add"sha":"..."to the PUT body.
Post-publish verification (only counts as done if all pass in order):
- Wait for the Vercel deployment to finish (~50-90s; can
curl -sI https://gingiris.tools/to confirm the site is live) -
curl -sI https://gingiris.tools/blog/{yyyy}/{mm}/{dd}/{slug}/→ HTTP 200(404 = permalink/date/future: truemisconfigured, fix it before continuing) - GSC manual Request Indexing (URL Inspection → Request Indexing; new domains crawl slowly, this step cannot be skipped)
- IndexNow push to Bing (LLM discover mostly goes through the Bing index, see
gr-geo-cite)
hreflang acceptance checklist (mandatory when publishing ja/ko versions or adding translations)
Background: the i18n baseline once had several hreflang bugs (KO self-loop, JA→EN pointing to
/en/homepage weak link, EN missing alternate), the consequence was JA/KO indexing stuck at 0 for a long time (memoryi18n_baseline.md). After the site-wide fix commit b667208 spot checks were all green——new articles must not add the bugs back。
- EN/JA/KO frontmatter cross-referencing:
hreflang_ja/hreflang_ko/hreflang_enpoints tothe specific counterpart article(never point to the/en/homepage) - Each page emits a self-referencing hreflang (the ko page must have
hreflang="ko"pointing to itself, a self-pointinghreflang="ja") -
x-defaultexists and points to the EN version - Each page is self-canonical (ja/ko do not canonical to EN; with trailing slash, consistent with sitemap)
- Post-publish curl spot check:
for u in "$EN_URL" "$JA_URL" "$KO_URL"; do
echo "== $u"
curl -s "$u" | grep -oE '<link rel="(alternate|canonical)"[^>]*>'
done
# 验收:每页 hreflang 完整(self + 对端 + x-default)且三页双向回链成对,canonical 自指
8. 24h after publishing
- Add to the
gr-seo-patrolmonitoring list - Social platform distribution (Twitter / LinkedIn / dev.to, via
gr-social-distill)
dev.to secondary publishing rules (⚠️ canonical red line)
- ✅ A dev.to article's canonical_url must point to dev.to itself(self-canonical), never point to gingiris.tools
- Correct:
canonical_url: https://dev.to/iris1031/article-slug-xxxx - Wrong:
canonical_url: https://gingiris.tools/blog/...(this makes Google treat the dev.to article as a duplicate, excluded from SERP)
- Correct:
- ✅ Publishing time gap ≥7 days(do not publish on the same day as gingiris.tools)
- ✅ Add "Originally published at gingiris.tools" at the end to establish a two-way reference
- ❌ Do not copy canonical_url directly from the Jekyll frontmatter to dev.to, that is the gingiris.tools address
Anti-patterns
- ❌ Do not use heavily AI-flavored templates ("In today's digital landscape...")—— before publishing run
skills/gr-geo-cite/scripts/citability-scorer.py, only pass if the page score is ≥ 75 - ❌ Do not stuff keywords into H1
- ❌ Do not forget hreflang —— when adding translations to already-published old articles, go back and edit the original frontmatter
- ❌ Do not publish 3 articles for the same keyword —— cannibalization will come knocking immediately
- ❌ dev.to canonical points to gingiris.tools — dead link or duplicate issue, always self-canonical
Cascading recommendations
- After writing →
gr-seo-patroladd monitoring - Found it's a series draft →
gr-blog-postcontinue producing post 2 and set canonical - 24h after English publish → manually trigger Japanese/Korean translation
API dependencies
| Service | Env var | Source |
|---|---|---|
| GitHub PAT | GITHUB_PAT |
~/.config/gingiris/secrets.env(used after source, not inlined) |
| DeepSeek / Teamo (translation) | DEEPSEEK_API_KEY / TEAMOROUTER_API_KEY |
Same as above |
Citability-by-Design Spec (mandatory for NEW articles, 2026-05-18+)
Rationale: Verified 2026-05-07 that retrofitting old articles hits a ~65-68/100 citability ceiling no matter what (booster passages, surgical rewrites, splitting all produce diminishing returns). Writing new articles from this spec produces 75-85 baseline directly. Spec saves ~3 hours of post-hoc citability fixing per article.
Per-section structural requirements
Every H2/H3 section must satisfy ALL of:
-
Word count: 134-167 (the AI-extraction sweet spot validated by zubair-trabzada/geo-seo-claude scoring)
- Under 134 → self_containment drops below 10/25
- Over 167 → same penalty for being too long for AI chunks
- Use a word counter as you draft
-
Opening sentence = definition pattern, one of:
[Thing] is [definition][Thing] refers to [scope][Thing] means [unpacking]In other words, [Thing] is...[Thing] can be defined as...
-
Section contains at least ONE of each:
- ✅ Original research signal: "Our X-launch dataset", "We tracked", "Our 2026 audit measured", "Our analysis of N samples"
- ✅ Specific number with unit: "60K stars", "30 launches", "$79/mo", "67%"
- ✅ Specific named product/tool: "Taplio ($39/mo)", "Surfe", "PH Deck", "Loom" — by name not "[the tool]"
Heading conventions
-
H1 = page title (≤ 70 chars after title-suffix fix from 2026-05-07)
-
H2 should be question form ~40% of the time:
- ✅ "How do I get cited by Perplexity in 2026?"
- ✅ "What is the GEO three-piece set?"
- ❌ "Perplexity citation strategy"
-
Each H2 should contain primary keyword or clear question intent
Article-level requirements
- 5-12 H2 sections (sweet spot: 7-8)
- TL;DR or "Citable Statistics" block IN FIRST H2 (becomes top-scored passage)
- FAQ Schema JSON-LD at end (5+ Q&A using exact User-Search-Form questions)
last_modified_at:frontmatter (flows through to dateModified schema)- canonical_url self-reference
- hreflang_ja / hreflang_ko if multilingual variants exist
Citability self-check before publishing
Run before committing the article:
# 兼容两种安装位置:优先 monorepo 相对路径,fallback 本机安装
SCORER="skills/gr-geo-cite/scripts/citability-scorer.py"
[ -f "$SCORER" ] || SCORER="$HOME/.claude/skills/gr-geo-cite/scripts/citability-scorer.py"
python3 "$SCORER" --file /local/path/to/draft.html
Target: page score ≥ 75. If under 70, revise top 2 weakest passages.
Anti-patterns (avoid)
- ❌ Long expository paragraphs (200+ words) — split into 2 sections at 134-167 each
- ❌ Generic transitions ("Now let's discuss...") — replace with definition pattern
- ❌ Marketing fluff ("the best way to") — replace with measured claims with data
- ❌ "[Tool name]" placeholders — always cite the specific tool by name + price
- ❌ Bullet lists with single words — combine into prose with definition + example pattern
Real-data benchmark
Articles from 2026-05-07 audit (without this spec):
| Article (old, retrofit) | Score | Pattern |
|---|---|---|
| PH playbook master | 65 | Top passage 74, dragged by 62s |
| Social listening | 68 | Best of the 5 (early Citable Stats) |
| Community directory | 62 | Lifted from 54 via booster (+12% from 0 to 1 sweet-spot passage) |
Predicted from spec (NEW articles):
| Spec compliance | Predicted score |
|---|---|
| All sections 134-167 + definition pattern + 1 original signal | 78-85 |
| 80% sections compliant, 20% legacy structure | 72-77 |
| 50% compliant | 65-70 (same as retrofit ceiling) |
The marginal value of strict compliance is ~10 points vs partial compliance.