Skip to content

How it works

merged PRs ──► shipdot draft ──► PR with draft entries ──► human review & merge
│
.shipdot/entries/*.md ◄──┘
│
shipdot build
│
┌────────────────────────────┼─────────────────────────┐
▼ ▼ ▼
shipdot.json llms.txt llms-full.txt
│
<ship-dot src="/shipdot.json">
│
bell + unread badge, feed panel, hotspots on target elements
  1. You merge pull requests as usual. Optionally, authors describe the change for users in a ### shipdot section of the PR description.
  2. shipdot draft (locally or in the GitHub Action) lists PRs merged since the last tag, skips the ones users will not notice, and writes one Markdown entry per PR. With an LLM key it can also rewrite and translate them.
  3. A human reviews the drafts in a pull request: fix the wording, add a target for a hotspot, merge.
  4. shipdot build validates the entries and compiles them into a static shipdot.json. HTML is sanitized here, with a strict allowlist, so the widget never has to.
  5. <ship-dot> fetches shipdot.json, compares entry IDs with the ones stored in localStorage, shows the unread count, and puts hotspots on the elements that unread entries point at.

There is no server, database, account or tracking. Deploy shipdot.json with the rest of your static files.

The reasoning behind these choices lives in the architecture decision records: