Vibecode Hashnode
track this build6 phases, 12 steps, beginner friendly0%A Markdown blog with RSS, a custom domain and a newsletter form is a weekend with a static-site generator. What you cannot rebuild is the network: Hashnode surfaces your posts to a developer audience you did not bring, and that distribution is the reason to publish there rather than on your own domain.
You are building a lean indie version of Hashnode. 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 ===== # Hashnode · indie build A developer blog you own: Markdown posts in a repo rendered by Astro with syntax highlighting, tags, RSS, search and a generated OG image per post, deployed to your domain, with a script that cross-posts to Hashnode with the canonical URL pointing home so you keep the feed without giving up ownership. Estimated effort: **weekend**. 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 | | --- | --- | --- | | Framework | Astro with content collections, static output | validated frontmatter and zero client JavaScript by default | | Content | Markdown and MDX files in the repo | the folder is the CMS and git is the history | | Hosting | Any static host on your domain | there is nothing to run | ## 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 - [ ] **Your existing posts exported** · free - Why: Phase 1 imports them with their original dates. - Get it: Hashnode: Blog dashboard > Export > download the JSON or Markdown export. - [ ] **A static host connected to the repo** · free - Why: Deploy on push. - Get it: Cloudflare Pages or Netlify: connect the repository, build command npm run build, output dist. - [ ] **A domain or subdomain** (optional) · roughly $10 a year, or free on an existing domain - Why: Your posts at your address; canonical points here. - Get it: Register at Cloudflare Registrar, Porkbun or Namecheap, or use a subdomain of one you already own. You add one DNS record in the deploy phase. - [ ] **A Hashnode personal access token (optional)** (optional) · free - Why: Phase 6 cross-posts via the API with canonical set to your domain. - Get it: Hashnode > Account settings > Developer > Generate new token. ## Quick start ```sh npm create astro@latest blog -- --template minimal --typescript strict --install --git cd blog && mkdir -p src/content/posts ``` Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - The network feed; cross-posting with canonical is the honest way to keep it. - Comments, reactions and image hosting. - the developer network feed and its discovery - built-in newsletter delivery - comments and reactions from a logged-in audience - the editor and image hosting If one of those is essential to you, that is the reason to keep paying for Hashnode, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Hashnode 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 developer blog to replace Hashnode. 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) - Astro with content collections, output static. Markdown and MDX posts in a folder. No CMS, no database. - Deploy to any static host. One tiny Node endpoint only if you build the newsletter signup in Phase 5. ### Data model (create this before Phase 1) Each post is one Markdown file with frontmatter: title, date, slug, tags, description, canonical (optional), draft (bool). The folder is the CMS and git is the history. ### Phase 1 · Posts and routing Build: the content collection with a validated frontmatter schema, /:slug pages, an index sorted by date, and draft posts excluded from the build. Syntax highlighting for code blocks at build time, no client-side highlighter. Done when: a post with a missing title fails the build with a readable error, a draft does not appear in production, and a code block renders highlighted with zero JavaScript shipped for it. Do not build yet: design, tags, feeds. ### Phase 2 · Reading experience Build: a typographic layout with a measured line length, dark mode via prefers-color-scheme, a table of contents generated from headings, reading time, and heading anchor links. No web fonts unless self-hosted. Done when: the page scores 100 on Lighthouse Performance and Accessibility, and a long post is readable on a phone without horizontal scroll from a code block. ### Phase 3 · Tags, RSS and search Build: /tags/:tag pages, a full RSS feed with complete post content, a sitemap, and client-side search over a build-time JSON index (title, description, tags) kept under 50 kB. Done when: the feed validates, every tag page lists the right posts, and search finds a post by a word in its description. ### Phase 4 · SEO and cards Build: canonical URLs (honoring frontmatter canonical for cross-posts), Open Graph and Twitter meta, JSON-LD Article, and a generated 1200x630 OG image per post at build time. Done when: a post previews correctly in a card validator and its canonical points where the frontmatter says. ### Phase 5 · Newsletter signup Build: one small Node endpoint storing emails to SQLite with a honeypot and a rate limit, and a form on every post. No sending in v1 · export CSV into a real sender when you are ready. Done when: a signup stores once, a duplicate is a no-op, and the CSV export opens in a spreadsheet. ### Phase 6 · Deploy and cross-post Build: deploy config for a static host with the custom domain, and a script that pushes a post to Hashnode via its API with the canonical URL set to your domain, so the feed still works for you. Done when: a new post is live on your domain and mirrored on Hashnode with canonical pointing home. ### Out of scope (and why) - The network feed. You cannot build an audience with code; cross-posting with canonical is the honest way to keep it. - Comments, reactions and image hosting. ### README must contain - The frontmatter reference and how to add a post. - The cross-posting script and why canonical matters. ===== AGENTS.md ===== # Agent instructions · Hashnode indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: Astro with content collections, static output, Markdown and MDX files in the repo, Any static host on your domain. 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 · Hashnode A developer blog you own: Markdown posts in a repo rendered by Astro with syntax highlighting, tags, RSS, search and a generated OG image per post, deployed to your domain, with a script that cross-posts to Hashnode with the canonical URL pointing home so you keep the feed without giving up ownership. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Posts and routing A validated content collection, post pages, an index, drafts excluded, code highlighted at build time. ### Steps 1. Create the Astro project and the posts collection with a frontmatter schema title, date, slug, tags, description, canonical (optional), draft. Files: `src/content.config.ts` ```sh npm create astro@latest blog -- --template minimal --typescript strict --install --git cd blog && mkdir -p src/content/posts ``` 2. Import the export into Markdown files with original dates; add /:slug and an index sorted by date ### Done when - [ ] A post with a missing title fails the build naming the file - [ ] A draft is absent from the build - [ ] A code block renders highlighted with zero JavaScript shipped ## Phase 2 · Reading experience Typography, dark mode, a table of contents, reading time, anchors. ### Steps 1. Build the post layout with a measured line length and system fonts 2. Generate a table of contents from headings, add reading time and heading anchors ### Done when - [ ] Lighthouse 100 on Performance and Accessibility - [ ] A long post is readable on a phone without horizontal scroll from a code block ## Phase 3 · Tags, RSS and search Tag pages, a full-content feed, a sitemap, small client-side search. ### Steps 1. Add /tags/:tag, RSS with full content and a sitemap ```sh npx astro add rss sitemap ``` 2. Build a search JSON index at build time under 50 kB and a small search box ### Done when - [ ] The feed validates - [ ] Every tag page lists the right posts - [ ] Search finds a post by a word in its description ## Phase 4 · SEO and cards Canonical honoured, OG and JSON-LD present, an OG image per post. ### Steps 1. Add canonical from frontmatter or SITE_URL, Open Graph, Twitter meta and JSON-LD Article 2. Generate a 1200x630 OG image per post at build time with satori and resvg ```sh npm install satori@0.29.0 @resvg/resvg-js@2.6.2 ``` ### Done when - [ ] A post previews correctly in a card validator - [ ] Canonical points where the frontmatter says ## Phase 5 · Newsletter signup Emails stored locally; no sending in v1. ### Steps 1. One small Node endpoint storing to SQLite with honeypot and rate limit 2. A form on every post and a CSV export ### Done when - [ ] A signup stores once; a duplicate is a no-op - [ ] The CSV opens in a spreadsheet ## Phase 6 · Deploy and cross-post Live on your domain, mirrored on Hashnode with canonical home. ### Steps 1. Connect the static host and the custom domain 2. Write scripts/crosspost.mjs that publishes a post to Hashnode via its GraphQL API with canonicalUrl set Publish here first, syndicate second; the reverse leaves Hashnode canonical. ### Done when - [ ] A new post is live on your domain - [ ] The mirror on Hashnode has canonical pointing home, verified in the page source ## Not in this build - The network feed; cross-posting with canonical is the honest way to keep it. - Comments, reactions and image hosting. ## After v1, if you want it - Cross-post to dev.to with the same canonical rule - A series or collection page type ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Canonical base for every post. SITE_URL=https://blog.yourdomain.com # Optional · secret. Developer token for cross-posting. Empty disables the script. HASHNODE_TOKEN=... # Optional. From your Hashnode blog dashboard URL or the API. HASHNODE_PUBLICATION_ID=...
You are building a lean indie version of Hashnode. 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 ===== # Hashnode · indie build A developer blog you own: Markdown posts in a repo rendered by Astro with syntax highlighting, tags, RSS, search and a generated OG image per post, deployed to your domain, with a script that cross-posts to Hashnode with the canonical URL pointing home so you keep the feed without giving up ownership. Estimated effort: **weekend**. 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 | | --- | --- | --- | | Framework | Astro with content collections, static output | validated frontmatter and zero client JavaScript by default | | Content | Markdown and MDX files in the repo | the folder is the CMS and git is the history | | Hosting | Any static host on your domain | there is nothing to run | ## 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 - [ ] **Your existing posts exported** · free - Why: Phase 1 imports them with their original dates. - Get it: Hashnode: Blog dashboard > Export > download the JSON or Markdown export. - [ ] **A static host connected to the repo** · free - Why: Deploy on push. - Get it: Cloudflare Pages or Netlify: connect the repository, build command npm run build, output dist. - [ ] **A domain or subdomain** (optional) · roughly $10 a year, or free on an existing domain - Why: Your posts at your address; canonical points here. - Get it: Register at Cloudflare Registrar, Porkbun or Namecheap, or use a subdomain of one you already own. You add one DNS record in the deploy phase. - [ ] **A Hashnode personal access token (optional)** (optional) · free - Why: Phase 6 cross-posts via the API with canonical set to your domain. - Get it: Hashnode > Account settings > Developer > Generate new token. ## Quick start ```sh npm create astro@latest blog -- --template minimal --typescript strict --install --git cd blog && mkdir -p src/content/posts ``` Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - The network feed; cross-posting with canonical is the honest way to keep it. - Comments, reactions and image hosting. - the developer network feed and its discovery - built-in newsletter delivery - comments and reactions from a logged-in audience - the editor and image hosting If one of those is essential to you, that is the reason to keep paying for Hashnode, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Hashnode 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 developer blog to replace Hashnode. 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) - Astro with content collections, output static. Markdown and MDX posts in a folder. No CMS, no database. - Deploy to any static host. One tiny Node endpoint only if you build the newsletter signup in Phase 5. ### Data model (create this before Phase 1) Each post is one Markdown file with frontmatter: title, date, slug, tags, description, canonical (optional), draft (bool). The folder is the CMS and git is the history. ### Phase 1 · Posts and routing Build: the content collection with a validated frontmatter schema, /:slug pages, an index sorted by date, and draft posts excluded from the build. Syntax highlighting for code blocks at build time, no client-side highlighter. Done when: a post with a missing title fails the build with a readable error, a draft does not appear in production, and a code block renders highlighted with zero JavaScript shipped for it. Do not build yet: design, tags, feeds. ### Phase 2 · Reading experience Build: a typographic layout with a measured line length, dark mode via prefers-color-scheme, a table of contents generated from headings, reading time, and heading anchor links. No web fonts unless self-hosted. Done when: the page scores 100 on Lighthouse Performance and Accessibility, and a long post is readable on a phone without horizontal scroll from a code block. ### Phase 3 · Tags, RSS and search Build: /tags/:tag pages, a full RSS feed with complete post content, a sitemap, and client-side search over a build-time JSON index (title, description, tags) kept under 50 kB. Done when: the feed validates, every tag page lists the right posts, and search finds a post by a word in its description. ### Phase 4 · SEO and cards Build: canonical URLs (honoring frontmatter canonical for cross-posts), Open Graph and Twitter meta, JSON-LD Article, and a generated 1200x630 OG image per post at build time. Done when: a post previews correctly in a card validator and its canonical points where the frontmatter says. ### Phase 5 · Newsletter signup Build: one small Node endpoint storing emails to SQLite with a honeypot and a rate limit, and a form on every post. No sending in v1 · export CSV into a real sender when you are ready. Done when: a signup stores once, a duplicate is a no-op, and the CSV export opens in a spreadsheet. ### Phase 6 · Deploy and cross-post Build: deploy config for a static host with the custom domain, and a script that pushes a post to Hashnode via its API with the canonical URL set to your domain, so the feed still works for you. Done when: a new post is live on your domain and mirrored on Hashnode with canonical pointing home. ### Out of scope (and why) - The network feed. You cannot build an audience with code; cross-posting with canonical is the honest way to keep it. - Comments, reactions and image hosting. ### README must contain - The frontmatter reference and how to add a post. - The cross-posting script and why canonical matters. ===== AGENTS.md ===== # Agent instructions · Hashnode indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: Astro with content collections, static output, Markdown and MDX files in the repo, Any static host on your domain. 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 · Hashnode A developer blog you own: Markdown posts in a repo rendered by Astro with syntax highlighting, tags, RSS, search and a generated OG image per post, deployed to your domain, with a script that cross-posts to Hashnode with the canonical URL pointing home so you keep the feed without giving up ownership. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Posts and routing A validated content collection, post pages, an index, drafts excluded, code highlighted at build time. ### Steps 1. Create the Astro project and the posts collection with a frontmatter schema title, date, slug, tags, description, canonical (optional), draft. Files: `src/content.config.ts` ```sh npm create astro@latest blog -- --template minimal --typescript strict --install --git cd blog && mkdir -p src/content/posts ``` 2. Import the export into Markdown files with original dates; add /:slug and an index sorted by date ### Done when - [ ] A post with a missing title fails the build naming the file - [ ] A draft is absent from the build - [ ] A code block renders highlighted with zero JavaScript shipped ## Phase 2 · Reading experience Typography, dark mode, a table of contents, reading time, anchors. ### Steps 1. Build the post layout with a measured line length and system fonts 2. Generate a table of contents from headings, add reading time and heading anchors ### Done when - [ ] Lighthouse 100 on Performance and Accessibility - [ ] A long post is readable on a phone without horizontal scroll from a code block ## Phase 3 · Tags, RSS and search Tag pages, a full-content feed, a sitemap, small client-side search. ### Steps 1. Add /tags/:tag, RSS with full content and a sitemap ```sh npx astro add rss sitemap ``` 2. Build a search JSON index at build time under 50 kB and a small search box ### Done when - [ ] The feed validates - [ ] Every tag page lists the right posts - [ ] Search finds a post by a word in its description ## Phase 4 · SEO and cards Canonical honoured, OG and JSON-LD present, an OG image per post. ### Steps 1. Add canonical from frontmatter or SITE_URL, Open Graph, Twitter meta and JSON-LD Article 2. Generate a 1200x630 OG image per post at build time with satori and resvg ```sh npm install satori@0.29.0 @resvg/resvg-js@2.6.2 ``` ### Done when - [ ] A post previews correctly in a card validator - [ ] Canonical points where the frontmatter says ## Phase 5 · Newsletter signup Emails stored locally; no sending in v1. ### Steps 1. One small Node endpoint storing to SQLite with honeypot and rate limit 2. A form on every post and a CSV export ### Done when - [ ] A signup stores once; a duplicate is a no-op - [ ] The CSV opens in a spreadsheet ## Phase 6 · Deploy and cross-post Live on your domain, mirrored on Hashnode with canonical home. ### Steps 1. Connect the static host and the custom domain 2. Write scripts/crosspost.mjs that publishes a post to Hashnode via its GraphQL API with canonicalUrl set Publish here first, syndicate second; the reverse leaves Hashnode canonical. ### Done when - [ ] A new post is live on your domain - [ ] The mirror on Hashnode has canonical pointing home, verified in the page source ## Not in this build - The network feed; cross-posting with canonical is the honest way to keep it. - Comments, reactions and image hosting. ## After v1, if you want it - Cross-post to dev.to with the same canonical rule - A series or collection page type ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Canonical base for every post. SITE_URL=https://blog.yourdomain.com # Optional · secret. Developer token for cross-posting. Empty disables the script. HASHNODE_TOKEN=... # Optional. From your Hashnode blog dashboard URL or the API. HASHNODE_PUBLICATION_ID=...
You are building a production product version of Hashnode. 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 ===== # Hashnode · product brief ## Problem A Markdown blog with RSS, a custom domain and a newsletter form is a weekend with a static-site generator. What you cannot rebuild is the network: Hashnode surfaces your posts to a developer audience you did not bring, and that distribution is the reason to publish there rather than on your own domain. ## Product outcome A blog that is yours by default and still reaches the Hashnode audience by syndication. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - a static host - a domain - optionally an email provider for the newsletter ## Explicit non-goals for v1 - The network feed; cross-posting with canonical is the honest way to keep it. - Comments, reactions and image hosting. - the developer network feed and its discovery - built-in newsletter delivery - comments and reactions from a logged-in audience - the editor and image hosting ## Success criteria - Lighthouse 100 - Canonical verified on a mirrored post - One restore of the signup database ===== BRIEF.md ===== # Build brief · Hashnode 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 developer blog to replace Hashnode. 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) - Astro with content collections, output static. Markdown and MDX posts in a folder. No CMS, no database. - Deploy to any static host. One tiny Node endpoint only if you build the newsletter signup in Phase 5. ### Data model (create this before Phase 1) Each post is one Markdown file with frontmatter: title, date, slug, tags, description, canonical (optional), draft (bool). The folder is the CMS and git is the history. ### Phase 1 · Posts and routing Build: the content collection with a validated frontmatter schema, /:slug pages, an index sorted by date, and draft posts excluded from the build. Syntax highlighting for code blocks at build time, no client-side highlighter. Done when: a post with a missing title fails the build with a readable error, a draft does not appear in production, and a code block renders highlighted with zero JavaScript shipped for it. Do not build yet: design, tags, feeds. ### Phase 2 · Reading experience Build: a typographic layout with a measured line length, dark mode via prefers-color-scheme, a table of contents generated from headings, reading time, and heading anchor links. No web fonts unless self-hosted. Done when: the page scores 100 on Lighthouse Performance and Accessibility, and a long post is readable on a phone without horizontal scroll from a code block. ### Phase 3 · Tags, RSS and search Build: /tags/:tag pages, a full RSS feed with complete post content, a sitemap, and client-side search over a build-time JSON index (title, description, tags) kept under 50 kB. Done when: the feed validates, every tag page lists the right posts, and search finds a post by a word in its description. ### Phase 4 · SEO and cards Build: canonical URLs (honoring frontmatter canonical for cross-posts), Open Graph and Twitter meta, JSON-LD Article, and a generated 1200x630 OG image per post at build time. Done when: a post previews correctly in a card validator and its canonical points where the frontmatter says. ### Phase 5 · Newsletter signup Build: one small Node endpoint storing emails to SQLite with a honeypot and a rate limit, and a form on every post. No sending in v1 · export CSV into a real sender when you are ready. Done when: a signup stores once, a duplicate is a no-op, and the CSV export opens in a spreadsheet. ### Phase 6 · Deploy and cross-post Build: deploy config for a static host with the custom domain, and a script that pushes a post to Hashnode via its API with the canonical URL set to your domain, so the feed still works for you. Done when: a new post is live on your domain and mirrored on Hashnode with canonical pointing home. ### Out of scope (and why) - The network feed. You cannot build an audience with code; cross-posting with canonical is the honest way to keep it. - Comments, reactions and image hosting. ### README must contain - The frontmatter reference and how to add a post. - The cross-posting script and why canonical matters. ===== ARCHITECTURE.md ===== # Architecture · Hashnode ## Stack | Part | Choice | Why | | --- | --- | --- | | Framework | Astro with content collections, static output | validated frontmatter and zero client JavaScript by default | | Content | Markdown and MDX files in the repo | the folder is the CMS and git is the history | | Hosting | Any static host on your domain | there is nothing to run | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Content | the collection and schema | Any Markdown source | | Site | Astro layouts, feeds, OG | Another static generator against the same files | | Signup | the one endpoint | A hosted form later | | Syndicate | the cross-post script | Add Medium or dev.to with the same canonical rule | ## 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 · Canonical base for every post. - `HASHNODE_TOKEN` · optional, secret · Developer token for cross-posting. Empty disables the script. - `HASHNODE_PUBLICATION_ID` · optional · From your Hashnode blog dashboard URL or the API. ## 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 · Hashnode product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: Astro with content collections, static output, Markdown and MDX files in the repo, Any static host on your domain. - 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 · Hashnode Estimated effort: **weekend** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · Posts and routing A validated content collection, post pages, an index, drafts excluded, code highlighted at build time. ### Steps 1. Create the Astro project and the posts collection with a frontmatter schema title, date, slug, tags, description, canonical (optional), draft. Files: `src/content.config.ts` ```sh npm create astro@latest blog -- --template minimal --typescript strict --install --git cd blog && mkdir -p src/content/posts ``` 2. Import the export into Markdown files with original dates; add /:slug and an index sorted by date ### Done when - [ ] A post with a missing title fails the build naming the file - [ ] A draft is absent from the build - [ ] A code block renders highlighted with zero JavaScript shipped ## M2 · Reading experience Typography, dark mode, a table of contents, reading time, anchors. ### Steps 1. Build the post layout with a measured line length and system fonts 2. Generate a table of contents from headings, add reading time and heading anchors ### Done when - [ ] Lighthouse 100 on Performance and Accessibility - [ ] A long post is readable on a phone without horizontal scroll from a code block ## M3 · Tags, RSS and search Tag pages, a full-content feed, a sitemap, small client-side search. ### Steps 1. Add /tags/:tag, RSS with full content and a sitemap ```sh npx astro add rss sitemap ``` 2. Build a search JSON index at build time under 50 kB and a small search box ### Done when - [ ] The feed validates - [ ] Every tag page lists the right posts - [ ] Search finds a post by a word in its description ## M4 · SEO and cards Canonical honoured, OG and JSON-LD present, an OG image per post. ### Steps 1. Add canonical from frontmatter or SITE_URL, Open Graph, Twitter meta and JSON-LD Article 2. Generate a 1200x630 OG image per post at build time with satori and resvg ```sh npm install satori@0.29.0 @resvg/resvg-js@2.6.2 ``` ### Done when - [ ] A post previews correctly in a card validator - [ ] Canonical points where the frontmatter says ## M5 · Newsletter signup Emails stored locally; no sending in v1. ### Steps 1. One small Node endpoint storing to SQLite with honeypot and rate limit 2. A form on every post and a CSV export ### Done when - [ ] A signup stores once; a duplicate is a no-op - [ ] The CSV opens in a spreadsheet ## M6 · Deploy and cross-post Live on your domain, mirrored on Hashnode with canonical home. ### Steps 1. Connect the static host and the custom domain 2. Write scripts/crosspost.mjs that publishes a post to Hashnode via its GraphQL API with canonicalUrl set Publish here first, syndicate second; the reverse leaves Hashnode canonical. ### Done when - [ ] A new post is live on your domain - [ ] The mirror on Hashnode has canonical pointing home, verified in the page source ## M7 · Operate the newsletter endpoint (production only) Only if you keep the signup: monitor and back it up like any small server. ### Steps 1. /healthz, uptime check, structured logs 2. Nightly backup of the signups database off the box and one restore ### Done when - [ ] An alert fires when the endpoint is stopped - [ ] A restore contains yesterday's signups ===== OPERATIONS.md ===== # Operations · Hashnode ## Backup The repo is the backup; the signup database nightly. ## Restore Redeploy; copy the database. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring Uptime on the site and the endpoint. ## Incident checklist A bad deploy is reverted with git. 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 - [ ] Lighthouse 100 - [ ] Canonical verified on a mirrored post - [ ] One restore of the signup database ## Launch constraint Do not market omitted Hashnode 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. Canonical base for every post. SITE_URL=https://blog.yourdomain.com # Optional · secret. Developer token for cross-posting. Empty disables the script. HASHNODE_TOKEN=... # Optional. From your Hashnode blog dashboard URL or the API. HASHNODE_PUBLICATION_ID=...
# Hashnode · indie build A developer blog you own: Markdown posts in a repo rendered by Astro with syntax highlighting, tags, RSS, search and a generated OG image per post, deployed to your domain, with a script that cross-posts to Hashnode with the canonical URL pointing home so you keep the feed without giving up ownership. Estimated effort: **weekend**. 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 | | --- | --- | --- | | Framework | Astro with content collections, static output | validated frontmatter and zero client JavaScript by default | | Content | Markdown and MDX files in the repo | the folder is the CMS and git is the history | | Hosting | Any static host on your domain | there is nothing to run | ## 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 - [ ] **Your existing posts exported** · free - Why: Phase 1 imports them with their original dates. - Get it: Hashnode: Blog dashboard > Export > download the JSON or Markdown export. - [ ] **A static host connected to the repo** · free - Why: Deploy on push. - Get it: Cloudflare Pages or Netlify: connect the repository, build command npm run build, output dist. - [ ] **A domain or subdomain** (optional) · roughly $10 a year, or free on an existing domain - Why: Your posts at your address; canonical points here. - Get it: Register at Cloudflare Registrar, Porkbun or Namecheap, or use a subdomain of one you already own. You add one DNS record in the deploy phase. - [ ] **A Hashnode personal access token (optional)** (optional) · free - Why: Phase 6 cross-posts via the API with canonical set to your domain. - Get it: Hashnode > Account settings > Developer > Generate new token. ## Quick start ```sh npm create astro@latest blog -- --template minimal --typescript strict --install --git cd blog && mkdir -p src/content/posts ``` Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - The network feed; cross-posting with canonical is the honest way to keep it. - Comments, reactions and image hosting. - the developer network feed and its discovery - built-in newsletter delivery - comments and reactions from a logged-in audience - the editor and image hosting If one of those is essential to you, that is the reason to keep paying for Hashnode, and the README should say so rather than pretend.
# Build brief · Hashnode 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 developer blog to replace Hashnode. 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) - Astro with content collections, output static. Markdown and MDX posts in a folder. No CMS, no database. - Deploy to any static host. One tiny Node endpoint only if you build the newsletter signup in Phase 5. ### Data model (create this before Phase 1) Each post is one Markdown file with frontmatter: title, date, slug, tags, description, canonical (optional), draft (bool). The folder is the CMS and git is the history. ### Phase 1 · Posts and routing Build: the content collection with a validated frontmatter schema, /:slug pages, an index sorted by date, and draft posts excluded from the build. Syntax highlighting for code blocks at build time, no client-side highlighter. Done when: a post with a missing title fails the build with a readable error, a draft does not appear in production, and a code block renders highlighted with zero JavaScript shipped for it. Do not build yet: design, tags, feeds. ### Phase 2 · Reading experience Build: a typographic layout with a measured line length, dark mode via prefers-color-scheme, a table of contents generated from headings, reading time, and heading anchor links. No web fonts unless self-hosted. Done when: the page scores 100 on Lighthouse Performance and Accessibility, and a long post is readable on a phone without horizontal scroll from a code block. ### Phase 3 · Tags, RSS and search Build: /tags/:tag pages, a full RSS feed with complete post content, a sitemap, and client-side search over a build-time JSON index (title, description, tags) kept under 50 kB. Done when: the feed validates, every tag page lists the right posts, and search finds a post by a word in its description. ### Phase 4 · SEO and cards Build: canonical URLs (honoring frontmatter canonical for cross-posts), Open Graph and Twitter meta, JSON-LD Article, and a generated 1200x630 OG image per post at build time. Done when: a post previews correctly in a card validator and its canonical points where the frontmatter says. ### Phase 5 · Newsletter signup Build: one small Node endpoint storing emails to SQLite with a honeypot and a rate limit, and a form on every post. No sending in v1 · export CSV into a real sender when you are ready. Done when: a signup stores once, a duplicate is a no-op, and the CSV export opens in a spreadsheet. ### Phase 6 · Deploy and cross-post Build: deploy config for a static host with the custom domain, and a script that pushes a post to Hashnode via its API with the canonical URL set to your domain, so the feed still works for you. Done when: a new post is live on your domain and mirrored on Hashnode with canonical pointing home. ### Out of scope (and why) - The network feed. You cannot build an audience with code; cross-posting with canonical is the honest way to keep it. - Comments, reactions and image hosting. ### README must contain - The frontmatter reference and how to add a post. - The cross-posting script and why canonical matters.
# Agent instructions · Hashnode indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: Astro with content collections, static output, Markdown and MDX files in the repo, Any static host on your domain. 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 · Hashnode A developer blog you own: Markdown posts in a repo rendered by Astro with syntax highlighting, tags, RSS, search and a generated OG image per post, deployed to your domain, with a script that cross-posts to Hashnode with the canonical URL pointing home so you keep the feed without giving up ownership. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Posts and routing A validated content collection, post pages, an index, drafts excluded, code highlighted at build time. ### Steps 1. Create the Astro project and the posts collection with a frontmatter schema title, date, slug, tags, description, canonical (optional), draft. Files: `src/content.config.ts` ```sh npm create astro@latest blog -- --template minimal --typescript strict --install --git cd blog && mkdir -p src/content/posts ``` 2. Import the export into Markdown files with original dates; add /:slug and an index sorted by date ### Done when - [ ] A post with a missing title fails the build naming the file - [ ] A draft is absent from the build - [ ] A code block renders highlighted with zero JavaScript shipped ## Phase 2 · Reading experience Typography, dark mode, a table of contents, reading time, anchors. ### Steps 1. Build the post layout with a measured line length and system fonts 2. Generate a table of contents from headings, add reading time and heading anchors ### Done when - [ ] Lighthouse 100 on Performance and Accessibility - [ ] A long post is readable on a phone without horizontal scroll from a code block ## Phase 3 · Tags, RSS and search Tag pages, a full-content feed, a sitemap, small client-side search. ### Steps 1. Add /tags/:tag, RSS with full content and a sitemap ```sh npx astro add rss sitemap ``` 2. Build a search JSON index at build time under 50 kB and a small search box ### Done when - [ ] The feed validates - [ ] Every tag page lists the right posts - [ ] Search finds a post by a word in its description ## Phase 4 · SEO and cards Canonical honoured, OG and JSON-LD present, an OG image per post. ### Steps 1. Add canonical from frontmatter or SITE_URL, Open Graph, Twitter meta and JSON-LD Article 2. Generate a 1200x630 OG image per post at build time with satori and resvg ```sh npm install satori@0.29.0 @resvg/resvg-js@2.6.2 ``` ### Done when - [ ] A post previews correctly in a card validator - [ ] Canonical points where the frontmatter says ## Phase 5 · Newsletter signup Emails stored locally; no sending in v1. ### Steps 1. One small Node endpoint storing to SQLite with honeypot and rate limit 2. A form on every post and a CSV export ### Done when - [ ] A signup stores once; a duplicate is a no-op - [ ] The CSV opens in a spreadsheet ## Phase 6 · Deploy and cross-post Live on your domain, mirrored on Hashnode with canonical home. ### Steps 1. Connect the static host and the custom domain 2. Write scripts/crosspost.mjs that publishes a post to Hashnode via its GraphQL API with canonicalUrl set Publish here first, syndicate second; the reverse leaves Hashnode canonical. ### Done when - [ ] A new post is live on your domain - [ ] The mirror on Hashnode has canonical pointing home, verified in the page source ## Not in this build - The network feed; cross-posting with canonical is the honest way to keep it. - Comments, reactions and image hosting. ## After v1, if you want it - Cross-post to dev.to with the same canonical rule - A series or collection page type
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Canonical base for every post. SITE_URL=https://blog.yourdomain.com # Optional · secret. Developer token for cross-posting. Empty disables the script. HASHNODE_TOKEN=... # Optional. From your Hashnode blog dashboard URL or the API. HASHNODE_PUBLICATION_ID=...
# Hashnode · product brief ## Problem A Markdown blog with RSS, a custom domain and a newsletter form is a weekend with a static-site generator. What you cannot rebuild is the network: Hashnode surfaces your posts to a developer audience you did not bring, and that distribution is the reason to publish there rather than on your own domain. ## Product outcome A blog that is yours by default and still reaches the Hashnode audience by syndication. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - a static host - a domain - optionally an email provider for the newsletter ## Explicit non-goals for v1 - The network feed; cross-posting with canonical is the honest way to keep it. - Comments, reactions and image hosting. - the developer network feed and its discovery - built-in newsletter delivery - comments and reactions from a logged-in audience - the editor and image hosting ## Success criteria - Lighthouse 100 - Canonical verified on a mirrored post - One restore of the signup database
# Build brief · Hashnode 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 developer blog to replace Hashnode. 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) - Astro with content collections, output static. Markdown and MDX posts in a folder. No CMS, no database. - Deploy to any static host. One tiny Node endpoint only if you build the newsletter signup in Phase 5. ### Data model (create this before Phase 1) Each post is one Markdown file with frontmatter: title, date, slug, tags, description, canonical (optional), draft (bool). The folder is the CMS and git is the history. ### Phase 1 · Posts and routing Build: the content collection with a validated frontmatter schema, /:slug pages, an index sorted by date, and draft posts excluded from the build. Syntax highlighting for code blocks at build time, no client-side highlighter. Done when: a post with a missing title fails the build with a readable error, a draft does not appear in production, and a code block renders highlighted with zero JavaScript shipped for it. Do not build yet: design, tags, feeds. ### Phase 2 · Reading experience Build: a typographic layout with a measured line length, dark mode via prefers-color-scheme, a table of contents generated from headings, reading time, and heading anchor links. No web fonts unless self-hosted. Done when: the page scores 100 on Lighthouse Performance and Accessibility, and a long post is readable on a phone without horizontal scroll from a code block. ### Phase 3 · Tags, RSS and search Build: /tags/:tag pages, a full RSS feed with complete post content, a sitemap, and client-side search over a build-time JSON index (title, description, tags) kept under 50 kB. Done when: the feed validates, every tag page lists the right posts, and search finds a post by a word in its description. ### Phase 4 · SEO and cards Build: canonical URLs (honoring frontmatter canonical for cross-posts), Open Graph and Twitter meta, JSON-LD Article, and a generated 1200x630 OG image per post at build time. Done when: a post previews correctly in a card validator and its canonical points where the frontmatter says. ### Phase 5 · Newsletter signup Build: one small Node endpoint storing emails to SQLite with a honeypot and a rate limit, and a form on every post. No sending in v1 · export CSV into a real sender when you are ready. Done when: a signup stores once, a duplicate is a no-op, and the CSV export opens in a spreadsheet. ### Phase 6 · Deploy and cross-post Build: deploy config for a static host with the custom domain, and a script that pushes a post to Hashnode via its API with the canonical URL set to your domain, so the feed still works for you. Done when: a new post is live on your domain and mirrored on Hashnode with canonical pointing home. ### Out of scope (and why) - The network feed. You cannot build an audience with code; cross-posting with canonical is the honest way to keep it. - Comments, reactions and image hosting. ### README must contain - The frontmatter reference and how to add a post. - The cross-posting script and why canonical matters.
# Architecture · Hashnode ## Stack | Part | Choice | Why | | --- | --- | --- | | Framework | Astro with content collections, static output | validated frontmatter and zero client JavaScript by default | | Content | Markdown and MDX files in the repo | the folder is the CMS and git is the history | | Hosting | Any static host on your domain | there is nothing to run | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Content | the collection and schema | Any Markdown source | | Site | Astro layouts, feeds, OG | Another static generator against the same files | | Signup | the one endpoint | A hosted form later | | Syndicate | the cross-post script | Add Medium or dev.to with the same canonical rule | ## 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 · Canonical base for every post. - `HASHNODE_TOKEN` · optional, secret · Developer token for cross-posting. Empty disables the script. - `HASHNODE_PUBLICATION_ID` · optional · From your Hashnode blog dashboard URL or the API. ## 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 · Hashnode product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: Astro with content collections, static output, Markdown and MDX files in the repo, Any static host on your domain. - 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 · Hashnode Estimated effort: **weekend** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · Posts and routing A validated content collection, post pages, an index, drafts excluded, code highlighted at build time. ### Steps 1. Create the Astro project and the posts collection with a frontmatter schema title, date, slug, tags, description, canonical (optional), draft. Files: `src/content.config.ts` ```sh npm create astro@latest blog -- --template minimal --typescript strict --install --git cd blog && mkdir -p src/content/posts ``` 2. Import the export into Markdown files with original dates; add /:slug and an index sorted by date ### Done when - [ ] A post with a missing title fails the build naming the file - [ ] A draft is absent from the build - [ ] A code block renders highlighted with zero JavaScript shipped ## M2 · Reading experience Typography, dark mode, a table of contents, reading time, anchors. ### Steps 1. Build the post layout with a measured line length and system fonts 2. Generate a table of contents from headings, add reading time and heading anchors ### Done when - [ ] Lighthouse 100 on Performance and Accessibility - [ ] A long post is readable on a phone without horizontal scroll from a code block ## M3 · Tags, RSS and search Tag pages, a full-content feed, a sitemap, small client-side search. ### Steps 1. Add /tags/:tag, RSS with full content and a sitemap ```sh npx astro add rss sitemap ``` 2. Build a search JSON index at build time under 50 kB and a small search box ### Done when - [ ] The feed validates - [ ] Every tag page lists the right posts - [ ] Search finds a post by a word in its description ## M4 · SEO and cards Canonical honoured, OG and JSON-LD present, an OG image per post. ### Steps 1. Add canonical from frontmatter or SITE_URL, Open Graph, Twitter meta and JSON-LD Article 2. Generate a 1200x630 OG image per post at build time with satori and resvg ```sh npm install satori@0.29.0 @resvg/resvg-js@2.6.2 ``` ### Done when - [ ] A post previews correctly in a card validator - [ ] Canonical points where the frontmatter says ## M5 · Newsletter signup Emails stored locally; no sending in v1. ### Steps 1. One small Node endpoint storing to SQLite with honeypot and rate limit 2. A form on every post and a CSV export ### Done when - [ ] A signup stores once; a duplicate is a no-op - [ ] The CSV opens in a spreadsheet ## M6 · Deploy and cross-post Live on your domain, mirrored on Hashnode with canonical home. ### Steps 1. Connect the static host and the custom domain 2. Write scripts/crosspost.mjs that publishes a post to Hashnode via its GraphQL API with canonicalUrl set Publish here first, syndicate second; the reverse leaves Hashnode canonical. ### Done when - [ ] A new post is live on your domain - [ ] The mirror on Hashnode has canonical pointing home, verified in the page source ## M7 · Operate the newsletter endpoint (production only) Only if you keep the signup: monitor and back it up like any small server. ### Steps 1. /healthz, uptime check, structured logs 2. Nightly backup of the signups database off the box and one restore ### Done when - [ ] An alert fires when the endpoint is stopped - [ ] A restore contains yesterday's signups
# Operations · Hashnode ## Backup The repo is the backup; the signup database nightly. ## Restore Redeploy; copy the database. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring Uptime on the site and the endpoint. ## Incident checklist A bad deploy is reverted with git. 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 - [ ] Lighthouse 100 - [ ] Canonical verified on a mirrored post - [ ] One restore of the signup database ## Launch constraint Do not market omitted Hashnode 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. Canonical base for every post. SITE_URL=https://blog.yourdomain.com # Optional · secret. Developer token for cross-posting. Empty disables the script. HASHNODE_TOKEN=... # Optional. From your Hashnode blog dashboard URL or the API. HASHNODE_PUBLICATION_ID=...
$ choose a build depth, inspect the files, then open the complete pack in your agent
The blog is free. People stay for the feed that puts a first post in front of thousands of developers, and pay $5 for the API and headless mode once the blog becomes part of something bigger.
xthe developer network feed and its discovery
xbuilt-in newsletter delivery
xcomments and reactions from a logged-in audience
xthe editor and image hosting
Hashnode pricing
pro$5/mo · monthly flat · $60/yr
free tierThe free tier includes a full blog on a custom domain; Pro adds the API, headless mode and branding removal.
verified 2026-09-04 · source ↗
Is Hashnode free?
The free tier includes a full blog on a custom domain; Pro adds the API, headless mode and branding removal. Paid is Pro at $5/mo (checked 2026-09-04).
Vibecode Hashnode
Kinda. The core of Hashnode is buildable in a weekend with the prompt on this page, but there are real gaps: the developer network feed and its discovery, built-in newsletter delivery. Read the honest list above before committing.
How much does Hashnode cost?
Hashnode costs about $5/month (Pro, checked 2026-09-04), which is $60 per year.
What do I lose by replacing Hashnode?
Honestly: the developer network feed and its discovery; built-in newsletter delivery; comments and reactions from a logged-in audience; the editor and image hosting. If any of those are load-bearing for you, keep paying.
Is there an open-source alternative to Hashnode?
Yes: Astro (static site framework with content collections), WriteFreely (minimal self-hosted writing platform). Using prior art is also vibecoding; the prompt is for when you want it exactly your way.