README Standards — Esposter

SkillDev tools

Esposter README conventions — the anchor+emoji heading template, the published-vs-private split that drives the badges, the typedoc module-page URL and scoped-name slug mangling that drive the docs link, when Getting Started is omitted, reading published-vs-private off each manifest rather than a list, the two package inventories (AGENTS.md and the root README table) that are edited together, GitHub blob/tree URL rules, and a Settled list of the directions already rejected (making a README diagram interactive with markup, a second copy of the workspace graph as a dark `<picture>` variant or a hosted duplicate, and re-emitting that graph as a mermaid fence for GitHub's pan/zoom, and dropping the `<a name>` wrapper to collapse the two anchors an emoji heading answers to). Apply when creating or updating any README.md in this monorepo, including the root one.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the README Standards — Esposter skill

What this skill tells your AI

The instructions your AI receives, as published by esposter/esposter in .agents/skills/readme-standards/SKILL.md and read by ahel’s review.

Settled — do not re-propose

  • Making a README diagram interactive with markup. GitHub sanitises rendered markdown — <script>, <iframe>, <object>/<embed> and inline <svg> are stripped, and an svg behind an <img> renders isolated, so its own scripts and anchors are dead. Pan/zoom in a README is therefore never a markup question: it exists only for the formats GitHub renders itself, which is why a repo whose diagram zooms has a mermaid fence — GitHub draws those in an iframe and supplies the pan/zoom widget. The most an image can offer is a link to a larger rendering, which the workspace graph already does.
  • A second copy of the workspace graph — a <picture> dark variant, a hosted copy under apps/web/public/, anything paired with the committed svg. One artifact is the design, not an omission: bgcolor="transparent" plus a palette whose every fill, border and neutral was measured against both a white and a near-black page (scripts/src/dependencyGraph/constants.ts, PackageRoleColorsMap.ts) is what makes the single file correct in either colour scheme.
  • Dropping the <a name> wrapper so a heading has one anchor. Every heading here answers to two: the explicit name the ToC links (#local-development), and the id GitHub derives from the rendered text, which strips the emoji without trimming the space it left behind and so carries a leading hyphen (#-local-development) — that second one is what the hover permalink copies, so a link pasted from the UI and a link from the ToC differ. Both resolve, and the split is the price of the emoji rather than a fault in the template. Removing the wrapper would move every ToC link onto the hyphenated slug, which is an artifact of one renderer's slugger and not a name anything declares — where the explicit name says what it is and reads the same in every renderer that honours it. Dropping the emoji instead buys the clean slug by deleting the thing the heading template exists for. It stays as it is.
  • Re-emitting the workspace graph as a mermaid fence to collect GitHub's pan/zoom. It costs the dot layout and with it the runtime-edge weighting that ranks the picture by what the repo ships, the box3d fold, its shadow pass and the two-stop fills — and the root README is typedoc's index page, where a fence is a code block rather than a diagram. The zoom is worth less than the picture it degrades.

Template

Headings use the anchor+emoji form and a --- rule closes the ToC — the ToC links the explicit name, not the hyphen-prefixed slug GitHub derives from the emoji (see Settled). Copy the shape from a sibling README:

# <npm-name>

[badges — see Badge Rules]

One-sentence description (from package.json `description`, expanded for clarity).

## Table of Contents

- 🚀 [Getting Started](#getting-started) ← omit when the package has no install/run step
- 📖 [Documentation](#documentation)
- ⚖️ [License](#license)

---

## <a name="getting-started">🚀 Getting Started</a>

(install command + minimal working example)

## <a name="documentation">📖 Documentation</a>

We highly recommend you take a look at the [documentation](<see rule 3>) to level up.
Key exports table / usage examples / architecture notes

## <a name="license">⚖️ License</a>

Apache-2.0 reference + badge refs at the bottom

Badge Rules

Published packages (no "private": true) — include all four:

[![Apache-2.0 licensed][badge-license]][url-license]
[![NPM version][badge-npm-version]][url-npm]
[![NPM downloads][badge-npm-downloads]][url-npm]
[![NPM Unpacked Size (with version)][badge-npm-unpacked-size]][url-npm]

Private packages — license badge only:

[![Apache-2.0 licensed][badge-license]][url-license]

Badge ref format (bottom of file):

[badge-license]: https://img.shields.io/github/license/Esposter/Esposter.svg?color=blue
[url-license]: https://github.com/Esposter/Esposter/blob/main/LICENSE
[badge-npm-version]: https://img.shields.io/npm/v/<npm-name>/latest?color=brightgreen
[url-npm]: https://www.npmjs.com/package/<npm-name>/v/latest
[badge-npm-unpacked-size]: https://img.shields.io/npm/unpacked-size/<npm-name>/latest?label=npm
[badge-npm-downloads]: https://img.shields.io/npm/dm/<npm-name>.svg

Which packages, and which are published

Every package carries a README.md at its own root. Whether it is published is private in its package.json, and its npm name is that manifest's name — both read from the source rather than from a list here, which would rot the first time a package is added. AGENTS.md carries the inventory with a description per package, the one thing the tree cannot answer.

Two lists exist on purpose and are edited together: AGENTS.md pairs each path with its npm name for an agent resolving an import, and the root README's package table pairs each path with a repository link and a published mark for a reader arriving from npm or GitHub. Neither is the other's copy — but adding, removing or renaming a package changes both, and nothing checks that it did.

Content Rules

  1. Description — lead with what it does, not what it is. "Drizzle ORM schemas and migrations" beats "A library of database schemas".

  2. Getting Started — install command + one minimal working example. Omit when the package is neither installed nor run directly — that's every private library package (configuration, db, db-mock, db-schema, shared-node, azure-functions, infra), which jump straight to Documentation and carry an Architecture / How It Works section instead. apps/web is private but keeps a Getting Started: it's a runnable app with a real dev setup.

  3. Documentation — always the sentence "We highly recommend you take a look at the documentation to level up." The link target is the package's typedoc module page, at https://esposter.com/docs/api/modules/<slug>.html. The /api segment is not optional: typedoc's out is apps/web/public/docs/api, so /docs/ alone is the in-app docs site and /docs/modules/… 404s.

    • Slug — typedoc mangles a scoped name (@esposter/foo_esposter_foo); an unscoped name is literal (foofoo). Never spell the slug from the npm name by hand — read it from apps/web/public/docs/api/modules/.
    • Which packages have a page — every package not in typedoc's exclude list (typedoc.config.js), which is the app and the configuration package. This has nothing to do with the published/private split: a private package still gets a module page. Those two, and the root README, link the docs site root https://esposter.com/docs instead.

    Either way add a key-exports table or architecture notes so the README is useful without the docs site.

  4. Commands — list the package's own pnpm scripts (build, test, lint:fix, typecheck), not root scripts.

  5. No filler — skip "we are excited to…", lengthy prose, or content that duplicates CLAUDE.md. READMEs are reference docs.

  6. Root README — keep the Packages table in sync when adding/removing packages. Columns: Package (link), Description, Published (✓ or —).

  7. GitHub URL conventionblob/main for files, tree/main for directories (e.g. .../tree/main/packages/shared vs .../blob/main/LICENSE). Never use relative paths — typedoc resolves them as local media and warns if they resolve to directories.

Signals

GitHub stars
23
Forks
3
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
readme-standards
Source
github.com/esposter/esposter