agentleFS
kostja94kostja94/openblog/AGENTS.md

openblog

AGENTS.md7 starsChanged 19 days agoMITView on GitHub

You are editing OpenBlog, an open-source, Git-based CMS for blogs — implemented as an agent-native blog module for product websites. Content lives in Git (Markdown + frontmatter); you maintain routes, theme, site chrome, and SEO primitives (sitemap, RSS, robots, JSON-LD) through the repo. For site-wide SEO, GEO, keyword strategy, and marketing-page optimization, use marketing-skills — OpenBlog only guarantees blog-path SEO primitives. Existing product site? Read INTEGRATION.md before editing chrome. When someone opens this repo without a clear task, ask which…

  • Installs packages
  • Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.

    Of the AGENTS.md files we read, the 31,700 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.

  • In this repository7 other files it gives its agents.

The file

We split this AGENTS.md into the rules it gives an agent

7 rules. About 0 are common, 3 are distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Existing product site?: Read INTEGRATION.md before editing chrome.

    line 5
  2. Distinctive:

    When someone opens this repo without a clear task, ask which path applies before editing files:

    line 9
  3. Very specific:

    Do not default to create-openblog if they mention an existing website, product URL, chrome, or navbar alignment.

    line 26
  4. Distinctive:

    Run validation before finishing:

    line 78
  5. Very specific:

    Do not put navbar/footer in packages/components

    line 118
  6. Very specific:

    Use repo skills in skills/ (install via skills/README.md or npx skills add kostja94/openblog --skill blog-cms):

    line 131
  7. Very specific:

    After changing theme in config (or running theme:infer):

    line 179

≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

AGENTS.md — OpenBlog

You are editing OpenBlog, an open-source, Git-based CMS for blogs — implemented as an agent-native blog module for product websites. Content lives in Git (Markdown + frontmatter); you maintain routes, theme, site chrome, and SEO primitives (sitemap, RSS, robots, JSON-LD) through the repo. For site-wide SEO, GEO, keyword strategy, and marketing-page optimization, use marketing-skills — OpenBlog only guarantees blog-path SEO primitives.

Existing product site? Read INTEGRATION.md before editing chrome.

Agent: route the user first

When someone opens this repo without a clear task, ask which path applies before editing files:

User situationPoint them toSkill
Has a product / marketing site — wants /blog, matching nav/logoINTEGRATION.mdblog-cms → integrate-product-site
Greenfield — new blog, local demo, no existing siteQuick start → scaffold (create-openblog)blog-cms → setup-blog-module
Module already wired — add or edit a postContent model in this filecreate-post (optional)
Pre-merge / deploy checks on blog postsValidate + buildvalidate-blog-seo
Ready to merge and deployGit → CI checklistpublish (optional)

Suggested prompt to show the user:

OpenBlog has two common paths:

  1. Existing product site → integrate /blog via INTEGRATION.md (recommended)
  2. Try it first → clone the repo, then npm run create-openblog -- my-blog (or npm install && npm run dev for a quick demo) Which applies to you? If you have a product site URL, share it.

Do not default to create-openblog if they mention an existing website, product URL, chrome, or navbar alignment.

Contributions: Upstream PRs to this repo are enterprise-only (design-token or component/platform partners). Do not encourage individual users to open PRs — point them to INTEGRATION.md, Issues, or CONTRIBUTING.md for enterprise partnership inquiries.

Architecture (v0.2)

Layers are decoupled under packages/. Users customize via openblog.config.ts at repo root.

LayerLocationCustomize via
Corepackages/coreschema, URL, SEO — rarely fork
Contentpackages/contentcontent.adapter + content.options
Componentspackages/componentscomponents.optional.* (Blog Chrome)
Themespackages/themestheme: + CSS import in globals.css
Site Chrometemplates/next/src/chrome/chrome.* in config + site-chrome.ts
Frontendtemplates/nextroutes, env, overrides

Existing product site? Read INTEGRATION.md before editing chrome.

Scope

  • In scope: openblog.config.ts, templates/next/content/blog/*.md, templates/next/src/chrome/, blog routes
  • Out of scope (v0): marketing landing pages, video posts, database CMS, scraping navbar from URLs

Content root

  • Posts: templates/next/content/blog/{slug}.md (default; see content.options.dir in config)
  • Filename must match frontmatter slug (kebab-case)
  • Article slugs page, category, and author are reserved for navigation routes.

Frontmatter schema

This section describes the current runtime schema. For author and taxonomy requirements, read the approved author and taxonomy contract.

Defined in @openblog/core (postFrontmatterSchema). Required fields:

title: string
description: string   # 80–320 chars, used for SEO meta
dek: string           # required, reader-facing article introduction
excerpt: string       # required, card / featured / RSS summary
slug: kebab-case
date: YYYY-MM-DD
authors: [author-id]  # ordered IDs from content/authors/{id}.json
categories: [category-id] # ordered, unique existing IDs from content/categories/{id}.json
articleType: guide     # optional; independent of categories, tags, featured status and layout
tags: string[]        # optional
draft: false         # optional, default false
updated: YYYY-MM-DD  # optional
cover: /images/...   # optional, featured image for OG (not body first image)

Run validation before finishing:

npm run validate:posts

This command also verifies local cover assets in public/ and their PNG social-image conversion. Local source files remain unchanged; published local covers produce a static /og.png under the article URL. External covers are not downloaded and are reported as unverified. See image behavior.

Author identities

Author profiles live in content/authors/{id}.json, beside the blog directory. Required profile fields are id, slug, name, and type (Person or Organization); optional fields are bio, avatar, experience, linkedin, and sameAs. Article authors is an ordered, unique list of existing IDs. Unknown references, duplicate page slugs, and filename/id mismatches fail validation. Names do not generate IDs or page URLs. The byline, author card, author page, RSS, sitemap, and Schema use the resolved profiles. Missing personal details must not be invented. Biography drafting and accounts are not implemented.

Article copy responsibilities

Categories live in content/categories/{id}.json, beside the blog directory, with required id, slug, name, intro (reader-facing), and description (SEO), plus optional parent referencing another category ID. Articles use an ordered, unique categories ID list; the singular category field is rejected. There is no separately maintained primary category. Names and page slugs come from the category records. Unknown references/parents, hierarchy cycles, duplicate slugs, and filename/id mismatches fail validation. A parent archive automatically includes descendant articles, deduplicated even when an article directly selects both parent and child. Only categories with published direct or descendant articles appear in the index, archive pages, and sitemap. Direct assignments drive article badges, RSS categories and articleSection; resolved ancestors drive hierarchy breadcrumbs, parent collections and their Schema. Tags remain non-link labels and article keywords, without independent archive URLs.

articleType is optional: tutorial, guide, case-study, opinion, product-introduction, announcement, comparison, or reference. Labels are defined once in ARTICLE_TYPE_LABELS and shared by UI and Schema genre. A missing type is not inferred. It does not select a layout, add a category, or create a type archive.

description is the SEO description, including article metadata and JSON-LD. dek is the reader-facing introduction; excerpt is the summary used in cards, featured collections, and RSS. All three fields are required and independently supplied. Reader copy does not require a marketing CTA.

Missing, blank, or non-text reader fields fail validation; consumers use their designated field directly. Do not substitute description, dek, or excerpt for one another or add legacy compatibility branches. Custom adapters must satisfy the same PostMeta contract. UI truncation does not change stored text or RSS content.

Publication validation also requires real YYYY-MM-DD dates (updated must not precede date), non-empty unique tags, and one authored FAQ section in each published article. FAQ questions use H3 headings or standalone bold question paragraphs ending in ?/?, each followed by a non-empty answer. Drafts may omit FAQ content; do not invent answers. The visible Markdown FAQ is also the source of FAQPage Schema. See current validation and Schema behavior.

validate:posts also checks references in published Markdown offline. Inline and reference-style local images/files resolve as browser URLs against the article URL and must exist inside public/, including symlink boundaries; local images use the image-integrity inspector. Managed blog links must resolve to published/enabled article, author, category, pagination or feed routes. Local fragments share the renderer's heading aliases; cross-article fragments must use actual rendered IDs such as #content-introduction, #faq-question or #article-faq. Missing files, broken managed routes, unsafe URLs and invalid article anchors fail validation. Empty image alt text and undefined explicit reference labels are warnings. Code examples are not scanned, external URLs are not fetched, and ordinary host-site pages outside the configured blog base are not validated. Diagnostics report body-relative lines, not frontmatter line numbers.

TLDR is authored only in an optional ## TL;DR Markdown section, not frontmatter. A present section must be non-empty and unique. components.optional.tldr controls separate presentation only: disabling it leaves the authored summary in the body. Do not substitute excerpt, dek, or description for missing summary content.

URL rules

  • Canonical URLs have no trailing slash
  • Blog and category archives use 12 articles per page. Page one uses the archive base URL; later pages use /page/{number}, have self-canonical metadata and page-specific CollectionPage Schema, and are included in the sitemap. Invalid/out-of-range page routes return 404. Featured content appears on the blog's first page only; published articles remain reachable through the complete paginated list.
  • Internal links in Markdown use paths from blogPath():
    • standalone / subdirectory: /blog/{slug}
    • subdomain: /{slug} (public URL; files still live under content/blog/)

Chrome integration

  • Site Chrome (navbar/footer/logo): openblog.config.ts → chrome, edit src/chrome/site-chrome.ts
  • Blog Chrome (breadcrumbs, article UI): packages/components + components.optional.*
  • Do not put navbar/footer in packages/components

Component SSOT: Bricks owns reusable component responsibilities and construction guidance. When a task requires a new or substantially redesigned named component, use its component-builder; OpenBlog owns the concrete runtime implementation and configuration. See the generated implementation mapping.

Do not break

  • DEPLOY_MODE behavior (see openblog.config.ts + env)
  • Static generation for all published slugs
  • Draft posts excluded from sitemap and RSS
  • OpenBlogProvider in root layout (components need site context)

Skills

Use repo skills in skills/ (install via skills/README.md or npx skills add kostja94/openblog --skill blog-cms):

SkillPurpose
blog-cmsEntry — route integrate vs scaffold
integrate-product-sitePrimary — mount blog on existing product site (chrome, patterns, npm run integrate)
setup-blog-modulePrimary — greenfield scaffold, config, env, theme, features, validate/build
create-postOptional — add post when user provides body/brief
validate-blog-seoOptional — blog module SEO validation (not site-wide audit); see marketing-skills for GEO/growth
publishOptional — PR merge and deploy checklist

Legacy: audit-seo redirects to validate-blog-seo.

X (Twitter) embeds

Optional component — not a features flag. Enable in openblog.config.ts:

components: {
  optional: {
    xEmbed: true,
  },
},

Paste a status URL on its own line in Markdown (or as a standalone link); inline links in a sentence stay plain links:

https://x.com/openblog/status/1234567890

Requires client-side load of platform.twitter.com/widgets.js. If the embed fails, readers get a fallback “View post on X” link.

Optional features

Taxonomy and feeds are toggled in openblog.config.ts → features (all default true):

FlagEffect when false
categoriesNo /blog/category/[slug] routes
tagstagsList UI and article Schema keywords off; no tag routes in either state
authorsNo author routes; author UI off
rssNo /blog/rss.xml feed

Core blog CMS (list + post pages, sitemap, validation) stays enabled regardless.

Theme sync

After changing theme in config (or running theme:infer):

npm run theme:sync   # writes templates/next/src/app/theme.generated.css

dev and build run theme:sync automatically. See docs/theming.md.

Commands

npm install          # from repo root (workspaces)
npm run dev          # http://localhost:3000/blog
npm run validate:posts
npm run theme:sync
npm run build
npm run check        # tests/contracts (monorepo), lint, validation, build, output verification
npm run check:full   # monorepo only: also test fresh standalone scaffold

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.