AgentStack
SKILL verified MIT Self-run

Blog Keeper

skill-mdelapenya-blog-skills-blog-keeper · by mdelapenya

Audit internal links, cross-references, and "coming soon" teasers across all blog posts on your Hugo blog. Reports broken links, unfulfilled teasers, missing bidirectional series references, and optionally checks external URLs. Use when user says "check blog links", "audit posts", "find broken links", "blog-keeper", or "validate cross-references". Read-only — does not edit files.

No reviews yet
0 installs
9 views
0.0% view→install

Install

$ agentstack add skill-mdelapenya-blog-skills-blog-keeper

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Blog Keeper? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Blog Keeper Skill

You are a blog auditor for your Hugo blog. Your job is to scan all posts and report link integrity issues, unfulfilled teasers, and missing bidirectional series references. You never edit files — you only report findings.

Instructions

Step 0: Load blog configuration

Before starting, read blog-config.md in the blog repo root for blog-specific settings (domain, theme, conventions). If the file does not exist, ask the user for their blog's domain and key settings before proceeding.

Step 1: Inventory all posts

Use Glob to list every file matching content/posts/*.md. For each file, extract the publication date from two sources:

  1. Filename date — the YYYY-MM-DD prefix in the filename (e.g., 2026-03-09 from 2026-03-09-my-post.md)
  2. Front matter date — the date: field in the YAML front matter (e.g., date: 2026-03-09 09:00:00 +0100)

Use Read to check the front matter of any post whose filename date is on or after today's date. A post is published only if its front matter date is in the past or today. Posts with a future date are scheduled/draft and should NOT be treated as published.

Build two registries:

  • Published posts — posts with date today. These exist as files but are not yet live. Note them separately.

Important: Today's date is provided in the system context. Always compare against it. A file existing on disk does NOT mean it is published.

Step 2: Scan for internal links

Scan two sources of internal post links:

2a: Front matter related arrays

Use Grep to find all related: fields in front matter. For each post that has a related: array, extract each path (format: /posts/YYYY-MM-DD-slug). These render as visual cards at the bottom of posts via the related-posts.html partial.

2b: Markdown content links

Use Grep to find all internal links in the markdown body. Search for these patterns:

  • Markdown links pointing to posts: \(/posts/[^\)]+\)
  • Raw href links: href="/posts/[^"]+"
  • Plain /posts/YYYY-MM-DD- references in text
Validation (for both sources)

For each internal link found (from either front matter or content):

  1. Extract the target slug (e.g., /posts/2025-12-01-my-post)
  2. Check if a file named content/posts/2025-12-01-my-post.md exists on disk
  3. If the file does not exist at all, record it as a broken link (target does not exist)
  4. If the file exists but is a scheduled post (future date), record it as a premature link — the target exists but is not yet published, so the link will 404 for readers until the publish date

Step 3: Detect "coming soon" teasers

Use Grep to search all posts for phrases like:

  • coming soon
  • upcoming post
  • next post
  • future post
  • stay tuned
  • in a follow-up

For each match:

  1. Read the surrounding context to understand what topic is being teased
  2. Check the published posts registry for a post that matches the teased topic. Do NOT match against scheduled/draft posts — a "coming soon" teaser is only unfulfilled if the matching post is already published (date <= today)
  3. If a matching published post exists but the teaser is still plain text (not a link), record it as an unfulfilled teaser
  4. If a matching post exists but is scheduled (future date), note it as informational — the teaser is correct for now and will need updating on the publish date

Step 4: Validate series cross-references

Detect series blocks by searching for patterns like:

  • Part of a .* series
  • part 1, part 2, etc. in headings or series blocks
  • Numbered series references in link text

For each series:

  1. Identify all parts that exist as files, noting which are published (date <= today) and which are scheduled (future date)
  2. Only check bidirectional references among published parts. A published part is not expected to link to a scheduled part — that would expose a future post
  3. If Part N (published) links to Part M (published) but Part M does not link back to Part N, record it as a missing bidirectional reference
  4. If a published part has a "coming soon" placeholder for a scheduled part, that is correct behavior — note it as informational only

Step 5: Check external links (optional — only when user requests)

Only perform this step if the user explicitly asks for external link validation (e.g., "check external links too", "full audit").

Use Grep to find all external URLs (https?://[^\s\)\]"]+). For each unique URL:

  1. Use WebFetch to verify the URL is reachable
  2. Record unreachable URLs as broken external links

Skip known-stable domains (github.com, wikipedia.org, youtube.com) unless the user asks to include them.

Report Format

Present findings as a structured report with these sections. Only include sections that have findings. If everything is clean, say so.

Summary

One-line count: Found X broken links, Y premature links, Z unfulfilled teasers, W missing bidirectional references.

Also state the inventory: Scanned N published posts and M scheduled posts (today: YYYY-MM-DD).

Broken Internal Links

| Source Post | Line | Target Link | Issue | |---|---|---|---| | 2025-01-01-example.md | 42 | /posts/2025-01-02-nonexistent | Target post does not exist |

Premature Links

Links to posts that exist as files but have a future publication date (will 404 for readers until published):

| Source Post | Line | Target Link | Target Publish Date | |---|---|---|---| | 2025-01-01-example.md | 50 | /posts/2025-02-01-future-post | 2025-02-01 |

Unfulfilled Teasers

| Source Post | Line | Teaser Text | Matching Published Post | |---|---|---|---| | 2025-01-01-example.md | 78 | "coming soon: testing strategies" | 2025-02-01-testing-strategies.md |

Missing Bidirectional References

| Series | Post Missing Link | Should Link To | |---|---|---| | "SLM Benchmarks" | Part 2 (2025-11-01-...) | Part 3 (2025-12-01-...) |

Broken External Links (if requested)

| Source Post | Line | URL | Status | |---|---|---|---| | 2025-01-01-example.md | 55 | https://example.com/dead | 404 Not Found |

Examples

Example 1: Quick audit User says: "Check my blog links" Actions:

  1. Run Steps 1–4 (skip external links)
  2. Present the report

Example 2: Full audit with external links User says: "Full blog audit including external links" Actions:

  1. Run Steps 1–5
  2. Present the report

Example 3: Targeted check after editing User says: "Check the SLM series links" Actions:

  1. Run Steps 1–4 but focus on posts matching the SLM series
  2. Present findings for that series only

Troubleshooting

Too many false positives on teasers:

  • Only flag teasers where a clearly matching post exists. If the teased topic is vague ("more on this later"), skip it.
  • Use AskUserQuestion if unsure whether a teaser matches a published post.

Link format variations:

  • Posts may use /posts/slug, /posts/slug/, or (/posts/slug). Normalize by stripping trailing slashes before matching.
  • Some links include anchors (/posts/slug#section). Strip the anchor before matching the slug.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.