Vibecode Headway
track this build5 phases, 10 steps, beginner friendly0%A changelog is Markdown entries rendered to a page and an RSS feed, plus a badge that knows the last entry the user saw. That is a sitting. The $29 is for the custom domain and removing the badge, which you get for free by owning it.
You are building a lean indie version of Headway. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # Headway · indie build A changelog page and a what's-new widget: Markdown entries rendered to a static page and RSS, a badge that knows the last entry a visitor saw, and a script that posts new entries to Slack. One of the smallest real products on the list and a good first build. Estimated effort: **one sitting**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Build | A Node script rendering Markdown | static, no server | | Widget | One vanilla-JS file under 3 KB | drops into any page | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Everything in this build runs on it: the server, the scripts, the tests. - Get it: Download the LTS installer from nodejs.org, or install with your package manager (brew install node, or nvm install 22). Restart the terminal afterwards. - Verify: node --version prints v22 or higher - [ ] **A terminal and a code editor** · free - Why: Every step below is a command you type or a file you edit. - Get it: VS Code (code.visualstudio.com), Cursor or Zed. Open a folder for the project and use the editor's built-in terminal. - Verify: You can open a folder and run a command in its terminal - [ ] **Git** · free - Why: History for your code, and the way most hosts deploy. - Get it: Install from git-scm.com or with your package manager, then run git init in the project folder once it exists. - Verify: git --version prints a version - [ ] **A static host, or your existing site** · free - Why: The changelog is static files. - Get it: Cloudflare Pages, Netlify, or a folder in your current site. - [ ] **A Slack incoming webhook (optional)** (optional) · free - Why: Phase 4 posts new entries. - Get it: api.slack.com/apps > Incoming Webhooks. ## Quick start ```sh mkdir changelog && cd changelog && git init && npm init -y && npm pkg set type=module && npm install markdown-it@14 gray-matter@4 mkdir -p changelog public && cp .env.example .env ``` Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - The hosted editor and reaction analytics. - the hosted editor - Slack and Twitter auto-posting - reaction analytics - private changelogs behind their auth If one of those is essential to you, that is the reason to keep paying for Headway, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Headway The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a changelog page and a "what's new" widget like Headway. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Markdown entries in a folder, a Node build script rendering static HTML and RSS, and one vanilla-JS widget under 3 kB. No framework, no server. ### Data model (create this before Phase 1) changelog/YYYY-MM-DD-slug.md with frontmatter: title, date, category (new | improved | fixed), and the body. ### Phase 1 · The page Build: build.mjs renders /changelog/index.html newest first with category labels, and /changelog/feed.xml. A missing frontmatter field fails the build naming the file. Done when: adding an entry and rebuilding shows it first and the feed validates. Do not build yet: the widget. ### Phase 2 · The widget Build: widget.js reads /changelog/latest.json (written by the build with the newest date and count) and shows a small badge on an element you mark with data-changelog; clicking opens a panel listing the last five entries; the badge clears by storing the seen date in localStorage wrapped in try/catch. Done when: a new entry makes the badge appear on next load, opening the panel clears it, and the page works with the widget blocked. ### Phase 3 · Design Build: a readable timeline layout, category colors, dark mode, and the panel styled to inherit the host page font. Done when: no contrast failures in either scheme and the panel does not leak styles into the host page. ### Phase 4 · Distribution Build: a script that posts a new entry to a Slack webhook and a Bluesky or X account (optional keys in .env) on publish. Done when: a new entry appears in Slack within a minute of the build. ### Phase 5 · Deploy Build: the host config on your domain, the README. Done when: an entry goes from Markdown to live with one command. ### Out of scope (and why) - The hosted editor and reaction analytics. The PR is the editor here. ### README must contain - The frontmatter reference. - The one-line embed for the widget. ===== AGENTS.md ===== # Agent instructions · Headway indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A Node script rendering Markdown, One vanilla-JS file under 3 KB. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ===== BUILD_PLAN.md ===== # Build plan · Headway A changelog page and a what's-new widget: Markdown entries rendered to a static page and RSS, a badge that knows the last entry a visitor saw, and a script that posts new entries to Slack. One of the smallest real products on the list and a good first build. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · The page Entries rendered newest first with categories; a validating build; RSS. ### Steps 1. changelog/YYYY-MM-DD-slug.md with frontmatter (title, date, category) and build.mjs ```sh mkdir changelog && cd changelog && git init && npm init -y && npm pkg set type=module && npm install markdown-it@14 gray-matter@4 mkdir -p changelog public && cp .env.example .env ``` 2. Render index.html and feed.xml; fail on a missing field naming the file ### Done when - [ ] Adding an entry and rebuilding shows it first - [ ] The feed validates - [ ] A missing field fails the build ## Phase 2 · The widget A badge from latest.json cleared by opening the panel. ### Steps 1. The build writes latest.json with newest date and count; widget.js shows a badge on data-changelog 2. A panel listing the last five entries; localStorage for the seen date in try/catch ### Done when - [ ] A new entry makes the badge appear - [ ] Opening the panel clears it - [ ] The page works with the widget blocked ## Phase 3 · Design A timeline, category colours, dark mode, no style leaks. ### Steps 1. Timeline layout and category colours with dark mode 2. Scope the widget's styles so nothing leaks into the host page ### Done when - [ ] No contrast failures - [ ] The panel does not alter host page styles ## Phase 4 · Distribution Slack on publish. ### Steps 1. A publish script posting a new entry to SLACK_WEBHOOK_URL 2. Guard against re-posting an entry already announced ### Done when - [ ] A new entry appears in Slack within a minute - [ ] A rebuild does not re-post ## Phase 5 · Deploy One command from Markdown to live; README. ### Steps 1. Host config on your domain 2. README: frontmatter reference and the one-line embed Files: `README.md` ### Done when - [ ] An entry goes from Markdown to live with one command ## Not in this build - The hosted editor and reaction analytics. ## After v1, if you want it - Email digests of entries - Reactions stored in a tiny endpoint ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Public base of the changelog. SITE_URL=https://yourdomain.com/changelog # Optional · secret. For the publish script. Empty disables it. SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
You are building a lean indie version of Headway. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # Headway · indie build A changelog page and a what's-new widget: Markdown entries rendered to a static page and RSS, a badge that knows the last entry a visitor saw, and a script that posts new entries to Slack. One of the smallest real products on the list and a good first build. Estimated effort: **one sitting**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Build | A Node script rendering Markdown | static, no server | | Widget | One vanilla-JS file under 3 KB | drops into any page | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Everything in this build runs on it: the server, the scripts, the tests. - Get it: Download the LTS installer from nodejs.org, or install with your package manager (brew install node, or nvm install 22). Restart the terminal afterwards. - Verify: node --version prints v22 or higher - [ ] **A terminal and a code editor** · free - Why: Every step below is a command you type or a file you edit. - Get it: VS Code (code.visualstudio.com), Cursor or Zed. Open a folder for the project and use the editor's built-in terminal. - Verify: You can open a folder and run a command in its terminal - [ ] **Git** · free - Why: History for your code, and the way most hosts deploy. - Get it: Install from git-scm.com or with your package manager, then run git init in the project folder once it exists. - Verify: git --version prints a version - [ ] **A static host, or your existing site** · free - Why: The changelog is static files. - Get it: Cloudflare Pages, Netlify, or a folder in your current site. - [ ] **A Slack incoming webhook (optional)** (optional) · free - Why: Phase 4 posts new entries. - Get it: api.slack.com/apps > Incoming Webhooks. ## Quick start ```sh mkdir changelog && cd changelog && git init && npm init -y && npm pkg set type=module && npm install markdown-it@14 gray-matter@4 mkdir -p changelog public && cp .env.example .env ``` Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - The hosted editor and reaction analytics. - the hosted editor - Slack and Twitter auto-posting - reaction analytics - private changelogs behind their auth If one of those is essential to you, that is the reason to keep paying for Headway, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Headway The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a changelog page and a "what's new" widget like Headway. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Markdown entries in a folder, a Node build script rendering static HTML and RSS, and one vanilla-JS widget under 3 kB. No framework, no server. ### Data model (create this before Phase 1) changelog/YYYY-MM-DD-slug.md with frontmatter: title, date, category (new | improved | fixed), and the body. ### Phase 1 · The page Build: build.mjs renders /changelog/index.html newest first with category labels, and /changelog/feed.xml. A missing frontmatter field fails the build naming the file. Done when: adding an entry and rebuilding shows it first and the feed validates. Do not build yet: the widget. ### Phase 2 · The widget Build: widget.js reads /changelog/latest.json (written by the build with the newest date and count) and shows a small badge on an element you mark with data-changelog; clicking opens a panel listing the last five entries; the badge clears by storing the seen date in localStorage wrapped in try/catch. Done when: a new entry makes the badge appear on next load, opening the panel clears it, and the page works with the widget blocked. ### Phase 3 · Design Build: a readable timeline layout, category colors, dark mode, and the panel styled to inherit the host page font. Done when: no contrast failures in either scheme and the panel does not leak styles into the host page. ### Phase 4 · Distribution Build: a script that posts a new entry to a Slack webhook and a Bluesky or X account (optional keys in .env) on publish. Done when: a new entry appears in Slack within a minute of the build. ### Phase 5 · Deploy Build: the host config on your domain, the README. Done when: an entry goes from Markdown to live with one command. ### Out of scope (and why) - The hosted editor and reaction analytics. The PR is the editor here. ### README must contain - The frontmatter reference. - The one-line embed for the widget. ===== AGENTS.md ===== # Agent instructions · Headway indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A Node script rendering Markdown, One vanilla-JS file under 3 KB. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ===== BUILD_PLAN.md ===== # Build plan · Headway A changelog page and a what's-new widget: Markdown entries rendered to a static page and RSS, a badge that knows the last entry a visitor saw, and a script that posts new entries to Slack. One of the smallest real products on the list and a good first build. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · The page Entries rendered newest first with categories; a validating build; RSS. ### Steps 1. changelog/YYYY-MM-DD-slug.md with frontmatter (title, date, category) and build.mjs ```sh mkdir changelog && cd changelog && git init && npm init -y && npm pkg set type=module && npm install markdown-it@14 gray-matter@4 mkdir -p changelog public && cp .env.example .env ``` 2. Render index.html and feed.xml; fail on a missing field naming the file ### Done when - [ ] Adding an entry and rebuilding shows it first - [ ] The feed validates - [ ] A missing field fails the build ## Phase 2 · The widget A badge from latest.json cleared by opening the panel. ### Steps 1. The build writes latest.json with newest date and count; widget.js shows a badge on data-changelog 2. A panel listing the last five entries; localStorage for the seen date in try/catch ### Done when - [ ] A new entry makes the badge appear - [ ] Opening the panel clears it - [ ] The page works with the widget blocked ## Phase 3 · Design A timeline, category colours, dark mode, no style leaks. ### Steps 1. Timeline layout and category colours with dark mode 2. Scope the widget's styles so nothing leaks into the host page ### Done when - [ ] No contrast failures - [ ] The panel does not alter host page styles ## Phase 4 · Distribution Slack on publish. ### Steps 1. A publish script posting a new entry to SLACK_WEBHOOK_URL 2. Guard against re-posting an entry already announced ### Done when - [ ] A new entry appears in Slack within a minute - [ ] A rebuild does not re-post ## Phase 5 · Deploy One command from Markdown to live; README. ### Steps 1. Host config on your domain 2. README: frontmatter reference and the one-line embed Files: `README.md` ### Done when - [ ] An entry goes from Markdown to live with one command ## Not in this build - The hosted editor and reaction analytics. ## After v1, if you want it - Email digests of entries - Reactions stored in a tiny endpoint ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Public base of the changelog. SITE_URL=https://yourdomain.com/changelog # Optional · secret. For the publish script. Empty disables it. SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
You are building a production product version of Headway. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== PRODUCT.md ===== # Headway · product brief ## Problem A changelog is Markdown entries rendered to a page and an RSS feed, plus a badge that knows the last entry the user saw. That is a sitting. The $29 is for the custom domain and removing the badge, which you get for free by owning it. ## Product outcome Product updates your users actually see, with a widget you own and an optional private track. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - a static host or your existing site ## Explicit non-goals for v1 - The hosted editor and reaction analytics. - the hosted editor - Slack and Twitter auto-posting - reaction analytics - private changelogs behind their auth ## Success criteria - Widget verified on a host page without style leaks - Publish guard verified ===== BRIEF.md ===== # Build brief · Headway The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a changelog page and a "what's new" widget like Headway. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Markdown entries in a folder, a Node build script rendering static HTML and RSS, and one vanilla-JS widget under 3 kB. No framework, no server. ### Data model (create this before Phase 1) changelog/YYYY-MM-DD-slug.md with frontmatter: title, date, category (new | improved | fixed), and the body. ### Phase 1 · The page Build: build.mjs renders /changelog/index.html newest first with category labels, and /changelog/feed.xml. A missing frontmatter field fails the build naming the file. Done when: adding an entry and rebuilding shows it first and the feed validates. Do not build yet: the widget. ### Phase 2 · The widget Build: widget.js reads /changelog/latest.json (written by the build with the newest date and count) and shows a small badge on an element you mark with data-changelog; clicking opens a panel listing the last five entries; the badge clears by storing the seen date in localStorage wrapped in try/catch. Done when: a new entry makes the badge appear on next load, opening the panel clears it, and the page works with the widget blocked. ### Phase 3 · Design Build: a readable timeline layout, category colors, dark mode, and the panel styled to inherit the host page font. Done when: no contrast failures in either scheme and the panel does not leak styles into the host page. ### Phase 4 · Distribution Build: a script that posts a new entry to a Slack webhook and a Bluesky or X account (optional keys in .env) on publish. Done when: a new entry appears in Slack within a minute of the build. ### Phase 5 · Deploy Build: the host config on your domain, the README. Done when: an entry goes from Markdown to live with one command. ### Out of scope (and why) - The hosted editor and reaction analytics. The PR is the editor here. ### README must contain - The frontmatter reference. - The one-line embed for the widget. ===== ARCHITECTURE.md ===== # Architecture · Headway ## Stack | Part | Choice | Why | | --- | --- | --- | | Build | A Node script rendering Markdown | static, no server | | Widget | One vanilla-JS file under 3 KB | drops into any page | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Build | Markdown to HTML, RSS, latest.json | Any generator | | Widget | badge and panel | A framework component | | Publish | Slack posting | Add Bluesky or email | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `SITE_URL` · required · Public base of the changelog. - `SLACK_WEBHOOK_URL` · optional, secret · For the publish script. Empty disables it. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it. ===== AGENTS.md ===== # Agent instructions · Headway product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: A Node script rendering Markdown, One vanilla-JS file under 3 KB. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ===== MILESTONES.md ===== # Delivery milestones · Headway Estimated effort: **one sitting** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · The page Entries rendered newest first with categories; a validating build; RSS. ### Steps 1. changelog/YYYY-MM-DD-slug.md with frontmatter (title, date, category) and build.mjs ```sh mkdir changelog && cd changelog && git init && npm init -y && npm pkg set type=module && npm install markdown-it@14 gray-matter@4 mkdir -p changelog public && cp .env.example .env ``` 2. Render index.html and feed.xml; fail on a missing field naming the file ### Done when - [ ] Adding an entry and rebuilding shows it first - [ ] The feed validates - [ ] A missing field fails the build ## M2 · The widget A badge from latest.json cleared by opening the panel. ### Steps 1. The build writes latest.json with newest date and count; widget.js shows a badge on data-changelog 2. A panel listing the last five entries; localStorage for the seen date in try/catch ### Done when - [ ] A new entry makes the badge appear - [ ] Opening the panel clears it - [ ] The page works with the widget blocked ## M3 · Design A timeline, category colours, dark mode, no style leaks. ### Steps 1. Timeline layout and category colours with dark mode 2. Scope the widget's styles so nothing leaks into the host page ### Done when - [ ] No contrast failures - [ ] The panel does not alter host page styles ## M4 · Distribution Slack on publish. ### Steps 1. A publish script posting a new entry to SLACK_WEBHOOK_URL 2. Guard against re-posting an entry already announced ### Done when - [ ] A new entry appears in Slack within a minute - [ ] A rebuild does not re-post ## M5 · Deploy One command from Markdown to live; README. ### Steps 1. Host config on your domain 2. README: frontmatter reference and the one-line embed Files: `README.md` ### Done when - [ ] An entry goes from Markdown to live with one command ## M6 · Private changelog (production only) A customer-only changelog behind your app's login. ### Steps 1. Serve the built HTML from your app behind its existing auth 2. Per-plan entries via a frontmatter field the build filters on ### Done when - [ ] A logged-out visitor cannot see the private changelog - [ ] A plan-tagged entry shows only to that plan ===== OPERATIONS.md ===== # Operations · Headway ## Backup The repo. ## Restore Redeploy. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring Uptime. ## Incident checklist Revert. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Widget verified on a host page without style leaks - [ ] Publish guard verified ## Launch constraint Do not market omitted Headway capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered. ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Public base of the changelog. SITE_URL=https://yourdomain.com/changelog # Optional · secret. For the publish script. Empty disables it. SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
# Headway · indie build A changelog page and a what's-new widget: Markdown entries rendered to a static page and RSS, a badge that knows the last entry a visitor saw, and a script that posts new entries to Slack. One of the smallest real products on the list and a good first build. Estimated effort: **one sitting**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Build | A Node script rendering Markdown | static, no server | | Widget | One vanilla-JS file under 3 KB | drops into any page | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Everything in this build runs on it: the server, the scripts, the tests. - Get it: Download the LTS installer from nodejs.org, or install with your package manager (brew install node, or nvm install 22). Restart the terminal afterwards. - Verify: node --version prints v22 or higher - [ ] **A terminal and a code editor** · free - Why: Every step below is a command you type or a file you edit. - Get it: VS Code (code.visualstudio.com), Cursor or Zed. Open a folder for the project and use the editor's built-in terminal. - Verify: You can open a folder and run a command in its terminal - [ ] **Git** · free - Why: History for your code, and the way most hosts deploy. - Get it: Install from git-scm.com or with your package manager, then run git init in the project folder once it exists. - Verify: git --version prints a version - [ ] **A static host, or your existing site** · free - Why: The changelog is static files. - Get it: Cloudflare Pages, Netlify, or a folder in your current site. - [ ] **A Slack incoming webhook (optional)** (optional) · free - Why: Phase 4 posts new entries. - Get it: api.slack.com/apps > Incoming Webhooks. ## Quick start ```sh mkdir changelog && cd changelog && git init && npm init -y && npm pkg set type=module && npm install markdown-it@14 gray-matter@4 mkdir -p changelog public && cp .env.example .env ``` Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - The hosted editor and reaction analytics. - the hosted editor - Slack and Twitter auto-posting - reaction analytics - private changelogs behind their auth If one of those is essential to you, that is the reason to keep paying for Headway, and the README should say so rather than pretend.
# Build brief · Headway The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a changelog page and a "what's new" widget like Headway. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Markdown entries in a folder, a Node build script rendering static HTML and RSS, and one vanilla-JS widget under 3 kB. No framework, no server. ### Data model (create this before Phase 1) changelog/YYYY-MM-DD-slug.md with frontmatter: title, date, category (new | improved | fixed), and the body. ### Phase 1 · The page Build: build.mjs renders /changelog/index.html newest first with category labels, and /changelog/feed.xml. A missing frontmatter field fails the build naming the file. Done when: adding an entry and rebuilding shows it first and the feed validates. Do not build yet: the widget. ### Phase 2 · The widget Build: widget.js reads /changelog/latest.json (written by the build with the newest date and count) and shows a small badge on an element you mark with data-changelog; clicking opens a panel listing the last five entries; the badge clears by storing the seen date in localStorage wrapped in try/catch. Done when: a new entry makes the badge appear on next load, opening the panel clears it, and the page works with the widget blocked. ### Phase 3 · Design Build: a readable timeline layout, category colors, dark mode, and the panel styled to inherit the host page font. Done when: no contrast failures in either scheme and the panel does not leak styles into the host page. ### Phase 4 · Distribution Build: a script that posts a new entry to a Slack webhook and a Bluesky or X account (optional keys in .env) on publish. Done when: a new entry appears in Slack within a minute of the build. ### Phase 5 · Deploy Build: the host config on your domain, the README. Done when: an entry goes from Markdown to live with one command. ### Out of scope (and why) - The hosted editor and reaction analytics. The PR is the editor here. ### README must contain - The frontmatter reference. - The one-line embed for the widget.
# Agent instructions · Headway indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A Node script rendering Markdown, One vanilla-JS file under 3 KB. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs".
# Build plan · Headway A changelog page and a what's-new widget: Markdown entries rendered to a static page and RSS, a badge that knows the last entry a visitor saw, and a script that posts new entries to Slack. One of the smallest real products on the list and a good first build. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · The page Entries rendered newest first with categories; a validating build; RSS. ### Steps 1. changelog/YYYY-MM-DD-slug.md with frontmatter (title, date, category) and build.mjs ```sh mkdir changelog && cd changelog && git init && npm init -y && npm pkg set type=module && npm install markdown-it@14 gray-matter@4 mkdir -p changelog public && cp .env.example .env ``` 2. Render index.html and feed.xml; fail on a missing field naming the file ### Done when - [ ] Adding an entry and rebuilding shows it first - [ ] The feed validates - [ ] A missing field fails the build ## Phase 2 · The widget A badge from latest.json cleared by opening the panel. ### Steps 1. The build writes latest.json with newest date and count; widget.js shows a badge on data-changelog 2. A panel listing the last five entries; localStorage for the seen date in try/catch ### Done when - [ ] A new entry makes the badge appear - [ ] Opening the panel clears it - [ ] The page works with the widget blocked ## Phase 3 · Design A timeline, category colours, dark mode, no style leaks. ### Steps 1. Timeline layout and category colours with dark mode 2. Scope the widget's styles so nothing leaks into the host page ### Done when - [ ] No contrast failures - [ ] The panel does not alter host page styles ## Phase 4 · Distribution Slack on publish. ### Steps 1. A publish script posting a new entry to SLACK_WEBHOOK_URL 2. Guard against re-posting an entry already announced ### Done when - [ ] A new entry appears in Slack within a minute - [ ] A rebuild does not re-post ## Phase 5 · Deploy One command from Markdown to live; README. ### Steps 1. Host config on your domain 2. README: frontmatter reference and the one-line embed Files: `README.md` ### Done when - [ ] An entry goes from Markdown to live with one command ## Not in this build - The hosted editor and reaction analytics. ## After v1, if you want it - Email digests of entries - Reactions stored in a tiny endpoint
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Public base of the changelog. SITE_URL=https://yourdomain.com/changelog # Optional · secret. For the publish script. Empty disables it. SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
# Headway · product brief ## Problem A changelog is Markdown entries rendered to a page and an RSS feed, plus a badge that knows the last entry the user saw. That is a sitting. The $29 is for the custom domain and removing the badge, which you get for free by owning it. ## Product outcome Product updates your users actually see, with a widget you own and an optional private track. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - a static host or your existing site ## Explicit non-goals for v1 - The hosted editor and reaction analytics. - the hosted editor - Slack and Twitter auto-posting - reaction analytics - private changelogs behind their auth ## Success criteria - Widget verified on a host page without style leaks - Publish guard verified
# Build brief · Headway The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a changelog page and a "what's new" widget like Headway. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Markdown entries in a folder, a Node build script rendering static HTML and RSS, and one vanilla-JS widget under 3 kB. No framework, no server. ### Data model (create this before Phase 1) changelog/YYYY-MM-DD-slug.md with frontmatter: title, date, category (new | improved | fixed), and the body. ### Phase 1 · The page Build: build.mjs renders /changelog/index.html newest first with category labels, and /changelog/feed.xml. A missing frontmatter field fails the build naming the file. Done when: adding an entry and rebuilding shows it first and the feed validates. Do not build yet: the widget. ### Phase 2 · The widget Build: widget.js reads /changelog/latest.json (written by the build with the newest date and count) and shows a small badge on an element you mark with data-changelog; clicking opens a panel listing the last five entries; the badge clears by storing the seen date in localStorage wrapped in try/catch. Done when: a new entry makes the badge appear on next load, opening the panel clears it, and the page works with the widget blocked. ### Phase 3 · Design Build: a readable timeline layout, category colors, dark mode, and the panel styled to inherit the host page font. Done when: no contrast failures in either scheme and the panel does not leak styles into the host page. ### Phase 4 · Distribution Build: a script that posts a new entry to a Slack webhook and a Bluesky or X account (optional keys in .env) on publish. Done when: a new entry appears in Slack within a minute of the build. ### Phase 5 · Deploy Build: the host config on your domain, the README. Done when: an entry goes from Markdown to live with one command. ### Out of scope (and why) - The hosted editor and reaction analytics. The PR is the editor here. ### README must contain - The frontmatter reference. - The one-line embed for the widget.
# Architecture · Headway ## Stack | Part | Choice | Why | | --- | --- | --- | | Build | A Node script rendering Markdown | static, no server | | Widget | One vanilla-JS file under 3 KB | drops into any page | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Build | Markdown to HTML, RSS, latest.json | Any generator | | Widget | badge and panel | A framework component | | Publish | Slack posting | Add Bluesky or email | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `SITE_URL` · required · Public base of the changelog. - `SLACK_WEBHOOK_URL` · optional, secret · For the publish script. Empty disables it. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it.
# Agent instructions · Headway product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: A Node script rendering Markdown, One vanilla-JS file under 3 KB. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone.
# Delivery milestones · Headway Estimated effort: **one sitting** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · The page Entries rendered newest first with categories; a validating build; RSS. ### Steps 1. changelog/YYYY-MM-DD-slug.md with frontmatter (title, date, category) and build.mjs ```sh mkdir changelog && cd changelog && git init && npm init -y && npm pkg set type=module && npm install markdown-it@14 gray-matter@4 mkdir -p changelog public && cp .env.example .env ``` 2. Render index.html and feed.xml; fail on a missing field naming the file ### Done when - [ ] Adding an entry and rebuilding shows it first - [ ] The feed validates - [ ] A missing field fails the build ## M2 · The widget A badge from latest.json cleared by opening the panel. ### Steps 1. The build writes latest.json with newest date and count; widget.js shows a badge on data-changelog 2. A panel listing the last five entries; localStorage for the seen date in try/catch ### Done when - [ ] A new entry makes the badge appear - [ ] Opening the panel clears it - [ ] The page works with the widget blocked ## M3 · Design A timeline, category colours, dark mode, no style leaks. ### Steps 1. Timeline layout and category colours with dark mode 2. Scope the widget's styles so nothing leaks into the host page ### Done when - [ ] No contrast failures - [ ] The panel does not alter host page styles ## M4 · Distribution Slack on publish. ### Steps 1. A publish script posting a new entry to SLACK_WEBHOOK_URL 2. Guard against re-posting an entry already announced ### Done when - [ ] A new entry appears in Slack within a minute - [ ] A rebuild does not re-post ## M5 · Deploy One command from Markdown to live; README. ### Steps 1. Host config on your domain 2. README: frontmatter reference and the one-line embed Files: `README.md` ### Done when - [ ] An entry goes from Markdown to live with one command ## M6 · Private changelog (production only) A customer-only changelog behind your app's login. ### Steps 1. Serve the built HTML from your app behind its existing auth 2. Per-plan entries via a frontmatter field the build filters on ### Done when - [ ] A logged-out visitor cannot see the private changelog - [ ] A plan-tagged entry shows only to that plan
# Operations · Headway ## Backup The repo. ## Restore Redeploy. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring Uptime. ## Incident checklist Revert. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Widget verified on a host page without style leaks - [ ] Publish guard verified ## Launch constraint Do not market omitted Headway capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered.
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Public base of the changelog. SITE_URL=https://yourdomain.com/changelog # Optional · secret. For the publish script. Empty disables it. SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
$ choose a build depth, inspect the files, then open the complete pack in your agent
Product managers pay to write in a browser and never ask an engineer.
xthe hosted editor
xSlack and Twitter auto-posting
xreaction analytics
xprivate changelogs behind their auth
Nothing worth pointing at. That's why the prompt exists.
Headway pricing
pro$29/mo · monthly flat · $348/yr
free tierThe free plan includes unlimited changelog entries, a public page and the widget with Headway branding.
verified 2026-09-04 · source ↗
Is Headway free?
The free plan includes unlimited changelog entries, a public page and the widget with Headway branding. Paid is Pro at $29/mo (checked 2026-09-04).
Vibecode Headway
Yes. A competent AI coding agent (Claude Code, Codex, Cursor) can build a usable personal Headway replacement in one session with the prompt on this page. It runs on your own machine or server with no subscription.
How much does Headway cost?
Headway costs about $29/month (Pro, checked 2026-09-04), which is $348 per year. That's what you save by replacing it with one prompt.
What do I lose by replacing Headway?
Honestly: the hosted editor; Slack and Twitter auto-posting; reaction analytics; private changelogs behind their auth. If any of those are load-bearing for you, keep paying.
Is there an open-source alternative to Headway?
No mature open-source alternative worth pointing at, which is exactly why the one-shot prompt on this page exists.