diff --git a/.claude/skills/author-post/kinds/idea.md b/.claude/skills/author-post/kinds/idea.md index 02dbf7598..fc1031391 100644 --- a/.claude/skills/author-post/kinds/idea.md +++ b/.claude/skills/author-post/kinds/idea.md @@ -60,6 +60,17 @@ capture the idea, why it appeals, and what's unresolved. If the idea is still a **`mature-content`** first — it interview-drives a rough idea to board-ready (motivation, value, scope, to-dos, success criteria) before you author. +**When the idea is a BUSINESS PLAN**, `blog-kinds.json` (`kinds.idea.sections`, profile +`business-plan`) declares the recommended body sections AND **the question each one answers**, the +canonical structure, so you don't reinvent it. The 14 sections run: the idea in one line · a name for +it · why compelling · the product · who it's for · market and competition · business model · pricing +sketch · go to market · unit economics · roadmap · open questions and risks · success criteria · next +step. These are **recommended, not required**: `validate-post-outline.js` warns (`missing-section`, +never blocks) only when a post already reads like a business plan and is missing one. You may RENAME a +section's heading, keep its identity by pinning the anchor, `## My Title {#unit-economics}`. The +**`pressure-test-business-idea`** skill produces exactly this shape; read `kinds.idea.sections` (each +section's `question` + `guidance`) as the source of truth for what each section should answer. + ## Validate + hand-offs - Gates: `make validate-naming` (title voice), `make validate-idea-tags` (board tag glosses), diff --git a/.claude/skills/manage-kinds/SKILL.md b/.claude/skills/manage-kinds/SKILL.md index ddbf313f7..c01e51373 100644 --- a/.claude/skills/manage-kinds/SKILL.md +++ b/.claude/skills/manage-kinds/SKILL.md @@ -35,7 +35,21 @@ its consumers. - **`outline`** — the structural elements the post should contain, each `{id, label}`. The `id` maps to a TEST in `validate-post-outline.js`'s `CHECKS`; the `label` is the human contract text. Reuse an existing `id` (e.g. `description`, `sections`, `mockup`, `decisions`) when the check already - exists — only a genuinely new structural requirement needs a new `id` + a new test. + exists — only a genuinely new structural requirement needs a new `id` + a new test. `outline` is + the HARD gate (a missing element warns per-post). +- **`sections`** (OPTIONAL) — the recommended BODY sections + **the question each answers**, each + `{anchor, heading, question, guidance}`. Encodes the CLAUDE.md "frame each section around its + question" convention as data. **`anchor`** is the STABLE identity (the heading's slug); **`heading`** + is the DEFAULT title a post MAY OVERRIDE; **`question`** is what the section answers; **`guidance`** + is the one-line how-to. A companion **`sectionsProfile`** string (e.g. `"business-plan"`) + a + **`sectionsNote`** say WHEN the sections apply. Unlike `outline`, `sections` is RECOMMENDED not + gated: `validate-post-outline.js` warns (`missing-section`, never blocks) only for a post that + MATCHES the `sectionsProfile` (so a small idea isn't nagged to write a full plan). A post satisfies + a section by a heading whose slug matches `anchor`, or, if it RENAMED the heading, by pinning the + anchor with Docusaurus's `## New Title {#anchor}` syntax. NOTE the blog collections the outline + + sections checks apply to: `blog`/`designs`/`thoughts`/`mindset`/`questions` (the `isBlogPost` + + `DEFAULT_DIRS` set in the validator). Worked example: `idea` carries a 14-section `business-plan` + profile. ## Who consumes it (do NOT hand-maintain a parallel copy anywhere) diff --git a/.claude/skills/pressure-test-business-idea/SKILL.md b/.claude/skills/pressure-test-business-idea/SKILL.md new file mode 100644 index 000000000..5efab55cc --- /dev/null +++ b/.claude/skills/pressure-test-business-idea/SKILL.md @@ -0,0 +1,157 @@ +--- +name: pressure-test-business-idea +description: Stress-test a business idea against four moves BEFORE building it, then capture it as a board-ready /thoughts idea post. Put any idea through wedge-first (find the single cheapest entry product that still tests the core bet), honest-numbers (never invent financials — name the two or three real numbers that decide it and mark them as blockers), accumulation-moat (ask what the customer builds up over time that makes leaving painful, and whether it is real on day one or a bet to earn), and a Phase-0 pull test (the cheapest experiment that proves people WANT it, run before building durable layers). Output is a decisive readout: the wedge, the blocking numbers, the moat honesty, the Phase-0 test, and a go/kill/park call. TRIGGERS when the user shares a business idea, a product concept, a "what if I built/sold X" braindump, a monetization plan, or asks "is this a good business idea?", "should I build this?", "how do I validate this?", "pressure-test this idea", "poke holes in this business". Hands the surviving idea to organize-post + author-post to write it up as a `kind: idea` /thoughts post that boards on the Ideas board (via groom-initiatives). Worked examples: the snap-on coaster business + the dump-and-organize todo agent (both /thoughts idea posts). Pairs with organize-post, author-post, mature-content, groom-initiatives. +--- + +# Pressure-test a business idea + +Every business idea arrives sounding good. The job of this skill is to find out whether it *is* good +before real money and months get spent proving it is not. It puts an idea through **four moves, in +order**, that turn an exciting pitch into a plan you can act on or kill, then hands the survivor off +to be written up as a `/thoughts` idea post. + +This is a JUDGMENT skill, not a transformer. You run the four moves as a short interview + analysis, +and produce a structured readout. It is deliberately honest: a named-but-thin moat is a finding, not a +failure, and an idea that fails a move just got cheaper to walk away from. + +## When to reach for it + +The user shares a business idea, a product concept, a "what if I built/sold X" braindump, a +monetization plan, or asks any of: "is this a good business idea?", "should I build this?", "how do I +validate this?", "pressure-test / poke holes in this idea." If they just want it *filed* (not +stress-tested), that is `organize-post`; if it is already validated and they want it *written up*, +that is `author-post`. This skill is the thinking in between. + +## The four moves (run them in this order — the order is the point) + +The moves are ordered on purpose. The wedge tells you WHAT to test. Honest-numbers tells you the BAR +it has to clear. The moat question tells you whether winning the wedge is WORTH anything. The Phase-0 +test is HOW you find out, cheaply, before committing. Run them out of order and you build the family +before you know anyone wants the wedge. + +### 1. Wedge-first — find the cheapest thing to validate + +An idea usually contains a whole FAMILY of products. The instinct is to describe the family; the +discipline is to find the single cheapest, lowest-risk entry point that still tests the core bet, and +plan to launch only that. + +- Ask: *what is the smallest, cheapest, lowest-risk thing I could ship that still tells me whether the + whole idea works?* +- The wedge is NOT "phase one of the roadmap." It is the one thing whose success or failure tells you + whether the rest is worth building. If the wedge fails, the family was never going to work, and you + found out cheap. +- Tell of a good wedge: cheap to make, easy to try, universal, and it exercises the CORE mechanic (not + a side feature). + +> Coaster example: a single coaster is the wedge for a whole line of coffee accessories (cheap, +> giftable, universal, ships for almost nothing). Agent example: the MVP connector with just the core +> recording tools is the wedge for the graph, the blog, and the upsell engine. + +### 2. Honest-numbers — never invent the financials + +The fastest way to fool yourself is to fill the unit-economics section with plausible numbers. A +made-up margin makes ANY idea pencil out. + +- The rule: where a real number is needed and you do not have it, do NOT guess. Name the number that + has to be gotten, and mark it as the blocker. +- The output of this move is not a spreadsheet. It is a short list of the **two or three real numbers + that decide the business**, plus an admission that the plan is provisional until they exist. +- Typical blocking numbers: landed/unit cost, cost-to-serve per active user, CAC vs LTV, repeat + rate / churn. + +> Coaster: the blocking number is landed cost per piece from a real manufacturing quote — pricing, +> margin, viability all wait on it. Agent: the cost to run the orchestration + hosting layer per +> active user, knowable only from a running MVP. + +### 3. Accumulation-moat — what does the customer build up over time? + +A product is easy to copy. What is hard to copy is whatever the CUSTOMER accumulates by using it, +because a competitor starting from zero cannot hand a new user that history. + +- Ask: *what does a customer build up here that makes leaving painful, and is that moat real on day + one or a bet I have to earn?* +- Be as honest here as in the numbers. A thin day-one moat is a finding. Distinguish the moat you get + for FREE (real on day one) from the moats you must deliberately BUILD (network effects, data + effects, a recipe/marketplace ecosystem). + +> Coaster: the collection of snap-together pieces a customer owns (makes the next accessory relevant). +> Agent: the accumulated knowledge graph + organized corpus living in one place (real-ish day one), +> plus cross-linked public blogs + a filing-recipe marketplace (bets to build). For the agent you must +> admit "an agent that files notes is easy to clone" and that the stronger moats are things to build. + +### 4. Phase-0 pull test — prove demand before building anything durable + +Design the cheapest possible experiment that proves people WANT the thing, and run it before building +the durable layers. + +- Usually: a landing page + a demo + a real ask (join the list, pre-order, sign up), with a + **threshold set in advance**. +- The point is to separate "this is possible" from "people want this." Possible is cheap; wanted is + the whole question. If the pull is not there, no amount of building fixes it. +- Define the threshold BEFORE running it, so the result is a verdict, not a rationalization. + +> Both example ideas end on the same next step: get the one blocking cost number, and run a Phase-0 +> pull test, before tooling up or building the graph. + +## How to run it + +1. **Read the idea whole.** Note the core bet (the one thing that has to be true for this to be a + business) and the family of products hiding inside it. +2. **Walk the four moves in order**, asking the user sharp questions where you cannot infer the answer + (what is the cheapest wedge? what number do you not have? what accumulates? what is the cheapest + proof of demand?). Do not invent financials — name the blockers. +3. **Be decisive and honest.** Name a thin moat as thin. Name the single biggest risk. The value is + making the idea LEGIBLE: a short list of what must be true, the numbers that decide it, and the + cheap experiment that would kill it. +4. **Produce the readout** (shape below). +5. **Make the go/kill/park call**, then hand off: a surviving idea → `organize-post` (confirm it is an + unactioned `kind: idea`) → `author-post` (`homes/thoughts.md` + `kinds/idea.md`) to write it up as + a `/thoughts` post that boards on the Ideas board (`board: ideas`, via `groom-initiatives`). A raw + idea that needs firming first → `mature-content`. + +> **The written-up post's SECTIONS are codified.** When the idea becomes a `/thoughts` post, its +> recommended body structure lives in `blog-kinds.json` (`kinds.idea.sections`, profile +> `business-plan`): 13 sections, each with the QUESTION it answers and one-line guidance. Follow that +> structure so the post is complete and consistent with its siblings; `validate-post-outline.js` warns +> (`missing-section`, warn-tier) if a business-plan-shaped post skips one. The four pressure-test moves +> map onto those sections: the WEDGE → the product + go-to-market; the NUMBERS → unit economics + +> pricing sketch; the MOAT → market/competition + open questions and risks; the PHASE-0 TEST → success +> criteria + next step. + +## The output shape + +``` +PRESSURE TEST: +CORE BET: + +1. WEDGE: +2. BLOCKING NUMBERS: +3. MOAT: ; biggest risk: <...> +4. PHASE-0 TEST: + +CALL: GO (worth the next dollar) | KILL (fails move N because …) | PARK (blocked on ) +NEXT: + ; then hand to organize-post → author-post +``` + +Keep the call decisive. An idea that survives all four moves is not *proven*, but it is worth the next +dollar. One that fails any of them just got a lot cheaper to walk away from. + +## Worked examples (in this repo) + +Two ideas were put through this method in one sitting — products that could not be less alike, but the +four moves are visible in both, which is the whole reason this is a skill and not a one-off: + +- **Snap-on Islamic-art coasters** (`bytesofpurpose-blog/thoughts/2026-07-11-idea-islamic-art-coasters.md`) + — a physical-product wedge (the coaster), a manufacturing-cost blocker, an accessory-collection moat. +- **Dump-and-organize todo agent** (`bytesofpurpose-blog/thoughts/2026-07-11-idea-todo-agent.md`) — a + software-connector wedge (the MVP), a run-cost blocker, a platform-dependency risk, a corpus+graph + moat (with portability-by-design as the hedge). + +## Cross-links + +- **`organize-post`** — confirm the survivor is an unactioned `kind: idea` (vs already an initiative). +- **`author-post`** (`homes/thoughts.md`, `kinds/idea.md`) — write the idea up; title must read as an + OPEN QUESTION ("Should I build X?"), no em-dashes, board frontmatter. +- **`groom-initiatives`** — the Ideas-board contract (`board: ideas`, `stage`, `priority`); advancing + the card when the idea graduates to an `/initiatives` project. +- **`mature-content`** — firm up a raw idea (motivation/value/scope/to-dos) before authoring. diff --git a/bytesofpurpose-blog/scripts/lib/blog-kinds.json b/bytesofpurpose-blog/scripts/lib/blog-kinds.json index f67090622..af3169305 100644 --- a/bytesofpurpose-blog/scripts/lib/blog-kinds.json +++ b/bytesofpurpose-blog/scripts/lib/blog-kinds.json @@ -1,5 +1,5 @@ { - "__doc__": "SINGLE SOURCE OF TRUTH for the blog post-kind taxonomy. Each kind declares its sidebar `emoji`, a one-line `description`, and an `outline` (the structural elements a post of that kind should contain). A post's emoji reflects its KIND (document type), not its topic, so the Posts sidebar is scannable by type. CONSUMERS: scripts/validate-post-outline.js reads emoji/description/outline from here; the draft-docs plugin reads `emoji` to prepend it to the sidebar label; the validate-post-outline-hook surfaces these on a finding; the / blog-ui components render the kind legends; the 'Start Here' post mirrors the kind->emoji table (drift-checked). THE THOUGHTS-vs-MINDSET MODEL: a THOUGHT is an idea that OCCURRED to me (a /thoughts post). A thought has three graduation paths: act on it -> an /initiatives INITIATIVE; deliberately ADOPT it to shape how I think -> a /mindset MINDSET post; distill it into durable knowledge -> a /craft doc. So two collection flags: `thought: true` + `thoughtGloss` mark the kinds of a /thoughts post (the ideas that occurred to me: idea, simulation, prediction, critique, design-story); `mindset: true` + `mindsetGloss` mark the kinds of a /mindset post (the curated inputs I keep to shape my thinking: question-set, quote-set, principle). A kind is one or the other, never both. LOCKSTEP: to add/change a kind, edit (1) this file, (2) a matching CHECKS entry in validate-post-outline.js if it has a new outline id, (3) the Start Here legend table, (4) the Thoughts legend if `thought: true` / the Mindset legend if `mindset: true`. Mirrors the docs emoji system (scripts/lib/emoji-map.json).", + "__doc__": "SINGLE SOURCE OF TRUTH for the blog post-kind taxonomy. Each kind declares its sidebar `emoji`, a one-line `description`, an `outline` (the structural elements a post of that kind should contain), and OPTIONALLY a `sections` array (the recommended BODY sections + the question each answers). A `sections` entry is {anchor, heading, question, guidance}: `anchor` is the STABLE identity (the heading's slug; a post satisfies the section by a heading whose slug matches `anchor`, or by pinning it via `## Title {#anchor}`), `heading` is the DEFAULT title a post MAY OVERRIDE, `question` is what that section answers (the CLAUDE.md 'frame each section around its question' convention made data), `guidance` is the one-line how-to. `sections` is RECOMMENDED not gated: validate-post-outline.js warns (never blocks) when a post that MATCHES the kind's `sectionsProfile` (e.g. a business-plan-shaped idea) is missing recommended sections; `sectionsNote` explains when the sections apply. The hard gate stays `outline`. A post's emoji reflects its KIND (document type), not its topic, so the Posts sidebar is scannable by type. CONSUMERS: scripts/validate-post-outline.js reads emoji/description/outline from here; the draft-docs plugin reads `emoji` to prepend it to the sidebar label; the validate-post-outline-hook surfaces these on a finding; the / blog-ui components render the kind legends; the 'Start Here' post mirrors the kind->emoji table (drift-checked). THE THOUGHTS-vs-MINDSET MODEL: a THOUGHT is an idea that OCCURRED to me (a /thoughts post). A thought has three graduation paths: act on it -> an /initiatives INITIATIVE; deliberately ADOPT it to shape how I think -> a /mindset MINDSET post; distill it into durable knowledge -> a /craft doc. So two collection flags: `thought: true` + `thoughtGloss` mark the kinds of a /thoughts post (the ideas that occurred to me: idea, simulation, prediction, critique, design-story); `mindset: true` + `mindsetGloss` mark the kinds of a /mindset post (the curated inputs I keep to shape my thinking: question-set, quote-set, principle). A kind is one or the other, never both. LOCKSTEP: to add/change a kind, edit (1) this file, (2) a matching CHECKS entry in validate-post-outline.js if it has a new outline id, (3) the Start Here legend table, (4) the Thoughts legend if `thought: true` / the Mindset legend if `mindset: true`. Mirrors the docs emoji system (scripts/lib/emoji-map.json).", "kinds": { "idea": { "emoji": "💡", @@ -8,6 +8,24 @@ "thoughtGloss": "Something I might build or do", "outline": [ {"id": "description", "label": "a non-empty `description:` frontmatter (powers the social card + share text)"} + ], + "sectionsProfile": "business-plan", + "sectionsNote": "An idea is deliberately LIGHT: the only gate is a non-empty `description:`. The `sections` below are the RECOMMENDED body when the idea is a BUSINESS PLAN (the shape the pressure-test-business-idea skill produces); they are guidance, warn-tier not blocking. A post SATISFIES a section by having a heading whose slug matches `anchor` OR whose text matches `heading`; `heading` is the DEFAULT title and a post may OVERRIDE it (pin the anchor with `## New Title {#anchor}`). Skip any that don't apply to a smaller idea. The warn only fires for a post that looks like a business plan (see validate-post-outline.js matchesSectionsProfile).", + "sections": [ + {"anchor": "the-idea-in-one-line", "heading": "The idea in one line", "question": "What is this, in one sentence I could pitch?", "guidance": "The whole concept compressed to a line, including the core mechanic and the double meaning if there is one."}, + {"anchor": "a-name-for-it", "heading": "A name for it", "question": "What do we call it, and what does the name lean on?", "guidance": "A few name candidates, each leaning on a different part of the pitch (the input, the mechanism, the payoff). Naming the payoff usually wins. Optional; a small idea may skip it."}, + {"anchor": "why-this-is-compelling", "heading": "Why this is compelling", "question": "Why is this worth doing, and why now?", "guidance": "The thesis: the insight, the timing, the unfair fit. A few bullets, each a distinct reason."}, + {"anchor": "the-product", "heading": "The product", "question": "What exactly does it do / what am I selling?", "guidance": "The product itself, its lines or tiers, and the through-line that connects them."}, + {"anchor": "who-it-is-for", "heading": "Who it is for", "question": "Who is the customer, and what pulls them in?", "guidance": "The target segments, named concretely, with the felt need each has."}, + {"anchor": "market-and-competition", "heading": "Market and competition", "question": "Who else does this, and what is my wedge into the space?", "guidance": "The adjacent players, the gap none of them owns, and the one risk to test early."}, + {"anchor": "business-model", "heading": "Business model", "question": "How does it make money, and how does that scale?", "guidance": "The revenue mechanism, the tiers, the metering, and the repeat-purchase or retention engine. Note any STRATEGY BRANCH that reshapes the economics (e.g. bring-your-own-model vs on-device inference)."}, + {"anchor": "pricing-sketch", "heading": "Pricing sketch", "question": "What would I charge, and what has to be true for that to work?", "guidance": "Price points to VALIDATE not commit; be honest that real pricing needs cost data."}, + {"anchor": "go-to-market", "heading": "Go to market", "question": "How do the first customers find and try it?", "guidance": "The launch channel, the wedge product to lead with, and the demand-capture (email/list) from day one."}, + {"anchor": "unit-economics", "heading": "Unit economics", "question": "What are the real numbers that decide whether this is a business?", "guidance": "Name the 2-3 blocking numbers (landed cost / cost-to-serve / CAC vs LTV / churn). Do NOT invent figures; mark each 'to get'."}, + {"anchor": "roadmap", "heading": "Roadmap", "question": "What is the phased path from validation to scale?", "guidance": "Phase 0 (validate pull) then wedge launch then expansion then moat, each phase a distinct learning."}, + {"anchor": "open-questions-and-risks", "heading": "Open questions and risks", "question": "What could kill this, and what don't I know yet?", "guidance": "The honest unknowns, the biggest risk named first, and where the moat is thin. A strategy branch that DE-RISKS others (e.g. on-device inference cutting both privacy and platform risk) belongs here too."}, + {"anchor": "success-criteria", "heading": "Success criteria", "question": "How will I know it's working (measurably)?", "guidance": "Thresholds set in advance: a Phase-0 pull bar, a working prototype, economics that pencil out, a launch that sells through."}, + {"anchor": "next-step", "heading": "Next step", "question": "What is the single cheapest next action?", "guidance": "The one or two things to do first (usually: get the blocking number + run the Phase-0 pull test) before anything else."} ] }, "question-set": { diff --git a/bytesofpurpose-blog/scripts/validate-post-outline.js b/bytesofpurpose-blog/scripts/validate-post-outline.js index 9c96f3844..3aafaedba 100644 --- a/bytesofpurpose-blog/scripts/validate-post-outline.js +++ b/bytesofpurpose-blog/scripts/validate-post-outline.js @@ -16,6 +16,10 @@ * a new outline id) — you do NOT hand-edit a rules list here. * * Findings (all warn-tier — advisory, never blocks): + * - missing-section: a post that fits a kind's `sectionsProfile` (e.g. a business-plan-shaped + * idea) is missing a recommended body section. Matched on the section `anchor` (a post MAY + * rename the heading — the anchor is the stable identity, pinnable via `## Title {#anchor}`). + * Recommended, not required. * - missing-kind a blog post with no `kind:` (kind drives the sidebar emoji + contract) * - unknown-kind a `kind:` not in blog-kinds.json * - long-sidebar-label the sidebar entry (sidebar_label || title) is > ~3 content words @@ -38,7 +42,7 @@ const path = require('path'); const matter = require('gray-matter'); const ROOT = path.join(__dirname, '..'); -const DEFAULT_DIRS = ['blog', 'designs', 'docs']; +const DEFAULT_DIRS = ['blog', 'designs', 'docs', 'thoughts', 'mindset', 'questions']; // The canonical blog-kind taxonomy is the SINGLE SOURCE OF TRUTH in lib/blog-kinds.json: // each kind declares {emoji, description, outline:[{id,label}]}. We read it here so the @@ -97,6 +101,61 @@ function contentWordCount(text) { const hasH2 = (body) => /^##\s+\S/m.test(body); +// Slugify a heading the way Docusaurus (github-slugger) does for anchor ids: lowercase, +// strip anything but word chars / spaces / hyphens, collapse spaces to single hyphens. +// Good enough to match a section `anchor` against a post's real headings. +function slugifyHeading(text) { + return text + .trim() + .toLowerCase() + .replace(/[^\w\s-]/g, '') + .replace(/\s+/g, '-') + .replace(/-+/g, '-') + .replace(/^-|-$/g, ''); +} + +// All ATX headings (## … ######) in a body, as {slug, text}. Skips fenced code blocks so a +// commented "## x" inside a code fence isn't read as a heading. Honors an EXPLICIT Docusaurus +// anchor override `## Custom Title {#pinned-anchor}` — the pinned id becomes the slug, so a +// post can RENAME a recommended section's heading while keeping its stable anchor identity. +function extractHeadings(body) { + const out = []; + let inFence = false; + for (const line of body.split('\n')) { + if (/^\s*```/.test(line)) { + inFence = !inFence; + continue; + } + if (inFence) continue; + const m = /^#{2,6}\s+(.+?)\s*$/.exec(line); + if (!m) continue; + let text = m[1].trim(); + const pinned = /\{#([\w-]+)\}\s*$/.exec(text); + if (pinned) { + text = text.replace(/\s*\{#[\w-]+\}\s*$/, '').trim(); + out.push({slug: pinned[1], text}); // explicit anchor wins + } else { + out.push({slug: slugifyHeading(text), text}); + } + } + return out; +} + +// A recommended-section profile only warns for a post that actually FITS the profile, so a +// small "I might build X" idea isn't nagged to write a 14-section business plan. The +// business-plan profile: the post says so (description/tags mention "business"), or it already +// reads like one (has several of the plan's signature sections). +function matchesSectionsProfile(profile, fm, headings) { + if (profile !== 'business-plan') return false; + const hay = `${fm.description || ''} ${(fm.tags || []).join(' ')}`.toLowerCase(); + if (/\bbusiness\b/.test(hay)) return true; + const planAnchors = new Set([ + 'business-model', 'unit-economics', 'go-to-market', 'pricing-sketch', 'market-and-competition', + ]); + const hits = headings.filter((h) => planAnchors.has(h.slug)).length; + return hits >= 2; // reads like a business plan already +} + // CHECKS: the TEST LOGIC for each outline element, keyed by the `id` declared in // blog-kinds.json. The JSON owns WHAT each kind requires (the legend authors + the hook // read); this registry owns HOW to detect it (functions can't live in JSON). When you add @@ -272,8 +331,10 @@ function checkFile(file) { } const kind = parsed.data && parsed.data.kind; const findings = []; - // Only enforce the kind vocabulary for BLOG posts (docs use their own kind words). - const isBlogPost = /\/(blog|designs)\//.test(file); + // Only enforce the kind vocabulary for BLOG posts (docs use their own kind words). The blog + // collections are the /initiatives feed (blog/), designs/, and the three temporal-thought + // instances (thoughts/, mindset/, questions/) — all declare a `kind:` from blog-kinds.json. + const isBlogPost = /\/(blog|designs|thoughts|mindset|questions)\//.test(file); // A blog post with NO `kind:` can't get a type-based sidebar emoji. Show the full legend // (emoji + description per kind) so the author can pick the right one inline. @@ -333,18 +394,49 @@ function checkFile(file) { } } - if (!OUTLINES[kind]) return findings; // no outline contract for this kind - for (const check of OUTLINES[kind]) { - if (!check.test(parsed.data, parsed.content)) { - findings.push({ - file: path.relative(ROOT, file), - kind, - id: check.id, - detail: - `kind: ${kind} post is missing ${check.label}\n` + - ` (a ${KINDS[kind].emoji} ${kind} post should have:\n${outlineExpectations(kind)}\n` + - ` ...or the kind may be wrong for this post. source: scripts/lib/blog-kinds.json)`, - }); + if (OUTLINES[kind]) { + for (const check of OUTLINES[kind]) { + if (!check.test(parsed.data, parsed.content)) { + findings.push({ + file: path.relative(ROOT, file), + kind, + id: check.id, + detail: + `kind: ${kind} post is missing ${check.label}\n` + + ` (a ${KINDS[kind].emoji} ${kind} post should have:\n${outlineExpectations(kind)}\n` + + ` ...or the kind may be wrong for this post. source: scripts/lib/blog-kinds.json)`, + }); + } + } + } + + // Recommended-SECTIONS check (warn-tier): if the kind declares `sections` and this post fits + // the kind's `sectionsProfile`, nudge on any recommended section whose `anchor` (or default + // `heading`) has no matching heading in the post. A post MAY override a section's title, so we + // match on the anchor slug first, then fall back to the default heading text. Never blocks. + const kindDef = KINDS[kind] || {}; + if (isBlogPost && Array.isArray(kindDef.sections) && kindDef.sections.length) { + const headings = extractHeadings(parsed.content); + if (matchesSectionsProfile(kindDef.sectionsProfile, parsed.data, headings)) { + const headingSlugs = new Set(headings.map((h) => h.slug)); + const headingTexts = new Set(headings.map((h) => h.text.toLowerCase())); + const missing = kindDef.sections.filter( + (s) => !headingSlugs.has(s.anchor) && !headingTexts.has((s.heading || '').toLowerCase()), + ); + if (missing.length) { + findings.push({ + file: path.relative(ROOT, file), + kind, + id: 'missing-section', + detail: + `kind: ${kind} post reads like a "${kindDef.sectionsProfile}" but is missing recommended section(s):\n` + + missing + .map((s) => ` · ${s.heading} (#${s.anchor}) — answers: ${s.question}`) + .join('\n') + + `\n (recommended, not required; a post MAY rename a section — the anchor is the identity.\n` + + ` source: scripts/lib/blog-kinds.json → kinds.${kind}.sections)`, + }); + } } } return findings; diff --git a/bytesofpurpose-blog/src/lib/idea-tags.ts b/bytesofpurpose-blog/src/lib/idea-tags.ts index 3d042def1..de054b381 100644 --- a/bytesofpurpose-blog/src/lib/idea-tags.ts +++ b/bytesofpurpose-blog/src/lib/idea-tags.ts @@ -79,6 +79,20 @@ export const IDEA_TAG_GLOSS: Record = { 'ab-testing': 'Running an A/B test to compare two variants on real users.', experiments: 'A/B experiments run on the site to learn what works.', posthog: 'PostHog, the product-analytics tool I use for events and experiments.', + + // Business & physical products (the entrepreneurship thread) + business: 'A business idea: turning a concept into something that could make money.', + 'physical-product': 'A tangible, manufactured product rather than software.', + ecommerce: 'Selling directly to customers online.', + shopify: 'The Shopify platform for running a direct-to-consumer store.', + 'islamic-art': 'Islamic geometric art as a design and product language.', + coffee: 'The coffee ritual and the accessories around it.', + + // AI products & connectors (the AI-business thread) + saas: 'Software sold as a subscription service.', + 'ai-agents': 'Autonomous AI agents that do multi-step work on your behalf.', + mcp: 'The Model Context Protocol: connectors that plug tools into Claude and other clients.', + 'knowledge-management': 'Capturing, organizing, and resurfacing what you know.', }; /** The tooltip text for a tag — its gloss, or a graceful generic fallback. */ diff --git a/bytesofpurpose-blog/thoughts/2026-07-11-idea-islamic-art-coasters.mdx b/bytesofpurpose-blog/thoughts/2026-07-11-idea-islamic-art-coasters.mdx new file mode 100644 index 000000000..243b15025 --- /dev/null +++ b/bytesofpurpose-blog/thoughts/2026-07-11-idea-islamic-art-coasters.mdx @@ -0,0 +1,278 @@ +--- +slug: idea-islamic-art-coasters +title: 'Should I Build a Snap-On Islamic-Art Coaster Business?' +sidebar_label: 'Islamic-art coasters?' +description: 'A business plan for the "LEGO of Islamic art": modular snap-together coasters and coffee accessories, starting with a Shopify store, that let people decorate the products they already own.' +authors: [oeid] +tags: [ideas, business, physical-product, ecommerce, shopify, islamic-art, coffee] +date: 2026-07-11 +kind: idea +board: ideas +stage: backlog +priority: low +draft: true +questions: + - What would a snap-on Islamic-art coaster business actually look like? + - Is there a real market for modular accessories that decorate products you already own? + - How would I launch and validate it on Shopify without much upfront cost? +--- + +What if Islamic art was a system you could build with, not just a pattern printed on a thing? The +idea: modular, snap-together pieces (the "LEGO of Islamic art") that let people compose their own +geometry and clip it onto the products they already love. The first product is the humblest one: +a coaster that snaps together and snaps on. + + + +## The idea in one line + +Sell modular Islamic-geometry pieces that snap together into coasters (and later, a family of +coffee accessories), sold direct-to-consumer through a Shopify store. Buy them as finished coasters, +or buy the pieces and build your own. + +The double meaning of "snap on" is the whole product: pieces snap **to each other** (modularity), +and the finished piece snaps **onto** something you own (a mug, a tray, a shelf edge). You are not +buying decor, you are buying a small kit for decorating the things already in your life. + +## A name for it + +Name candidates, each leaning on a different part of the pitch: + +- **Snap Coasters** (the plain front-runner): names the MECHANIC and the wedge product. Clear, easy + to say, obviously what it is. The risk is that it undersells the modular system beyond coasters. +- **Rosette** / **Girih**: lean on the Islamic-geometry heritage (a girih is the tile system the art + is built from). Evocative and ownable, but needs explaining to a Western buyer. +- **Snap Souk** / **Souk Tiles**: pair the snap mechanic with the marketplace feel. Warm, but "souk" + may read as generic Middle-Eastern branding rather than modern. +- **Tessellate**: names the pattern-making act itself. Elegant and distinctive, but abstract, it does + not say "coaster" or "gift". + +The call is whether to name the wedge (Snap Coasters), the heritage (Girih, Rosette), or the act +(Tessellate). Leading with the wedge is safest for launch; the heritage name is the stronger brand if +the system grows past coasters. + +## Why this is compelling + +:::warning[The pain today] +Islamic-art home goods force a bad choice: mass-produced and generic, or beautiful, artisanal, and +expensive. Neither lets you make the piece your own, and neither works with the products you already +have. You buy another standalone object, or you buy nothing. +::: + +:::tip[The relief] +A modular snap system is mid-price, playful, and personal: compose your own geometry, then clip it +onto the mug, tray, or shelf you already love. You decorate your current life instead of replacing it. +::: + +- **Islamic geometric art is inherently modular.** It is built from a small set of repeating units + tiled by rule. That is exactly the property that makes a snap-together toy system work, so the art + form and the product mechanic are a natural fit rather than a gimmick. +- **Accessories ride on love you already have.** People do not need another standalone object. They + do have a coffee setup, a desk, a prayer space, a shelf, that they want to make feel like theirs. + Positioning as "accessories to the products you already love" lowers the emotional and practical + bar to buy. +- **Coasters are a perfect wedge.** Low price, low risk, universally useful, giftable, and small + enough to ship cheaply. A coaster is the cheapest way to get someone to try the system. +- **A build-it dimension creates engagement and repeat purchase.** If the pieces are a system, one + purchase is a doorway. People come back for more pieces, new patterns, seasonal sets, and the next + accessory in the family. +- **Underserved aesthetic + gifting demand.** Islamic-art home goods skew either mass-produced and + generic, or expensive and artisanal. A modern, modular, mid-price, playful take is a gap, and it + has a strong built-in gifting occasion set (Ramadan, Eid, weddings, housewarmings). + +## The product + +**Line 1: The coaster (the wedge).** A coaster you can buy finished, or assemble from a handful of +snap-together tiles that lock into a geometric rosette. Sold as singles, as a set of four or six, and +as a "builder pack" of loose pieces plus a base ring. + +**Line 2: The coffee-accessory family (the expansion).** Once the snap system proves out, extend it +across the coffee ritual: a trivet or mat, a mug collar or sleeve, a spoon rest, a small tray edge, a +canister label frame. Each is the same snap mechanic in a new form factor, so the customer's existing +pieces stay relevant. + +**Line 3: The accessory-to-what-you-own play (the moat).** Attachments that clip onto products people +already own rather than replacing them. This is the differentiator: you are decorating the customer's +current life, not asking them to buy a whole new set. + +The through-line across all three: **one snap system, an expanding catalog of forms, and patterns you +compose yourself.** + +Here is the mechanic and why it loops back to another purchase: + + + +## Who it is for + +Three customers, and what each one comes to do: + + + +- **The aesthetic Muslim household** furnishing a modern home who wants Islamic art that feels + contemporary and personal, not kitsch. +- **The gift buyer** shopping Ramadan, Eid, weddings, and housewarmings, who wants something + meaningful, attractive, and not generic. +- **The maker / tinkerer** drawn to modular, build-your-own systems (the same instinct that sells + LEGO, mechanical keyboards, and desk-setup culture). +- **The coffee-ritual person** who already invests in their setup and buys accessories for it. + +## Market and competition + +- **Adjacent players** are mass-market Islamic-decor shops (generic, printed, cheap), premium + artisanal makers (beautiful, expensive, not modular), and generic modular-decor / build-your-own + toys (no cultural specificity). None of them owns "modular Islamic-geometry accessories you snap + onto what you own." +- **The wedge into a crowded category** is the mechanic plus the culture: a snap-together system is + novel in this aesthetic, and the accessory-to-what-you-own angle sidesteps competing on "another + nice object." +- **Risk to test early:** is the modularity a real draw, or does most demand just want a finished, + good-looking coaster? The plan below is built to learn that cheaply. + +## Business model + +- **Direct-to-consumer via Shopify.** Own the storefront, the customer relationship, and the data. + No marketplace fees eating margin, and full control of the brand story that this product needs. +- **Product tiers:** + - Finished coaster set (the easy first buy). + - Builder pack (pieces plus base, for the maker who wants to compose). + - Accessory add-ons (the expansion line, sold to existing customers). + - Seasonal / limited pattern drops (Ramadan and Eid editions) to drive repeat purchase and urgency. +- **Repeat-purchase engine:** the system design itself. New patterns, new forms, and gifting seasons + bring the same customer back, which is what makes the unit economics work over a customer's life + rather than on a single order. + +## Pricing sketch (to validate, not commit) {#pricing-sketch} + +- Single finished coaster: entry price point that clears shipping and feels giftable. +- Set of four to six: the anchor SKU, priced for a healthy gross margin. +- Builder pack: a small premium over the finished set, justified by more pieces and the build + experience. +- Accessory add-ons: priced to lift average order value on an existing customer. + +The real pricing comes from landed cost per piece plus target gross margin, which I cannot fill in +until I have a real manufacturing quote. Flagging that as the first hard number to get. + +## Go to market (Shopify) {#go-to-market} + +1. **Stand up a lean Shopify store** with a tight first catalog: one finished coaster set, one + builder pack, one hero accessory. Do not launch the whole family, launch the wedge. +2. **Lead with the story and the mechanic.** The product photography and a short build video carry + this: show pieces snapping together and snapping onto a real mug in a real kitchen. +3. **Seed through the gifting seasons.** Time the first push to a Ramadan or Eid window when intent to + buy meaningful Islamic gifts is highest. +4. **Grow through content and community.** Short videos of building patterns, customer builds, and + pattern-of-the-month drops. The build-it dimension is the content engine. +5. **Capture emails from day one** so the seasonal drops and the accessory expansion have an audience + to sell to. + +What the lean first storefront looks like: the tight three-product catalog, wedge first. + + +
+
The LEGO of Islamic Art
+
Snap-together coasters you clip onto what you already own.
+
+ {[ + {name: 'Coaster Set of 4', tag: 'Finished'}, + {name: 'Builder Pack', tag: 'Build your own'}, + {name: 'Mug Collar', tag: 'Snap-on accessory'}, + ].map((p) => ( +
+
+
{p.name}
+
{p.tag}
+
+ ))} +
+ +
+
+ +## Unit economics (the numbers to fill in) {#unit-economics} + +I am deliberately not inventing figures. These are the cells that decide whether this is a business: + +- **Landed cost per piece** (manufacture plus freight plus duties) at a realistic first order quantity. +- **Gross margin per SKU** at each price tier. +- **Fulfillment and shipping cost** per order (coasters are small and light, which helps a lot). +- **Customer acquisition cost** through the launch channels, versus average order value. +- **Repeat rate and lifetime value**, since the whole model leans on the system bringing customers + back rather than on a single sale. + +The first real work is turning these from placeholders into quotes and small tests. + +## Roadmap + +- **Phase 0, validate the pull (cheap):** a landing page plus a few product renders, a small ad spend + or a post to my own audience, and measure whether people click "buy" and join the list. Learn + whether the modularity or just the finished coaster is the draw. +- **Phase 1, prototype the snap:** get real pieces made, prove the snap-together and snap-onto + mechanic physically works and feels good, iterate the geometry. +- **Phase 2, launch the wedge:** Shopify store live with the coaster line, timed to a gifting season, + email capture on. +- **Phase 3, expand the family:** roll out the coffee accessories to the customers the coaster line + earned, and start seasonal pattern drops. +- **Phase 4, the moat:** the accessory-to-what-you-own attachments, the thing competitors cannot + easily copy because it depends on the snap system being established first. + +## Open questions and risks + +- **Manufacturing:** what material and process gives a satisfying snap, a premium feel, and a viable + cost? This is the make-or-break unknown and the first thing to resource. +- **Modularity demand:** do people actually want to build, or do they just want a nice finished + coaster? Phase 0 exists to answer this before spending on tooling. +- **Cultural respect:** Islamic geometric art carries meaning. The execution has to feel reverent and + authentic, not novelty, or it alienates the core audience. +- **Scope discipline:** the temptation is to launch the whole accessory family at once. The wedge + strategy (coaster first) is the guard against that. +- **Shipping and breakage:** small and light is good, but the pieces have to survive transit and the + snap has to hold up to real use. + +## Success criteria + +- Phase 0 shows real pull: a landing page converts clicks to email signups and pre-orders above a + threshold I set before launching, proving demand before I tool up. +- A physical prototype proves the snap mechanic is satisfying and durable. +- Unit economics pencil out: a realistic landed cost and price give a gross margin that survives + acquisition cost, with a repeat rate that makes lifetime value work. +- The first Shopify launch, timed to a gifting season, sells through its initial run and grows the + email list enough to feed the accessory expansion. + +## Next step + +Turn the two hardest unknowns into real numbers: get one manufacturing quote (landed cost per piece) +and run the Phase 0 landing-page test (does the pull exist). Everything else waits on those two +answers. diff --git a/bytesofpurpose-blog/thoughts/2026-07-11-idea-todo-agent.mdx b/bytesofpurpose-blog/thoughts/2026-07-11-idea-todo-agent.mdx new file mode 100644 index 000000000..9d58e40fc --- /dev/null +++ b/bytesofpurpose-blog/thoughts/2026-07-11-idea-todo-agent.mdx @@ -0,0 +1,366 @@ +--- +slug: idea-todo-agent +title: 'Should I Build a Dump-and-Organize Todo Agent?' +sidebar_label: 'Todo agent?' +description: 'A business plan for a bring-your-own-Claude MCP connector: dump raw notes, it files them into the right buckets and auto-builds a knowledge graph and blog.' +authors: [oeid] +tags: [ideas, business, saas, ai-agents, mcp, productivity, knowledge-management] +date: 2026-07-11 +kind: idea +board: ideas +stage: backlog +priority: low +draft: true +questions: + - What would a dump-and-organize todo agent actually be, and why build it as an MCP connector? + - How would a bring-your-own-Claude subscription with rate limits make money? + - What has to be true, and what could kill it, before this is worth building? +--- + +What if the way you keep notes was: dump everything in one place, and an agent sorts it? No folders +to pick, no tags to remember, no "where does this go." You brain-dump raw input and a todo agent +files each piece into the right bucket, splits personal from work, builds you a knowledge graph, and +hosts your own knowledge blog off it. You bring your own Claude, I charge for the connector that +orchestrates all of this. + + + +## The idea in one line + +A "dump-and-organize" agent, shipped as an MCP connector you install from the Claude store, that +takes unstructured input and files it into the right places through structured tools like +`record_idea()` and `record_reference()`, distills personal from work-related material, auto-builds a +knowledge graph, and publishes a knowledge blog for you. You pay a subscription, you are rate-limited, +and the model usage runs on your own Claude. + +The whole pitch is the loss of friction. You do not organize; you dump, and the organizing is the +product. Everything else, the graph and the blog, is durable output that falls out of the dumping for +free. + +## A name for it + +Name candidates to weigh, each leaning on a different part of the pitch: + +- **Know** (the front-runner): short, a real verb and noun, and it names the OUTPUT, not the chore. + You do not manage tasks, you Know things. It reads well as a command ("ask Know") and as a product. + The obvious risk is that a common word is hard to own for search and trademark. +- **Dump** or **Braindump**: names the INPUT and the zero-friction promise, but sells the mess, not the + payoff. +- **Filed** / **Sorted**: names the FILING, honest but small (it is the tidy, not the second brain). +- **Graeme** / **Graphite** / **Weave**: lean on the knowledge-GRAPH, the durable output that compounds. +- **Second Brain**: describes the value exactly but is a widely-used phrase, not ownable. + +The call comes down to whether to name the input (Dump), the mechanism (Filed, Weave), or the payoff +(Know, Second Brain). Naming the payoff is usually right, which is why **Know** leads. + +## Why this is compelling + +:::warning[The pain today] +Your thoughts, links, and tasks are scattered across five apps, and every one asks YOU to do the filing. The organizing is the tax you pay just to keep notes at all. +::: + +:::tip[The relief] +You dump raw input in one place and the agent does the filing. The tidiness, the graph, and the blog fall out for free, so you never pay the organizing tax again. +::: + +- **This is the future-of-productivity bet.** Every notes tool still asks the human to do the filing. + The next move is an agent that does the filing, and the input shrinks to "just tell me the thing." + If that is where productivity is going, the dump-and-organize agent is a direct expression of it. +- **Bring-your-own-Claude lowers my cost and my risk.** The expensive part, model inference, runs on + the customer's own Claude subscription. I am not reselling tokens or eating an unpredictable + inference bill. I charge for the orchestration layer, the tools, and the hosting, which are far more + predictable to run. +- **The Claude store is the distribution channel.** As an MCP connector, the install lives where the + users already are. Approval and connection get recorded inside Claude, so onboarding is a few + clicks, not a signup funnel I have to build and pay to fill. +- **The magic is legible.** "Dump anything, it lands in the right place" is a one-sentence demo. You + can show it working in thirty seconds, which is rare for a productivity tool. +- **Durable output, not just tidiness.** A knowledge graph and an auto-hosted blog are things the user + keeps and can point to. That is stickier than a folder that is merely well-sorted, and it is a + built-in reason to stay subscribed. + +## The product + +**The core loop: dump, then it files.** The user sends raw input, a thought, a link, a task, a quote, +and the agent routes each piece through a small set of structured tools rather than freeform text. +The tools are the API of the organizer: + +- `record_idea()`, for a raw idea worth keeping. +- `record_reference()`, for a link or source to file and cite later. +- `record_todo()`, for an actionable item that belongs on a list. +- `record_note()`, for context that is neither idea, reference, nor task. + +Because the filing goes through named tools, the behavior is inspectable and controllable, not a black +box that "figures it out." + + + +
+