[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f5NbmmkBLRD8mqBcYVLrUyhruUgJU_VLL7Fv-mgdvQaE":3},{"data":4},{"id":5,"slug":6,"title":7,"excerpt":8,"bodyHtml":9,"bodyMarkdown":10,"metaTitle":11,"metaDescription":12,"ogImageUrl":13,"seoScore":14,"publishedAt":15,"updatedAt":16},"7dc34b5b-4fb5-4763-8d6b-2dd3e299c7fa","how-it-all-links-together","How it all links together","One project's growth loop, end to end — the facts sheet, a post with its card, the first-touch that survives to a payment, a prospect found where indie devs launch, an email held for your yes, and the Command Center telling you what's next. Every step of it is now a tool an agent can call.","\u003Cp>Most marketing tools are a drawer of separate things. A writer here, a\nscheduler there, an analytics tab that has never heard of either. You do the\nlinking, in your head, on a Sunday.\u003C/p>\n\u003Cp>IndieBob is one loop, and the links are the product. This is that loop walked\nend to end on one project — every screen real, every command below run once\nbefore it was written down. At the end of each step is the same sentence in a\ndifferent costume: \u003Cstrong>this step is a tool an agent can call.\u003C/strong>\u003C/p>\n\u003Ch2>1. The facts sheet: one true description of your product\u003C/h2>\n\u003Cp>Nothing downstream is any good if the machine writing it is guessing about\nyour product. So the loop starts with a facts sheet: what the thing is, who\nit's for, what it costs, the claims you are willing to stand behind.\u003C/p>\n\u003Cp>\u003Cimg src=\"https://www.indiebob.com/screenshots/connect-guide-facts-desktop.png\" alt=\"The Connect step where a project's facts sheet is filled in\" />\u003C/p>\n\u003Cp>Every draft, every cold email, every social post is written from this sheet.\nIt's why a post about your app reads like your app, and why Bob doesn't invent\na feature you never shipped — the sheet is the only place claims come from.\u003C/p>\n\u003Cp>Connect verifies five steps and reports what it actually observed, not what\nyou ticked: SDK events, facts, revenue, publishing, first post.\u003C/p>\n\u003Ch2>2. A post, drafted and published — with its card\u003C/h2>\n\u003Cp>Write in the editor or ask Bob for a draft, then publish. The post hub is the\nartifact's own page: status, its live URL once traffic proves it, the SEO\naudit with an Apply button, and the distribution row.\u003C/p>\n\u003Cp>\u003Cimg src=\"https://www.indiebob.com/screenshots/post-hub-desktop.png\" alt=\"The post hub — status, live URL, performance, audit and distribution for one post\" />\u003C/p>\n\u003Cp>The share card is composed, not generated: your real logo, your real type,\nyour real capture at the venue's size. We don't let a model paint a picture of\nyour app — an invented screenshot is an invented claim, and it ships to\neveryone who sees the link.\u003C/p>\n\u003Cp>Over the API the same publish is two calls:\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-bash\">curl -X POST https://www.indiebob.com/api/v1/content/posts \\\n  -H \"Authorization: Bearer ib_sk_…\" -H 'Content-Type: application/json' \\\n  -d '{\"project\":\"my-app\",\"title\":\"How it all links together\",\"bodyMarkdown\":\"…\"}'\n\ncurl -X POST https://www.indiebob.com/api/v1/content/posts/&lt;id&gt;/publish \\\n  -H \"Authorization: Bearer ib_sk_…\"\n\u003C/code>\u003C/pre>\n\u003Cp>That is exactly how this post reached this page: markdown in the repo, pushed\nthrough \u003Ccode>POST /api/v1/content/posts\u003C/code> as a draft, read, then published. No\nspecial path for us.\u003C/p>\n\u003Ch2>3. The SDK: first touch, kept until it pays\u003C/h2>\n\u003Cp>Drop \u003Ccode>@indiebob/tracker\u003C/code> in your app and the loop closes. It's under 5 KB\ngzipped, sets no cookies, and its first job is to remember where somebody came\nfrom — the UTM, the referrer, the post they landed on — and keep it through\nsignup and through Stripe.\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-js\">import { IndieBob } from '@indiebob/tracker'\nconst bob = IndieBob.init({ projectId: 'proj_…' })\nbob.identify('user_123', { email: 'dev@example.com' })\n\u003C/code>\u003C/pre>\n\u003Cp>\u003Cimg src=\"https://www.indiebob.com/screenshots/sdk-guide-desktop.png\" alt=\"The SDK install guide inside a project's Connect path\" />\u003C/p>\n\u003Cp>That's what makes \"this post earned €X\" a fact rather than a vibe. The Earned\npage reads it back per post and per source, and where there is no data it says\nso with an em dash instead of a confident zero.\u003C/p>\n\u003Ch2>4. A prospect, found where indie devs actually launch\u003C/h2>\n\u003Cp>The other half of the loop is the people who haven't heard of you. Discovery\nreads the venues where products get launched and maintained and pulls out\nbusinesses that match your facts sheet, with the evidence of where each one\ncame from.\u003C/p>\n\u003Cp>Then Bob reads that prospect's own website and writes the subject, an opening\nabout their business, and one bridge sentence into your email. Your claims,\nyour CTA, your sign-off stay yours. The reading and the writing both happen on\nour own solar-powered, battery-backed AI farm — a prospect's website text\nnever leaves our hardware.\u003C/p>\n\u003Ch2>5. The email waits for a human\u003C/h2>\n\u003Cp>The first email to each prospect is held until you read it. Follow-ups approve\nthemselves.\u003C/p>\n\u003Cp>\u003Cimg src=\"https://www.indiebob.com/screenshots/outreach-review-queue-desktop.png\" alt=\"The review queue — first touches waiting for a human yes\" />\u003C/p>\n\u003Cp>If the rig is offline or the plan cap is hit, the touch waits with the reason\nshown in full. It never falls back to the generic template — sending the\nbland version is exactly the thing the feature exists to prevent. And what\nwent out is stored as it went out: subject, HTML, text, message id, per\nrecipient, forever.\u003C/p>\n\u003Ch2>6. Do Next: the loop's answer\u003C/h2>\n\u003Cp>The Command Center ranks what to do across every project, from the same data\nevery step above wrote.\u003C/p>\n\u003Cp>\u003Cimg src=\"https://www.indiebob.com/screenshots/site-do-next-desktop.png\" alt=\"The Command Center's Do Next list\" />\u003C/p>\n\u003Cp>Not a feed. A short ordered list where each row is a button into the tool that\ndoes it.\u003C/p>\n\u003Ch2>And now: your agent can run all of it\u003C/h2>\n\u003Cp>Here is the part that changed this week. Every step above is a capability with\na name, and the names are not marketing copy — they come from one registry\nfile in the codebase that is rendered five ways, so it cannot drift from the\nAPI it describes:\u003C/p>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Rendering\u003C/th>\n\u003Cth>Where\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>Markdown for a context window\u003C/td>\n\u003Ctd>\u003Ccode>https://www.indiebob.com/agents.md\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>JSON manifest\u003C/td>\n\u003Ctd>\u003Ccode>https://www.indiebob.com/.well-known/agents.json\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>The human docs page\u003C/td>\n\u003Ctd>\u003Ccode>https://www.indiebob.com/docs/agents\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>The API's own front door\u003C/td>\n\u003Ctd>\u003Ccode>GET /api/v1\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>MCP tool list\u003C/td>\n\u003Ctd>\u003Ccode>@indiebob/mcp\u003C/code>\u003C/td>\n\u003C/tr>\n\u003C/tbody>\u003C/table>\n\u003Cp>Thirteen tools, and you can read them off the published package yourself\nwithout an account:\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-bash\">echo '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}' \\\n  | INDIEBOB_API_KEY=ib_sk_x npx -y @indiebob/mcp\n\u003C/code>\u003C/pre>\n\u003Cpre>\u003Ccode>whoami          list_projects     read_metrics      next_actions\nlist_posts      get_post          create_post       publish_post\nlist_prospects  list_sequences    enroll_prospects  list_review_queue\napprove_message\n\u003C/code>\u003C/pre>\n\u003Cp>Read them against the loop and the map is one to one: \u003Ccode>list_projects\u003C/code> and\n\u003Ccode>read_metrics\u003C/code> for the numbers, \u003Ccode>create_post\u003C/code> and \u003Ccode>publish_post\u003C/code> for step 2,\n\u003Ccode>list_prospects\u003C/code> and \u003Ccode>enroll_prospects\u003C/code> for step 4, \u003Ccode>list_review_queue\u003C/code> and\n\u003Ccode>approve_message\u003C/code> for step 5, \u003Ccode>next_actions\u003C/code> for step 6.\u003C/p>\n\u003Cp>Three ways to wire it up. In Claude Code:\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-bash\">claude mcp add indiebob --env INDIEBOB_API_KEY=ib_sk_… -- npx -y @indiebob/mcp\n\u003C/code>\u003C/pre>\n\u003Cp>In Claude Desktop, open\n\u003Ca href=\"https://www.indiebob.com/mcp/indiebob.mcpb\">indiebob.mcpb\u003C/a> — it asks for your key\nand stores it in your system keychain. In any other MCP client, the same\n\u003Ccode>npx -y @indiebob/mcp\u003C/code> command in an \u003Ccode>mcpServers\u003C/code> block. The server is in the\nofficial MCP registry as \u003Ccode>io.github.chemic/indiebob\u003C/code>.\u003C/p>\n\u003Cp>It runs on your machine, not ours: a hosted endpoint would have to hold or\nbroker every user's key, and one leak would be everybody's prospect list. The\npackage has zero runtime dependencies and unpacks to about 22 KB.\u003C/p>\n\u003Ch2>What an agent deliberately cannot do\u003C/h2>\n\u003Cp>A capability list is only trustworthy if it has edges. These are ours, and\nthey are a feature:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Billing.\u003C/strong> No agent changes your plan or your card.\u003C/li>\n\u003Cli>\u003Cstrong>Key minting.\u003C/strong> An owner mints keys, in a browser, with their own login.\u003C/li>\n\u003Cli>\u003Cstrong>Project creation and settings.\u003C/strong> Including the facts sheet — the claims a\nmachine writes from are set by a person.\u003C/li>\n\u003Cli>\u003Cstrong>Sending.\u003C/strong> \u003Ccode>approve_message\u003C/code> approves a first touch; it does not send it.\nThe sequence's send window, daily cap and sending account still decide when\nit leaves.\u003C/li>\n\u003C/ul>\n\u003Cp>Scopes are granular and honest about refusal: a key without \u003Ccode>write:outreach\u003C/code>\ngets a 403 that names the scope it lacked, and a bad key gets a 401. Every id\nresolves inside the key owner's portfolio, so another account's project is a\n404 that looks exactly like a project that never existed.\u003C/p>\n\u003Ch2>The bottom of the stack\u003C/h2>\n\u003Cp>One last link, because people ask what this runs on. The AI writing your\nemails and your drafts runs on our own solar-powered, battery-backed farm —\nthat's why per-prospect personalisation is included rather than metered into\noblivion. Everything else — the app, the API an agent calls, the queue, and\nthe Postgres holding your events, posts, prospects and transactions — runs on\n\u003Cstrong>DigitalOcean App Platform and DigitalOcean's managed Postgres\u003C/strong>. It has been\na good place to put an indie product: push to deploy, a database with backups\nwe don't administer, and a bill that stays legible while the thing grows.\u003C/p>\n\u003Cp>Start at \u003Ca href=\"https://www.indiebob.com/docs/agents\">/docs/agents\u003C/a>, mint a key, and\npoint your agent at the loop.\u003C/p>\n\n\u003Cp data-indiebob-credit=\"1\">\u003Cem>\u003Ca href=\"https://www.indiebob.com/?ref=post-credit\" rel=\"noopener\">Written with IndieBob\u003C/a>\u003C/em>\u003C/p>","Most marketing tools are a drawer of separate things. A writer here, a\nscheduler there, an analytics tab that has never heard of either. You do the\nlinking, in your head, on a Sunday.\n\nIndieBob is one loop, and the links are the product. This is that loop walked\nend to end on one project — every screen real, every command below run once\nbefore it was written down. At the end of each step is the same sentence in a\ndifferent costume: **this step is a tool an agent can call.**\n\n## 1. The facts sheet: one true description of your product\n\nNothing downstream is any good if the machine writing it is guessing about\nyour product. So the loop starts with a facts sheet: what the thing is, who\nit's for, what it costs, the claims you are willing to stand behind.\n\n![The Connect step where a project's facts sheet is filled in](https://www.indiebob.com/screenshots/connect-guide-facts-desktop.png)\n\nEvery draft, every cold email, every social post is written from this sheet.\nIt's why a post about your app reads like your app, and why Bob doesn't invent\na feature you never shipped — the sheet is the only place claims come from.\n\nConnect verifies five steps and reports what it actually observed, not what\nyou ticked: SDK events, facts, revenue, publishing, first post.\n\n## 2. A post, drafted and published — with its card\n\nWrite in the editor or ask Bob for a draft, then publish. The post hub is the\nartifact's own page: status, its live URL once traffic proves it, the SEO\naudit with an Apply button, and the distribution row.\n\n![The post hub — status, live URL, performance, audit and distribution for one post](https://www.indiebob.com/screenshots/post-hub-desktop.png)\n\nThe share card is composed, not generated: your real logo, your real type,\nyour real capture at the venue's size. We don't let a model paint a picture of\nyour app — an invented screenshot is an invented claim, and it ships to\neveryone who sees the link.\n\nOver the API the same publish is two calls:\n\n```bash\ncurl -X POST https://www.indiebob.com/api/v1/content/posts \\\n  -H \"Authorization: Bearer ib_sk_…\" -H 'Content-Type: application/json' \\\n  -d '{\"project\":\"my-app\",\"title\":\"How it all links together\",\"bodyMarkdown\":\"…\"}'\n\ncurl -X POST https://www.indiebob.com/api/v1/content/posts/\u003Cid>/publish \\\n  -H \"Authorization: Bearer ib_sk_…\"\n```\n\nThat is exactly how this post reached this page: markdown in the repo, pushed\nthrough `POST /api/v1/content/posts` as a draft, read, then published. No\nspecial path for us.\n\n## 3. The SDK: first touch, kept until it pays\n\nDrop `@indiebob/tracker` in your app and the loop closes. It's under 5 KB\ngzipped, sets no cookies, and its first job is to remember where somebody came\nfrom — the UTM, the referrer, the post they landed on — and keep it through\nsignup and through Stripe.\n\n```js\nimport { IndieBob } from '@indiebob/tracker'\nconst bob = IndieBob.init({ projectId: 'proj_…' })\nbob.identify('user_123', { email: 'dev@example.com' })\n```\n\n![The SDK install guide inside a project's Connect path](https://www.indiebob.com/screenshots/sdk-guide-desktop.png)\n\nThat's what makes \"this post earned €X\" a fact rather than a vibe. The Earned\npage reads it back per post and per source, and where there is no data it says\nso with an em dash instead of a confident zero.\n\n## 4. A prospect, found where indie devs actually launch\n\nThe other half of the loop is the people who haven't heard of you. Discovery\nreads the venues where products get launched and maintained and pulls out\nbusinesses that match your facts sheet, with the evidence of where each one\ncame from.\n\nThen Bob reads that prospect's own website and writes the subject, an opening\nabout their business, and one bridge sentence into your email. Your claims,\nyour CTA, your sign-off stay yours. The reading and the writing both happen on\nour own solar-powered, battery-backed AI farm — a prospect's website text\nnever leaves our hardware.\n\n## 5. The email waits for a human\n\nThe first email to each prospect is held until you read it. Follow-ups approve\nthemselves.\n\n![The review queue — first touches waiting for a human yes](https://www.indiebob.com/screenshots/outreach-review-queue-desktop.png)\n\nIf the rig is offline or the plan cap is hit, the touch waits with the reason\nshown in full. It never falls back to the generic template — sending the\nbland version is exactly the thing the feature exists to prevent. And what\nwent out is stored as it went out: subject, HTML, text, message id, per\nrecipient, forever.\n\n## 6. Do Next: the loop's answer\n\nThe Command Center ranks what to do across every project, from the same data\nevery step above wrote.\n\n![The Command Center's Do Next list](https://www.indiebob.com/screenshots/site-do-next-desktop.png)\n\nNot a feed. A short ordered list where each row is a button into the tool that\ndoes it.\n\n## And now: your agent can run all of it\n\nHere is the part that changed this week. Every step above is a capability with\na name, and the names are not marketing copy — they come from one registry\nfile in the codebase that is rendered five ways, so it cannot drift from the\nAPI it describes:\n\n| Rendering | Where |\n|---|---|\n| Markdown for a context window | `https://www.indiebob.com/agents.md` |\n| JSON manifest | `https://www.indiebob.com/.well-known/agents.json` |\n| The human docs page | `https://www.indiebob.com/docs/agents` |\n| The API's own front door | `GET /api/v1` |\n| MCP tool list | `@indiebob/mcp` |\n\nThirteen tools, and you can read them off the published package yourself\nwithout an account:\n\n```bash\necho '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}' \\\n  | INDIEBOB_API_KEY=ib_sk_x npx -y @indiebob/mcp\n```\n\n```\nwhoami          list_projects     read_metrics      next_actions\nlist_posts      get_post          create_post       publish_post\nlist_prospects  list_sequences    enroll_prospects  list_review_queue\napprove_message\n```\n\nRead them against the loop and the map is one to one: `list_projects` and\n`read_metrics` for the numbers, `create_post` and `publish_post` for step 2,\n`list_prospects` and `enroll_prospects` for step 4, `list_review_queue` and\n`approve_message` for step 5, `next_actions` for step 6.\n\nThree ways to wire it up. In Claude Code:\n\n```bash\nclaude mcp add indiebob --env INDIEBOB_API_KEY=ib_sk_… -- npx -y @indiebob/mcp\n```\n\nIn Claude Desktop, open\n[indiebob.mcpb](https://www.indiebob.com/mcp/indiebob.mcpb) — it asks for your key\nand stores it in your system keychain. In any other MCP client, the same\n`npx -y @indiebob/mcp` command in an `mcpServers` block. The server is in the\nofficial MCP registry as `io.github.chemic/indiebob`.\n\nIt runs on your machine, not ours: a hosted endpoint would have to hold or\nbroker every user's key, and one leak would be everybody's prospect list. The\npackage has zero runtime dependencies and unpacks to about 22 KB.\n\n## What an agent deliberately cannot do\n\nA capability list is only trustworthy if it has edges. These are ours, and\nthey are a feature:\n\n- **Billing.** No agent changes your plan or your card.\n- **Key minting.** An owner mints keys, in a browser, with their own login.\n- **Project creation and settings.** Including the facts sheet — the claims a\n  machine writes from are set by a person.\n- **Sending.** `approve_message` approves a first touch; it does not send it.\n  The sequence's send window, daily cap and sending account still decide when\n  it leaves.\n\nScopes are granular and honest about refusal: a key without `write:outreach`\ngets a 403 that names the scope it lacked, and a bad key gets a 401. Every id\nresolves inside the key owner's portfolio, so another account's project is a\n404 that looks exactly like a project that never existed.\n\n## The bottom of the stack\n\nOne last link, because people ask what this runs on. The AI writing your\nemails and your drafts runs on our own solar-powered, battery-backed farm —\nthat's why per-prospect personalisation is included rather than metered into\noblivion. Everything else — the app, the API an agent calls, the queue, and\nthe Postgres holding your events, posts, prospects and transactions — runs on\n**DigitalOcean App Platform and DigitalOcean's managed Postgres**. It has been\na good place to put an indie product: push to deploy, a database with backups\nwe don't administer, and a bill that stays legible while the thing grows.\n\nStart at [/docs/agents](https://www.indiebob.com/docs/agents), mint a key, and\npoint your agent at the loop.\n","How IndieBob's growth loop links together — and how an agent runs it","A walk through one project's loop in IndieBob: facts sheet, published post, first-touch attribution, prospect discovery, a human-approved cold email, and Do Next — with the thirteen tools an agent can call to run the same loop over a scoped key.","https://www.indiebob.com/api/og/7672ce01-22f6-4076-9d59-5eee5faeb89e/7dc34b5b-4fb5-4763-8d6b-2dd3e299c7fa",null,"2026-09-08T09:08:38.831Z","2026-09-08T09:58:08.266Z"]