100 Commits
Author SHA1 Message Date
plt f03fe7f232 Merge branch 'main' into feat/ci-runner-setup 2026-09-02 17:58:59 +00:00
pat 59201c9c29 chore: brand presentation is AiBook.fun
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 16:33:11 +00:00
pat 6390d81c82 chore: brand presentation is AiBook.fun
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 16:33:10 +00:00
pat 1a629bc087 chore: brand presentation is AiBook.fun
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 16:33:09 +00:00
pat 195baa32cc chore: brand presentation is AiBook.fun
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 16:33:08 +00:00
pat 5cf207c6c9 chore: brand presentation is AiBook.fun
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 16:33:07 +00:00
pat 6685694cc2 chore: brand presentation is AiBook.fun
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 16:33:05 +00:00
pat af6512d765 chore: brand presentation is AiBook.fun
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 16:33:04 +00:00
pat 91d58ab12e chore: brand presentation is AiBook.fun
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 16:33:03 +00:00
pat 031942700a chore: brand presentation is AiBook.fun
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 16:33:02 +00:00
pat 32e8ef4446 chore: brand presentation is AiBook.fun
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 16:33:01 +00:00
pat 5eb257c987 chore: brand presentation is AiBook.fun
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 16:32:59 +00:00
pat b653e8fac9 chore: brand presentation is AiBook.fun
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 16:32:58 +00:00
pat c80574a913 chore: brand presentation is AiBook.fun
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 16:32:57 +00:00
pat 1f06edee73 chore: brand presentation is AiBook.fun 2026-09-02 16:32:56 +00:00
pat faf5bb7a25 chore: brand presentation is AiBook.fun 2026-09-02 16:32:55 +00:00
pat efcd1b9bca chore: brand presentation is AiBook.fun 2026-09-02 16:32:54 +00:00
pat 648f6de91a chore: brand presentation is AiBook.fun 2026-09-02 16:32:53 +00:00
pat 79c5a42ed8 chore: brand presentation is AiBook.fun 2026-09-02 16:32:51 +00:00
pat f0f8f9b01f chore: sync marketing site and workflows with local reading demo
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 16:21:50 +00:00
pat ca2361cce0 fix(nav): center the section links in the bar
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 14:41:34 +00:00
pat b263715ee2 fix(site): drop dead Contents links from nav and footer
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 14:39:34 +00:00
pat 0fae769daa fix(site): drop dead Contents links from nav and footer
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 14:39:32 +00:00
pat 7a7181b79c feat(nav): Go to Library button on the marketing site
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 12:57:34 +00:00
pat 51d3d9a6ae feat(nav): Go to Library button on the marketing site
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 12:57:33 +00:00
pat 6173d478c7 copy(site): content updates continuously, not once a year
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 12:47:52 +00:00
pat 27cf3db62b copy(site): content updates continuously, not once a year
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 12:47:51 +00:00
pat d9ba89ce17 copy(site): content updates continuously, not once a year
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 12:47:50 +00:00
pat aa5c4ea09e copy(site): content updates continuously, not once a year
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 12:47:49 +00:00
pat e5f2f221bc copy(site): content updates continuously, not once a year
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 12:47:48 +00:00
pat 9b0ad976d8 copy(site): content updates continuously, not once a year
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 12:47:47 +00:00
pat d10a59434f copy(site): content updates continuously, not once a year
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 12:47:45 +00:00
pat a24a9f4277 copy(site): sharpen field notes into plain facts
deploy / build-and-deploy (push) Canceled after 0s
2026-09-02 12:19:47 +00:00
plt 84c59eb358 Merge pull request 'feat(deploy): aibook.fun deploy layer (terraform + ansible + docker on DO)' (#4) from feat/aibook-fun-deploy into main
deploy / build-and-deploy (push) Canceled after 0s
Reviewed-on: #4
2026-09-02 09:53:59 +00:00
plt 6f9843ff44 Merge branch 'main' into feat/aibook-fun-deploy 2026-09-02 09:51:34 +00:00
pat e7da04ffb6 fix(site): give Fraunces section titles room to breathe 2026-09-02 05:58:39 +00:00
pat 30cf939eb7 copy(reader): Library page gets a title and a subtitle 2026-09-01 16:58:14 +00:00
pat 44c8fa2b43 copy(reader): write the library title like a person 2026-09-01 08:24:27 +00:00
pat b4f79661a1 fix(reader): keep library title on one line 2026-09-01 08:21:09 +00:00
pat 34d56b4dbb fix(reader): give library title room to breathe 2026-09-01 07:53:22 +00:00
pat b6bbd30415 fix(reader): Library in the nav, breadcrumbs in the chapter 2026-09-01 07:50:48 +00:00
pat c60448004f fix(reader): Library in the nav, breadcrumbs in the chapter 2026-09-01 07:50:47 +00:00
pat 1e143cf18a fix(reader): Library in the nav, breadcrumbs in the chapter 2026-09-01 07:50:46 +00:00
pat 4e447ca254 fix(reader): Library in the nav, breadcrumbs in the chapter 2026-09-01 07:50:45 +00:00
pat 2fca7dff4b fix(reader): Library in the nav, breadcrumbs in the chapter 2026-09-01 07:50:44 +00:00
pat 719f969443 fix(reader): Library in the nav, breadcrumbs in the chapter 2026-09-01 07:50:43 +00:00
pat 344be8b8f7 fix(reader): Library in the nav, breadcrumbs in the chapter 2026-09-01 07:50:42 +00:00
pat c488955c93 feat(reader): show workflow kit on chapter pages 2026-09-01 07:19:50 +00:00
pat 1daaea6148 feat(reader): show workflow kit on chapter pages 2026-09-01 07:19:49 +00:00
pat a85ad2e1d9 feat(reader): show workflow kit on chapter pages 2026-09-01 07:19:48 +00:00
pat 56988687cb feat(reader): show workflow kit on chapter pages 2026-09-01 07:19:47 +00:00
pat f80a6c2aca feat(reader): show workflow kit on chapter pages 2026-09-01 07:19:45 +00:00
pat 261ebe513f feat(reader): show workflow kit on chapter pages 2026-09-01 07:19:44 +00:00
pat 53a947e23d feat(reader): show workflow kit on chapter pages 2026-09-01 07:19:43 +00:00
pat 02697cd5f3 fix(library): start founding Real Estate sample at RE-01 2026-09-01 03:55:43 +00:00
pat 9638b58e7b fix(library): start founding Real Estate sample at RE-01 2026-09-01 03:55:42 +00:00
pat 203ab9394c fix(library): start founding Real Estate sample at RE-01 2026-09-01 03:55:41 +00:00
pat 84f64e6a00 fix(library): start founding Real Estate sample at RE-01 2026-09-01 03:55:40 +00:00
pat 4990a7e4c5 fix(library): start founding Real Estate sample at RE-01 2026-09-01 03:55:39 +00:00
pat 894de4d682 fix(library): start founding Real Estate sample at RE-01 2026-09-01 03:55:38 +00:00
pat f47b42e4a5 fix(reader): use full chapter width with workflow rail 2026-09-01 03:49:21 +00:00
pat 3f32886894 fix(reader): use full chapter width with workflow rail 2026-09-01 03:49:20 +00:00
pat dc9f3e27c6 fix(reader): use full chapter width with workflow rail 2026-09-01 03:49:19 +00:00
pat 7e98e19113 fix(reader): use full chapter width with workflow rail 2026-09-01 03:49:18 +00:00
pat ae1f1ab71b fix(reader): use full chapter width with workflow rail 2026-09-01 03:49:17 +00:00
pat abb2b65d2a Replace the chapter progress bar with an opaque outline 2026-09-01 03:44:10 +00:00
pat ae310ba1d3 Pass workflow index into the focus view 2026-09-01 03:44:09 +00:00
pat c1197a4f7f Show workflow count on ready library rows 2026-09-01 03:44:08 +00:00
pat b645d1bec2 Restructure the chapter shell around a visible outline 2026-09-01 03:44:06 +00:00
pat 8937061c49 Label nested workflows and add in-recipe jump links 2026-09-01 03:44:05 +00:00
pat d7c6a239c1 Add sticky chapter outline for the reading demo 2026-09-01 03:44:04 +00:00
pat 5f24a406cf Add chapter outline data and recipe short titles 2026-09-01 03:44:03 +00:00
pat f0c6a48187 fix(reader): do not show Library twice on the library page 2026-09-01 03:36:11 +00:00
pat 695a8e3f08 docs: note how to run the reading demo 2026-08-31 07:33:31 +00:00
pat a7d5e5f31e feat(reader): add reading-demo layout styles 2026-08-31 07:33:30 +00:00
pat 98830de44e feat(nav): send logo home and add Sample chapter link 2026-08-31 07:33:29 +00:00
pat 1f52209f87 feat(reader): add sample comps for RE-05 Try-it 2026-08-31 07:33:28 +00:00
pat b4ad25c1ec feat(reader): add sample listings for RE-04 Try-it 2026-08-31 07:33:27 +00:00
pat aac526f7a1 feat(reader): add print/focus recipe view 2026-08-31 07:33:26 +00:00
pat 6dfa941683 feat(reader): add Real Estate sample chapter 2026-08-31 07:33:25 +00:00
pat 7743e6fa75 feat(reader): add reading-demo library page 2026-08-31 07:33:24 +00:00
pat b87b7516dc feat(reader): add full nested workflow block 2026-08-31 07:33:23 +00:00
pat 6d13ab5962 feat(reader): reuse terminal chrome for nested method output 2026-08-31 07:33:22 +00:00
pat 8314dad574 feat(reader): add slim reader footer 2026-08-31 07:33:21 +00:00
pat 265d64abd6 feat(reader): add slim reader nav 2026-08-31 07:33:19 +00:00
pat 3dd20d13c0 feat(reader): persist Try-it activation in localStorage 2026-08-31 07:33:18 +00:00
pat 0fba3c8175 feat(reader): add sample Real Estate chapter and nested recipes 2026-08-31 07:33:17 +00:00
pat ce9bb4f943 docs: content is the critical path; chapter blank lives in workflows/ 2026-08-31 07:21:23 +00:00
pat 20cd0d09c8 docs: mark aibook.fun domain renewed in digital surface table 2026-08-31 07:21:21 +00:00
pat 0bc2fcd10b docs: close leftover D-2 copy; point §5.4 at workflows/chapter-structure.md 2026-08-31 07:21:20 +00:00
pat 48425b0baf docs: index the chapter blank; chapters are the reading unit; $47/yr signed 2026-08-31 07:21:19 +00:00
pat efc859b339 docs: add workflows/ chapter blank for review (PRD §5.4) 2026-08-31 07:21:18 +00:00
pat ad4bc12c00 docs: close Gate 0.1 and 0.2 (domain + pricing) 2026-08-31 07:16:38 +00:00
pat 53828e8d73 docs: commercial spine signed — $47/yr; writers on contract 2026-08-31 07:16:37 +00:00
pat 10ef165596 docs: sign D-1/D-2 — $47/yr, no v1 lifetime SKU, founding writers on contract; domain renewed 2026-08-31 07:16:36 +00:00
pat 46d366e6b0 docs: chapters are the reading unit; workflows nest in the essay 2026-08-30 23:25:57 +00:00
pat 9dfdf07ce3 docs: lock reading IA — chapters as essays with nested full workflows (2026-08-31) 2026-08-30 23:25:57 +00:00
pat 82acad15f2 docs: mark Gate 0.3 product-health ratification done (2026-08-29) 2026-08-29 20:36:17 +00:00
pat 353d749b52 docs: point Spec activation clock at access key; metrics ratified 2026-08-29 2026-08-29 20:36:16 +00:00
pat 2b76c45620 docs: ratify product-health metrics (2026-08-29)
Activation 20/35 from access-key date; campaign contributor waitlist 50/100; post-key submissions 10/25 in 90 days; renewal 40/60 excluding lifetime; curation SLA demoted from launch bar.
2026-08-29 20:36:15 +00:00
35 changed files with 2261 additions and 151 deletions
+14 -16
View File
@@ -1,14 +1,14 @@
---
title: "AIBook.fun — Implementation Plan"
title: "AiBook.fun — Implementation Plan"
type: implementation-plan
status: draft
owner: Patrick (Product)
launch-target: 2026-09-26
last-updated: 2026-08-26
last-updated: 2026-08-31
companions: [AiBook_PRD.md, AiBook_Spec.md]
---
# 📚 AIBook.fun — Implementation Plan
# 📚 AiBook.fun — Implementation Plan
> **Status: DRAFT.** The schedule below assumes decisions that aren't final yet (see "Do this
> week"). Dates, owners, and dollar figures are planning assumptions until signed off. This is a
@@ -16,12 +16,11 @@ companions: [AiBook_PRD.md, AiBook_Spec.md]
> [Appendix — What changed](#appendix--what-changed-in-this-revision) for how this revision
> differs from the prior draft.
**The clock:** today is late August 2026; **launch is 9/26/2026** — roughly **4–5 weeks out**.
Every week counts, and the critical path has little slack. The domain expires **09-05**, so
step one is non-negotiable and immediate.
**The clock:** today is 31 Aug 2026; **launch is 26 Sep 2026**. Domain and price are signed.
Content is the remaining critical path.
**The critical path in one line:**
`renew domain + make the pricing decisions → seed the Minimum Lovable Library → freeze copy → no-crypto scrub → submit to Kickstarter → launch 9/26`
`assign MLL authors + D-3 co-authors → write the library → freeze copy → no-crypto scrub → submit to Kickstarter → launch 9/26`
---
@@ -31,17 +30,16 @@ Before any copy or build locks, close these. Most are decisions or de-risking, n
| # | Task | Owner | Why it's first |
|:--|:--|:--|:--|
| 0.1 | **Renew aibook.fun today.** It expires 09-05; launch is 09-26. | Whoever holds the registrar login | It's a chore, not a decision. A lapsed domain 3 weeks before launch is a self-inflicted disaster. |
| 0.2 | **Decide the pricing spine — lifetime *and* royalties together** (D-1 + D-2). | Commercial lead (@GTM) | Both block copy freeze; they're linked (see [Spec §6](AiBook_Spec.md)). |
| 0.3 | **Ratify the North-Star + product-health floors** (activation, submissions, renewal). | Product (@pat) + team | So we measure the right thing from Day 1, not just dollars. |
| 0.1 | **~~Renew aibook.fun~~ Done 2026-08-31.** | Registrar owner | Closed. |
| 0.2 | **~~Pricing spine~~ Done 2026-08-31.** **$47/yr** is the product. No lifetime SKU as an equal. Founding writers on **contract** (v1 authored). | Commercial + Product | Copy freeze unblocked on price. |
| 0.3 | **~~Ratify the North-Star + product-health floors~~ Done 2026-08-29.** Activation 20/35 from access date; campaign waitlist 50/100; post-key submissions 10/25 in 90 days; renewal 40/60 excluding lifetime; curation is an ops SLA, not a launch bar. See PRD §8. | Product (@pat) | Locked. Don't quote 60% renewal publicly. |
| 0.4 | **Ratify the Minimum Lovable Library number and assign every workflow an author.** | Product + co-authors | This is the #1 risk; turn it from hope into owned work. |
| 0.5 | **Confirm the two unconfirmed co-authors, or cut their verticals from v1** (D-3). | Commercial lead (@GTM) | Scope certainty before outline lock. |
| 0.6 | Open the claims register; assign a post-campaign renewal owner. | Product + Commercial | Truth-in-claims gate; don't leave renewal unstaffed. |
| 0.7 | Set up the Kickstarter creator account + identity verification. | Campaign lead (@THY) | Long lead time; do it early. |
**✅ Gate 0 — decisions closed.** Pricing spine decided · targets ratified · Minimum Lovable
Library scoped with authors · domain renewed · claims register open. *Until pricing is decided,
don't freeze copy. Until the domain is renewed, don't push anything live.*
**✅ Gate 0 — decisions closed.** **Pricing spine signed ($47/yr; writers on contract)** · **targets ratified (2026-08-29)** · Minimum Lovable
Library scoped with authors · **domain renewed (2026-08-31)** · claims register open. *Until the library has named authors and D-3 is closed, don't treat content as on track. Copy freeze still waits on claims + co-author scope.*
---
@@ -53,8 +51,8 @@ campaign around an empty library fails.
### 1A · Content — seed the Minimum Lovable Library (critical path)
| Task | Owner |
|:--|:--|
| Lock the chapter outline (chapters per vertical, a named owner each) | Co-authors |
| Publish the Workflow Recipe template + 3 filled examples | Product |
| Lock the chapter outline (chapters per vertical, a named owner each). Blank is [`workflows/chapter-structure.md`](workflows/chapter-structure.md) | Co-authors |
| Review and freeze the chapter blank, then 3 filled examples | Product + authors |
| **Seed the Minimum Lovable Library to its floor number** (team + co-authors write & test the workflows) | Co-authors + team |
| 3 "clone-and-run" kits, each **verified by actually running it** | Dev + QA support |
| 2 sample chapters (the backer preview) | Two lead co-authors |
@@ -75,7 +73,7 @@ campaign around an empty library fails.
| Task | Owner |
|:--|:--|
| Kickstarter page copy (all sections, 9/26 dates) | Campaign lead + exec co-author |
| **Copy freeze — commercial terms locked** (lifetime/royalties per D-1/D-2) | Commercial lead (sign) |
| **Copy freeze** (price already signed: $47/yr, writers on contract; still freeze claims + NFT scrub) | Commercial lead (sign) |
| **No-crypto scrub gate on every asset** (translation table) | Campaign lead (owner) |
| Hero video: script → shoot → edit (2–3 min) | Creative lead (@LFG) + co-authors |
| Cover design + 3D mockups | Creative lead |
+90 -36
View File
@@ -1,13 +1,13 @@
---
title: "AIBook.fun — Product Requirements Document"
title: "AiBook.fun — Product Requirements Document"
type: prd
status: draft
owner: Patrick (Product)
launch-target: 2026-09-26
last-updated: 2026-08-26
last-updated: 2026-08-31
---
# 📚 AIBook.fun — Product Requirements Document
# 📚 AiBook.fun — Product Requirements Document
> **Status: DRAFT.** Dollar figures, dates past today, and commercial terms in this
> document are planning assumptions, not commitments. Nothing here should be quoted
@@ -20,7 +20,7 @@ last-updated: 2026-08-26
## TL;DR
AIBook.fun is a **crowd-written, practical field guide to using AI agents responsibly at
AiBook.fun is a **crowd-written, practical field guide to using AI agents responsibly at
work** — sold as an annual subscription, launched on Kickstarter on **September 26, 2026**.
Its unit of content is not a chapter but a **workflow you can actually run**: a documented,
tested recipe for getting a real job done with AI, complete with the guardrails.
@@ -142,8 +142,9 @@ the structural answer to "how do I know this AI advice isn't hallucinated?"
| **Costs** | Model/tool costs where known — honesty about the economics |
| **Author & sources** | Who wrote it, when, for which vertical, with citations |
**Chapters** are curated collections of these recipes, one set per vertical: Real Estate ·
Financial Advisors · Fractional C-Suite · Higher Ed · Communities · Technology. **Editions**
**Chapters** are substantial essays, one per vertical (Real Estate · Financial Advisors ·
Fractional C-Suite · Higher Ed · Communities · Technology), with full Workflow Recipes
**nested in the argument**. See [§5.4](#54-the-reading-surface-locked-2026-08-31). **Editions**
refresh annually — which is the honest justification for a *subscription* rather than a
one-time purchase: the content genuinely goes stale as AI changes.
@@ -160,15 +161,61 @@ post-launch aspiration. Community contribution is **Layer 2** — an experiment
we've seeded a library worth subscribing to.
### 5.3 Be honest: v1 is an *authored* book, not yet a *crowd* book
The prior draft's "contributor economy" pays co-authors **15% affiliate commission** — which
is a reward for *referring backers*, not for *writing workflows*. Writing a workflow currently
earns a byline and nothing else. The mechanic that would actually pay contributors — royalties
— is unresolved (see [D-2](#10-open-decisions)).
The prior draft's "contributor economy" pays co-authors **15% affiliate commission**, which
is a reward for *referring backers*, not for *writing workflows*.
So for v1, we state plainly: **the first edition is written by a founding set of co-authors and
the team.** Open community contribution — with a real incentive attached — is the very next
thing we build, and its incentive design ([D-2](#10-open-decisions)) is a **launch-blocking
decision, not a nice-to-have**, because the entire "living book" thesis depends on it.
**Signed 2026-08-31 (D-2):** founding writers are paid **on contract**. v1 is an authored book.
Affiliate referral can still pay for referring backers. It is not how writing is paid. Open
contribution with royalties or bounties waits for Layer 2.
So we state plainly: **the first edition is written by a founding set of co-authors and the
team.** Layer 2 is the next thing we build, after the library is worth subscribing to.
---
### 5.4 The reading surface (locked 2026-08-31)
People read **chapters**, not a shelf of detached cards. A chapter is a substantial essay
for one vertical: it argues a way of working, then **nests full workflows inside that
argument** as the proof.
This is a deliberate break from treating the workflow as the only page. The workflow is
still the unit of *practice* (and of activation). The chapter is the unit of *reading*.
**Chapter page**
- Title, vertical, edition, authors
- Opening promise (what this chapter is for) plus a **Skip to a Try-it** control — activation
must not require finishing the essay
- Essay body: sections that teach the practice (stakes, constraints, how we work here)
- Nested **Workflow blocks** at the points in the argument they earn — not bunched in an appendix
- End matter: further workflows in this vertical, sources, last updated
**Nested workflow block** (the recipe, in full — not a teaser)
1. Chrome: recipe ID, version, time, cost
2. Title as the job
3. Problem
4. Actors
5. Setup (tools, sample files, cost)
6. **Safeguards before the steps** so data-handling is read before anyone pastes a client list
7. Method, with real tool output *in* the steps
8. Evidence
9. Try-it (~15 min, sample data, mark complete — fires Activation)
10. Share result (community template; events, not content)
11. Author, sources, last updated
**Addressability**
- Every workflow has a stable ID (e.g. `RE-01`) and a URL that opens the chapter scrolled to
that block (and a focused/print view of the same block). Campaign samples, clone-and-run
kits, and Workflow-of-the-Week link here — never to an essay with no way in.
- PDF matches this stack: chapter essay + in-place recipes. Print and web must not drift.
**Non-goals for the reader**
- No chatbot on the chapter page
- No crypto/Web3 language
- Nested recipes are not collapsed “click to reveal” cards that hide the Method
**Writing drafts** live in [`workflows/chapter-structure.md`](workflows/chapter-structure.md).
Copy that blank into a vertical file (`workflows/real-estate.md`, etc.) when a chapter is assigned.
---
@@ -202,8 +249,8 @@ Requirements are grouped by the layer they serve; **most 🔴 items serve the co
| ID | Requirement | Pri |
|:--|:--|:--|
| A-1 | Post-campaign access: a digital key unlocks PDF + web reader for 12 months, renews annually | 🟢 |
| A-2 | Anchor price **$47/yr** *(draft — needs commercial re-sign)* + hardcopy at-cost upcharge | 🔴 |
| A-3 | Lifetime tier — **decision required before copy freeze** (see [D-1](#10-open-decisions)) | 🟡 |
| A-2 | Anchor price **$47/yr** *(signed 2026-08-31)* + hardcopy at-cost upcharge. No lifetime SKU as an equal product. | 🔴 |
| A-3 | Lifetime tier — **not offered as a v1 SKU** (D-1 signed 2026-08-31: $47/yr only). Revisit only as a capped early-bird later, not as an equal product. | 🟢 |
| A-4 | Fulfillment ledger: backer ↔ key/upcharge tracked (a spreadsheet is fine for v1) | 🟢 |
### 6.4 The other layers — mostly 🟡 / 🟢
@@ -236,7 +283,7 @@ Requirements are grouped by the layer they serve; **most 🔴 items serve the co
| NFR-3 | **Privacy:** no confidential client data in any workflow or campaign asset; track events, not content. |
| NFR-4 | **Availability:** landing page up through the campaign; emails on schedule; affiliate tracking live from Day 1 (the 30-day cookie means every hour of Day 1 counts). |
| NFR-5 | **Content quality:** every workflow passes the Recipe template + at least one co-author review. |
| NFR-6 | **Domain continuity:** aibook.fun must not lapse (it currently expires 09-05 — see [§9](#9-immediate-next-steps)). |
| NFR-6 | **Domain continuity:** aibook.fun must not lapse (**renewed 2026-08-31**). |
| NFR-7 | **Accessibility:** reader and landing page are mobile-readable, targeting WCAG AA. |
| NFR-8 | **Cost discipline:** pre-revenue burn stays within the ~$6K budget ([Appendix C](#appendix-c--budget)). |
@@ -249,12 +296,18 @@ metrics; those measure the *campaign*, not the *product.* A funded campaign can
dead product if nobody activates, renews, or contributes.
### Product health (report these first)
| Metric | Floor | Target | Why it matters |
|:--|:--|:--|:--|
| **Activation** — read 1 workflow + do 1 Try-it in 14 days | 20% | 35% | The North-Star. Is the core loop actually useful? |
| **Workflow submissions** during campaign window | 10 | 25 | Early signal that Layer 2 (contribution) is real |
| **Renewal rate** — year-1 cohort | — | 60% | Is a *subscription* the right model at all? |
| **Curation turnaround** ≤ 10 working days | 80% | 95% | Can we keep quality without becoming the bottleneck? |
**Ratified 2026-08-29 (Product).** These are the numbers we run. Do not quote the 60% renewal target on Kickstarter or any public surface.
| Metric | Floor | Target | Clock / notes | Why it matters |
|:--|:--|:--|:--|:--|
| **Activation** — read 1 workflow + finish 1 Try-it | 20% | 35% | **14 days from access-key date, not pledge date.** North-Star. | Is the core loop actually useful? |
| **Contributor waitlist** during the campaign | 50 | 100 | People who *say* they will contribute a workflow. Not written recipes. | Early Layer-2 signal without betting launch on cold-start writing |
| **Workflow submissions** | 10 | 25 | First **90 days after keys go out** | Is paid/open contribution real once the library exists? |
| **Renewal rate** — year-1 **paid** cohort | 40% | 60% | **Exclude lifetime SKUs** from the denominator. 60% is internal. | Is a *subscription* the right model at all? |
| **Curation turnaround** ≤ 10 working days | 80% | 95% | **Ops SLA after Layer 2 is on** — not a launch health bar | Can we keep quality without becoming the bottleneck? |
Leading indicator before fulfillment: % of the pre-launch list who run the *sample* Try-it.
### Campaign performance (the fundraise)
| Metric | Min | Target | Stretch |
@@ -279,13 +332,13 @@ dead product if nobody activates, renews, or contributes.
## 9. Immediate next steps
**This week — decisions and de-risking (before any copy or build locks):**
1. **Renew aibook.fun today.** It expires 09-05; launch is 09-26. This is a chore, not a
strategic decision — do it now and delete it from the risk list. *(Owner: whoever holds the
registrar login.)*
2. **Resolve the pricing spine together — lifetime ([D-1](#10-open-decisions)) *and* royalties
([D-2](#10-open-decisions)).** They're linked, and both block copy freeze.
3. **Ratify the North-Star + the product-health floors** (§8) so we're measuring the right
thing from Day 1.
1. **~~Renew aibook.fun~~ Done.** Domain renewed (confirmed 2026-08-31). Launch remains 09-26.
2. **~~Resolve the pricing spine (D-1 / D-2)~~ Done 2026-08-31.** Anchor is **$47/yr**. No
lifetime SKU as an equal product. Founding writers are engaged **on contract** — v1 is an
authored book; open royalties are not the v1 mechanic. Copy freeze is unblocked on price.
3. **~~Ratify the North-Star + the product-health floors~~ Done 2026-08-29.** Locked in §8:
activation 20/35 from access date; campaign waitlist 50/100; post-key submissions 10/25 in
90 days; renewal 40/60 excluding lifetime; curation SLA not a launch bar.
4. **Ratify the Minimum Lovable Library number and assign every workflow an author** (§5.2).
5. **Confirm the two unconfirmed co-authors** (Higher Ed, Communities) or re-scope those
verticals out of v1.
@@ -313,8 +366,8 @@ decision-maker has a starting point — but the recommendation is not yet a deci
| # | Decision | Recommendation | Blocks |
|:--|:--|:--|:--|
| **D-1** | **Lifetime tier — offer it, and at what price?** A ~$97–147 lifetime breaks even against $47/yr in ~2–3 years, which *undercuts the recurring-revenue thesis.* | **Pick a spine.** Keep $47/yr as the anchor. If you want a lifetime option, frame it *only* as a bounded early-bird instrument to capitalize the community fund (capped quantity), not the default SKU. Don't ship recurring + lifetime as equals. | KS copy freeze |
| **D-2** | **Contributor payment — how do people earn for *writing workflows* (not just referring)?** Today the only paid mechanic is affiliate referral. | **Resolve before launch.** This is the engine of the "living book." Decide: royalty pool, per-accepted-workflow bounty, or an explicit "v1 is authored, paid contribution ships in Q1" — but decide, don't leave blank. | The core value prop |
| **D-1** | ~~Lifetime tier~~ **Signed 2026-08-31.** Product price is **$47/yr**. No lifetime SKU as an equal v1 product. | Locked. Don't quote a lifetime price. Hardcopy remains an at-cost upcharge. | — |
| **D-2** | ~~Writer payment~~ **Signed 2026-08-31.** The first set of writers is engaged **on contract**. v1 is an authored book. Affiliate referral can still pay for *referring backers*; it is not how writing is paid. Open contribution + any royalty/bounty is post-v1 (Layer 2), not a launch mechanic. | Locked for v1. Revisit royalties before opening Layer 2. | — |
| **D-3** | **Co-author confirmations** (Higher Ed, Communities verticals). | Confirm within the week or cut those verticals from v1 and add post-launch. | Chapter outline, scope |
| **D-4** | **Refresh the source-of-truth plan** to the 9/26 dates and re-signed terms (depends on D-1/D-2). | Do after D-1/D-2 land. | Copy freeze |
| **D-5** | **Human-first or agent-first for v1?** Writing for human motivation and for machine ingestion are different jobs. | **Human-first.** Build the content format so agents *can* read it later (K-7), but optimize v1 for human learners. Agent onboarding is Layer 4. | Content design |
@@ -375,16 +428,17 @@ changes from the prior draft, and the reasoning:
funnel are explicitly later layers.
3. **Elevated the content cold-start** to the #1 risk and added the *Minimum Lovable Library*
launch gate (§5.2).
4. **Told the truth about incentives** (§5.3): v1 is an authored book; the "contributor
economy" is currently a referral scheme; paid contribution (D-2) is now launch-blocking.
5. **Forced the subscription-vs-lifetime tension** into a real decision (D-1).
4. **Told the truth about incentives** (§5.3). **D-2 signed 2026-08-31:** founding writers on
contract; v1 authored; royalties wait for Layer 2. Affiliate still pays referrals, not writing.
5. **Forced the subscription-vs-lifetime tension** into a real decision. **D-1 signed 2026-08-31:**
**$47/yr** only. No lifetime SKU as an equal v1 product.
6. **Split the validation bar from the funding floor** (§8) so a funded-but-dead outcome can't
hide.
7. **Reframed the pitch as utility-first** (§4, §9 hook test) — the buyer wants a workflow, not
an ownership philosophy.
8. **Demoted governance to proportionate** (Appendix B), keeping only the NFT-scrub and
truth-in-claims as active gates.
9. **Turned the domain "decision" into a same-day chore** (§9).
9. **Turned the domain into a same-day chore** (§9). **Done 2026-08-31:** `aibook.fun` renewed.
10. **Translated the jargon out.** Internal codes, handles, and merge-history are gone from the
body; a who's-who / glossary can be maintained separately if the team wants traceability
back to the source-of-truth IDs.
+17 -14
View File
@@ -1,14 +1,14 @@
---
title: "AIBook.fun — Product Specification"
title: "AiBook.fun — Product Specification"
type: spec
status: draft
owner: Patrick (Product)
launch-target: 2026-09-26
last-updated: 2026-08-26
last-updated: 2026-08-31
companions: [AiBook_PRD.md, AiBook_Implementation_Plan.md]
---
# 📚 AIBook.fun — Product Specification
# 📚 AiBook.fun — Product Specification
> **Status: DRAFT.** This spec is the *thinking* behind the product — the vision, the
> principles, the model. The [PRD](AiBook_PRD.md) turns it into requirements; the
@@ -22,7 +22,7 @@ companions: [AiBook_PRD.md, AiBook_Implementation_Plan.md]
## TL;DR
AIBook.fun is a **living, crowd-written field guide to using AI agents responsibly at work.**
AiBook.fun is a **living, crowd-written field guide to using AI agents responsibly at work.**
Its unit of value is a **workflow you can run** — a documented, tested recipe for doing a real
job with AI, including the guardrails. It launches as an annual subscription via Kickstarter on
**September 26, 2026**.
@@ -56,7 +56,8 @@ ambition — but an engine needs one cylinder firing before you add the rest. He
Everything else the product wants to be — a contributor economy, a cohort program, an
onboarding corpus for AI agents — is a **layer built on top of this loop**, and only worth
building once the loop demonstrably works. We measure that with one number, **Activation**: *did
a reader run at least one workflow within 14 days?* (Full metric set in [PRD §8](AiBook_PRD.md).)
a reader run at least one workflow and finish one Try-it within 14 days of getting access
(access key, not pledge)?* Floors/targets ratified 2026-08-29 — full set in [PRD §8](AiBook_PRD.md).
### The product in layers
| Layer | What | When |
@@ -95,7 +96,7 @@ These are gates, not preferences — a workflow or a claim either clears them or
| Actor | Who | Their job | The boundary |
|:--|:--|:--|:--|
| **Reader / subscriber** | Practitioners (real estate, financial advisors, fractional execs, higher ed, communities, tech) | Get current, trustworthy AI workflows to apply this week | Pays for access (~$47/yr — *draft*) |
| **Reader / subscriber** | Practitioners (real estate, financial advisors, fractional execs, higher ed, communities, tech) | Get current, trustworthy AI workflows to apply this week | Pays for access (**$47/yr** — signed) |
| **Co-author** | Confirmed: three founders across RE/FA, C-suite, and tech. Potential: two more for Higher Ed & Communities | Own a vertical; write and curate its workflows | Content follows the template; curated |
| **Curator / editor** | Co-authors + community editors | Keep the quality bar; run the editorial pipeline | Curating ≠ owning the platform |
| **Affiliate** | Community, podcast, press | Refer backers; earn commission | Commission rates below |
@@ -146,9 +147,11 @@ answer to "how do I know this isn't hallucinated AI advice?"
| **Costs** | Model/tool costs where known — honesty about economics |
| **Author & sources** | Who, when, which vertical, with citations |
**Chapters** are curated collections of these per vertical. **Editions** refresh annually —
**Chapters** are the reading unit: a substantial essay per vertical, with **full workflows
nested in the argument** (not a table of contents of cards). **Editions** refresh annually —
which is the honest justification for a *subscription*: AI moves fast enough that a static book
goes stale, so the value is in staying current.
goes stale, so the value is in staying current. Reading IA locked 2026-08-31; see
[PRD §5.4](AiBook_PRD.md).
### 4.2 Seed the shelf before you sell tickets (the cold-start rule)
The value proposition is a rich library. The failure mode is a near-empty one. Crowd-sourced
@@ -179,7 +182,7 @@ around and after launch, not gating it:
### 4.4 Digital surface (current state)
| Surface | What it is | Status |
|:--|:--|:--|
| `aibook.fun` domain | Public home: pitch, sample workflows, affiliate signup, campaign link | Parked — **expires 09-05, renew immediately** |
| `aibook.fun` domain | Public home: pitch, sample workflows, affiliate signup, campaign link | **Renewed 2026-08-31** |
| Landing page (built) | A staged proof-of-concept, ready to review and push live | Staged locally, not yet public |
| Subscription access | Digital key → PDF + web reader + annual updates | Not built yet (post-campaign) |
| Community | Team channel live; cohort spaces not built | Partial |
@@ -218,9 +221,9 @@ from the core loop.*
| Item | Value | Status |
|:--|:--|:--|
| Anchor subscription | $47/yr digital + hardcopy upcharge | **Draft** — needs commercial re-sign for the 9/26 relaunch |
| Lifetime access | Proposed; ~$97–147 one-time *(figures illustrative — do not quote)* | **Open decision** ([D-1](#8-open-decisions)) |
| Contributor royalties | None documented today; current mechanic is affiliate referral only | **Open decision** ([D-2](#8-open-decisions)) |
| Anchor subscription | **$47/yr** digital + hardcopy at-cost upcharge | **Signed 2026-08-31** |
| Lifetime access | Not a v1 SKU | **Signed D-1:** $47/yr only |
| Founding writers | Paid **on contract** (v1 is authored). Affiliate still pays referrals, not writing. | **Signed D-2 2026-08-31.** Royalties/bounties wait for Layer 2. |
| Projected revenue | ~$53,600 at 706 backers | Draft planning figure |
| Pre-revenue budget | ~$6,000 (ads + KS fees + affiliate fee) | Draft planning figure |
| "eBookNFT platform" | A future idea; this book is the first product | Not in scope |
@@ -274,8 +277,8 @@ carries a recommendation as a starting point, not a settled answer.
| # | Decision | Recommendation |
|:--|:--|:--|
| **D-1** | Lifetime tier — offer it, at what price/position? | Keep $47/yr as the anchor; a lifetime option only as a bounded early-bird capitalization play, not the default. |
| **D-2** | Contributor payment — how do people earn for *writing* workflows, not just referring? | **Resolve before launch** — it's the engine of the "living book." Royalty pool, per-workflow bounty, or an explicit "v1 authored, paid contribution in Q1." |
| **D-1** | ~~Lifetime~~ **Signed 2026-08-31:** **$47/yr** only. No lifetime SKU as an equal product. | Locked. |
| **D-2** | ~~Writer pay~~ **Signed 2026-08-31:** founding writers on **contract**. v1 authored. Layer 2 royalties later. | Locked for v1. |
| **D-3** | Confirm the two unconfirmed co-authors (Higher Ed, Communities) | Confirm this week, or cut those verticals from v1 and add post-launch. |
| **D-4** | Refresh the source-of-truth plan to the 9/26 dates & re-signed terms | Do after D-1/D-2 land. |
| **D-5** | Human-first or agent-first for v1? | Human-first. Build the format so agents *can* read it later; optimize v1 for human learners. |
+18 -17
View File
@@ -1,15 +1,15 @@
# 📚 AIBook.fun
# 📚 AiBook.fun
**A living, crowd-written field guide to using AI agents responsibly at work.**
AIBook.fun's unit of content isn't a chapter — it's a **workflow you can actually run**: a
documented, tested recipe for getting a real job done with AI, guardrails included. It's written
and kept current by the practitioners who use it, and it launches as an annual subscription,
crowdfunded on Kickstarter.
People read **chapters**. Each chapter is a substantial essay for one vertical, with full
workflows nested in the argument. The workflow is the unit of practice: a documented, tested
recipe for a real job, guardrails included. The first edition is written on contract by founding
authors. It launches as a **$47/yr** subscription, crowdfunded on Kickstarter.
> **Status: planning stage.** This repository holds the product's planning documents. The product
> is not yet live, and everything here is a working draft — figures, dates, and commercial terms
> are planning assumptions, not commitments. Public launch is **targeted for September 26, 2026**.
> **Status: planning + writing.** Planning docs and the chapter blank live here. The product is
> not yet live. **$47/yr** is signed. Domain `aibook.fun` is renewed. Other figures and unsigned
> terms are still planning assumptions, not for public quote. Launch target **26 Sep 2026**.
## The idea in one loop
@@ -30,22 +30,23 @@ not read AI theory.
## What's in this repository
This is a documentation and planning repo. Three companion documents define the product:
This is a documentation and writing repo.
| Document | What it covers |
|:--|:--|
| [Product Requirements (PRD)](AiBook_PRD.md) | What we're building and why — scope, requirements, success metrics, open decisions |
| [Product Specification (Spec)](AiBook_Spec.md) | The thinking behind it — vision, principles, content model, business model |
| [Implementation Plan](AiBook_Implementation_Plan.md) | How and when — the path from now to launch and fulfillment |
| [Product Requirements (PRD)](AiBook_PRD.md) | What we're building and why. Scope, requirements, success metrics, open decisions |
| [Product Specification (Spec)](AiBook_Spec.md) | The thinking behind it. Vision, principles, content model, business model |
| [Implementation Plan](AiBook_Implementation_Plan.md) | How and when. Path from now to launch and fulfillment |
| [Chapter structure](workflows/chapter-structure.md) | The blank chapter for review. Copy it into a vertical file when writing starts |
New here? Start with the **[Spec](AiBook_Spec.md)** for the vision, then the **[PRD](AiBook_PRD.md)**
for the specifics.
for the specifics. Writers start at **[chapter structure](workflows/chapter-structure.md)**.
## How it works (the short version)
- **Content:** every entry follows one *Workflow Recipe* template — problem, method (showing the
real tool output), safeguards, evidence, a ~15-minute Try-it, and costs. The template is the
quality guarantee — the structural answer to "how do I know this AI advice isn't made up?"
- **Content:** readers get a chapter essay. Nested in it, every workflow follows one recipe:
problem, actors, setup, safeguards, method (real tool output), evidence, a ~15-minute Try-it,
share, costs, author. Safeguards sit before the steps. The template is the quality guarantee.
- **Editions:** the guide refreshes annually — which is why it's a subscription. AI moves fast,
and stale advice is worthless.
- **Contribution:** the first edition is written by a founding set of co-authors; open community
@@ -61,7 +62,7 @@ for the specifics.
| Post-launch | Fulfill the first edition; open community contribution |
| Later | Cohort learning, annual editions, deeper ecosystem integration |
AIBook.fun is part of the **WeOwnNet** ecosystem.
AiBook.fun is part of the **WeOwnNet** ecosystem.
## License
+12 -1
View File
@@ -1,4 +1,4 @@
# AIBook.fun Marketing Site
# AiBook.fun Marketing Site
Scaffolded for Framer import and Next.js (Cloudflare Pages / DigitalOcean).
@@ -33,3 +33,14 @@ Note: Framer Sites don't run Next.js natively. For a live site with routing (A/B
- 3 sample tiers shown ($10 / $47yr / $4,888)
- No NFT/crypto/Web3 language (Kickstarter compliance scrubbed)
- Event tracking only (not content) — PostHog/Cloudflare Analytics slot available
## Reading demo
A sample reading environment is wired into this Next.js app (pages router).
```bash
npm install
npm run dev
```
Then open [http://localhost:3000/read](http://localhost:3000/read). One chapter is filled (Real Estate, with nested RE-01 and RE-02). This is a demo, not the live book.
+2 -2
View File
@@ -13,8 +13,8 @@ export default function Authors() {
<span className="spec reveal">Who’s writing this</span>
<h2 className="reveal">Practitioners, one per vertical.</h2>
<p className="lede reveal">
Each chapter is owned by someone who does the work — not a generalist writing about
it. Names are announced as co-authors confirm.
Each chapter is owned by someone who does that work for a living. Names go up as
co-authors confirm.
</p>
<div className="auth-grid">
{AUTHORS.map((a) => (
+2 -2
View File
@@ -11,7 +11,7 @@ export default function Book3D() {
<div className="book3d__face book3d__pages" />
<div className="book3d__face book3d__top" />
<div className="book3d__face book3d__spine">
<span>AIBook.fun · Responsible Agentic AI</span>
<span>AiBook.fun · Responsible Agentic AI</span>
</div>
<div className="book3d__face book3d__cover">
<span className="book3d__kicker">The Field Guide</span>
@@ -28,7 +28,7 @@ export default function Book3D() {
<path d="M20 5 L22.6 20 L20 35 L17.4 20 Z" fill="#efe9db" />
<path d="M5 20 L20 17.4 L35 20 L20 22.6 Z" fill="#efe9db" opacity="0.55" />
</svg>
<span className="book3d__brand">AIBook.fun</span>
<span className="book3d__brand">AiBook.fun</span>
</div>
{/* Belly band — the classic publisher's wraparound strip for a themed
tie-in, rather than redesigning the whole cover around it. */}
+7 -7
View File
@@ -1,28 +1,28 @@
const QA = [
{
q: "Is this AI theory, or something I can actually run?",
a: "Something you run. Every workflow shows the real tool output, lists the real steps, and ends in a ~15-minute Try-it on non-confidential sample data. If you can’t run it, it doesn’t ship.",
a: "Something you run. Every workflow shows the real tool output, lists the real steps, and ends in a ~15-minute Try-it on non-confidential sample data. If you can't run it, it doesn't ship.",
open: true,
},
{
q: "How is this different from a course?",
a: "A course teaches concepts; this is a field guide of tested recipes you apply to your real job this week. It refreshes annually because AI moves fast — stale advice is worthless.",
a: "A course teaches concepts. This is a field guide of tested recipes you apply to your job this week. The recipes get rewritten as the tools change, not left sitting until next year.",
},
{
q: "What does “responsible by design” actually mean?",
a: "Every recipe includes data-handling rules, human-oversight steps, failure modes, and escalation paths. They’re part of the template — not an appendix, not an afterthought.",
q: "What does \"responsible by design\" actually mean?",
a: "Every recipe includes data-handling rules, human-oversight steps, failure modes, and escalation paths. They sit in the template above Method, not in a footnote.",
},
{
q: "Can I contribute a workflow after backing?",
a: "Yes — open contribution opens once the founding library is live. We’re finalizing how contributors get paid (not just a byline) before launch.",
a: "Yes. Open contribution starts once the founding library is live. How contributors get paid is still being finalized before launch.",
},
{
q: "Why subscribe instead of buy once?",
a: "Because a static AI book is out of date in months. The subscription is what keeps every workflow current — and it’s what funds the practitioners keeping them that way.",
a: "A one-time AI book goes stale in weeks. The $47/yr subscription funds ongoing updates as models and products move, often weekly or monthly.",
},
{
q: "Why frame this around the American Dream?",
a: "Because for most of the people writing and reading this guide, real fluency with these tools isn’t a slogan — it’s a practical ladder. Nobody in this book inherited their edge; they built it, one real skill at a time. We think this is the next one worth building.",
a: "For most of the people writing and reading this guide, fluency with these tools is a practical ladder. Nobody in this book inherited their edge. They built it, one real skill at a time. We think this is the next one worth building.",
},
];
+6 -6
View File
@@ -1,18 +1,18 @@
const NOTES = [
{
n: "01 / Stays current",
h: "A subscription, not a static book",
p: "AI moves too fast for a book you buy once. Each annual edition is refreshed so the ground you gain here doesn’t erode the moment you look away.",
h: "Rewritten as the tools move",
p: "Models and products change by the week. We update recipes when a step breaks or a better path shows up, often weekly or monthly. The $47/yr subscription is what pays for that work.",
},
{
n: "02 / Authored, then open",
h: "Written by practitioners first",
p: "The first edition is seeded by co-authors — a real founding library, not an empty shelf. Open, paid contribution opens once it’s worth browsing, so the people who build it get to own a piece of it.",
h: "Co-authors fill it before launch",
p: "Founding writers are on contract. They write and test the first library. Outside contribution opens later, once there is a real catalog to join, not an empty page waiting for strangers.",
},
{
n: "03 / Responsible by design",
h: "Guardrails in every recipe",
p: "Data handling, human oversight, failure modes, escalation — part of the template on every workflow, never an appendix.",
h: "Safeguards sit above the steps",
p: "Every recipe names what never goes in the prompt, who reviews before anything leaves the building, and when you stop. That block is read before Method.",
},
];
+3 -4
View File
@@ -5,17 +5,16 @@ export default function Footer() {
<div className="foot-top">
<div>
<div className="logo">
AIBook<b>.</b>
AiBook<b>.</b>
<span className="dot">fun</span>
</div>
<p className="foot-blurb">
A living, crowd-written field guide to using AI agents responsibly at work. Part
of the WeOwnNet ecosystem.
An authored field guide of runnable AI workflows for work. Part of the WeOwnNet
ecosystem.
</p>
</div>
<div className="foot-links">
<a href="#recipe">A recipe</a>
<a href="#contents">Contents</a>
<a href="#get">Preview</a>
<a href="#faq">FAQ</a>
</div>
+4 -3
View File
@@ -27,9 +27,10 @@ export default function Hero() {
<span className="serif-it">responsibly</span> at work.
</h1>
<p className="hero-sub">
Not theory. Not hype. A subscription guide of{" "}
<span className="hl">tested workflows you can actually run</span> — each with the
real tool output, the guardrails, and a 15-minute exercise so you learn by doing.
A living subscription guide of{" "}
<span className="hl">tested workflows you can run</span>. Each one shows the real
tool output, the safeguards, and a 15-minute Try-it. Recipes get updated as the
tools change.
</p>
<EmailForm className="hero-form" cta="Send me the preview chapter" />
<p className="hero-note">
+7 -7
View File
@@ -4,17 +4,17 @@ export default function Letter() {
<div className="letter-in">
<span className="spec reveal">A note on why</span>
<p className="letter-body reveal">
Most AI advice is either hype or theory — and neither survives contact with real
work. We’re writing the guide we wish we’d had: workflows that <em>actually run</em>,
with the <span className="mark">guardrails built in</span>, kept honest by the people
who use them every day. For a lot of us, mastering these tools isn’t optional
anymore — it’s how you build the life you’re working toward. Fund the first edition,
and you don’t just get the book — you help decide what goes in it.
Most AI advice is hype or theory, and neither survives contact with real work. We are
writing the guide we wish we had: workflows that <em>actually run</em>, with the{" "}
<span className="mark">safeguards built in</span>, kept current by the people who use
them every day as the tools move. For a lot of us, fluency with these tools is how you
build the life you are working toward. Fund the first edition and you help decide what
goes in it.
</p>
<div className="sign reveal">
<span className="scrawl">The co-authors</span>
<span className="who">
AIBook.fun founding team
AiBook.fun founding team
<br />
Real estate · finance · leadership · tech
</span>
+32 -13
View File
@@ -1,12 +1,27 @@
import { useEffect, useRef, useState } from "react";
import Link from "next/link";
const LINKS = [
{ href: "#recipe", label: "A recipe" },
{ href: "#contents", label: "Contents" },
{ href: "#letter", label: "Why" },
{ href: "#faq", label: "FAQ" },
];
function NavItem({ href, label, onClick }) {
if (href.startsWith("/")) {
return (
<Link href={href} onClick={onClick}>
{label}
</Link>
);
}
return (
<a href={href} onClick={onClick}>
{label}
</a>
);
}
export default function Nav() {
const [scrolled, setScrolled] = useState(false);
const [open, setOpen] = useState(false);
@@ -39,22 +54,25 @@ export default function Nav() {
return (
<nav ref={navRef} className={`nav${scrolled ? " scrolled" : ""}${open ? " open" : ""}`}>
<div className="nav-in">
<a className="logo" href="#top" onClick={close}>
AIBook<b>.</b>
<Link className="logo" href="/" onClick={close}>
AiBook<b>.</b>
<span className="dot">fun</span>
</a>
</Link>
<div className="nav-links">
{LINKS.map((l) => (
<a key={l.href} href={l.href}>
{l.label}
</a>
<NavItem key={l.href} href={l.href} label={l.label} />
))}
</div>
<a href="#get" className="btn btn-primary nav-cta">
Get the preview
</a>
<div className="nav-actions">
<Link href="/read" className="btn btn-ghost nav-cta" onClick={close}>
Go to Library
</Link>
<a href="#get" className="btn btn-primary nav-cta">
Get the preview
</a>
</div>
<button
type="button"
@@ -70,10 +88,11 @@ export default function Nav() {
<div className="nav-menu" id="mobile-menu">
{LINKS.map((l) => (
<a key={l.href} href={l.href} onClick={close}>
{l.label}
</a>
<NavItem key={l.href} href={l.href} label={l.label} onClick={close} />
))}
<Link href="/read" className="btn btn-ghost" onClick={close}>
Go to Library
</Link>
<a href="#get" className="btn btn-primary" onClick={close}>
Get the preview
</a>
+1 -1
View File
@@ -34,7 +34,7 @@ export default function Recipe() {
<div className="recipe reveal">
<div className="recipe-top">
<span className="recipe-id">
recipe <b>RE-04</b> · v1.2 · ~15 min
recipe <b>RE-01</b> · v1.2 · ~15 min
</span>
<span className="recipe-vert">Real Estate</span>
</div>
+5 -5
View File
@@ -9,7 +9,7 @@ export default function Tiers() {
</div>
<p className="tiers-note reveal">
Preview of planned pledge tiers. Final pricing is confirmed at the Kickstarter
launch — nothing here is a live checkout yet.
launch. Nothing here is a live checkout yet.
</p>
</div>
<div className="tier-grid">
@@ -19,7 +19,7 @@ export default function Tiers() {
<div className="t-unit">one-time</div>
<div className="t-desc">
The preview chapter, community updates, and an early look at the founding library
as it’s written.
as it is written.
</div>
</div>
<div className="tier feature reveal">
@@ -30,8 +30,8 @@ export default function Tiers() {
</div>
<div className="t-unit">annual subscription</div>
<div className="t-desc">
The full guide — PDF + web reader — and every annual update while you’re
subscribed. Recurring value, no lifetime gimmick.
The full guide in PDF and web reader, plus ongoing recipe updates while you are
subscribed. Billed yearly. No lifetime SKU in v1.
</div>
</div>
<div className="tier reveal">
@@ -40,7 +40,7 @@ export default function Tiers() {
<div className="t-unit">limited · final terms at launch</div>
<div className="t-desc">
A named acknowledgment in the guide, a private cohort seat, and a hand in shaping
the first edition — the ground floor of something you helped build.
the first edition.
</div>
</div>
</div>
@@ -0,0 +1,60 @@
import { collectChapterKit } from "../../data/sample-chapter";
export default function ChapterKit({ recipes }) {
const kit = collectChapterKit(recipes);
if (!kit.tools.length && !kit.files.length) return null;
return (
<section className="chapter-kit" id="need" aria-label="What you need">
<h2 className="chapter-kit-title">What you need</h2>
<p className="chapter-kit-lede">
{recipes.length} Try-it{recipes.length === 1 ? "" : "s"} on sample data. Nothing
from a live client file.
</p>
<dl className="kit-grid">
<div>
<dt>Tools</dt>
<dd>
<ul>
{kit.tools.map((t) => (
<li key={t}>{t}</li>
))}
</ul>
</dd>
</div>
<div>
<dt>Files</dt>
<dd>
<ul>
{kit.files.map((f) => (
<li key={f}>{f}</li>
))}
</ul>
</dd>
</div>
<div>
<dt>Model</dt>
<dd>
<ul>
{kit.models.map((m) => (
<li key={m}>{m}</li>
))}
</ul>
</dd>
</div>
<div>
<dt>Try-its</dt>
<dd>
<ul>
{kit.tryits.map((t) => (
<li key={t.id}>
{t.id} · {t.time} · {t.cost}
</li>
))}
</ul>
</dd>
</div>
</dl>
</section>
);
}
@@ -0,0 +1,99 @@
import { useEffect, useMemo, useState } from "react";
function OutlineBody({ groups, complete, count, total, active, showTitle }) {
return (
<>
<p className="outline-progress">
{count}/{total} Try-its complete
</p>
{showTitle ? <p className="outline-heading">In this chapter</p> : null}
{groups.map((g) => (
<div key={g.label} className="outline-group">
<p className="outline-group-label spec">{g.label}</p>
<ul>
{g.items.map((item) => {
const done = item.recipeId ? !!complete[item.recipeId] : false;
const isActive = active === item.id;
return (
<li key={item.id}>
<a
href={`#${item.id}`}
className={isActive ? "is-active" : undefined}
aria-current={isActive ? "location" : undefined}
>
<span>{item.label}</span>
{done ? (
<span className="outline-done" aria-label="Try-it complete">
✓
</span>
) : null}
</a>
</li>
);
})}
</ul>
</div>
))}
</>
);
}
export default function ChapterOutline({
groups,
complete = {},
count = 0,
total = 0,
variant = "desktop",
}) {
const ids = useMemo(
() => groups.flatMap((g) => g.items.map((item) => item.id)),
[groups]
);
const [active, setActive] = useState(ids[0] || "");
useEffect(() => {
const els = ids.map((id) => document.getElementById(id)).filter(Boolean);
if (!els.length || typeof IntersectionObserver === "undefined") return;
const observer = new IntersectionObserver(
(entries) => {
const visible = entries
.filter((e) => e.isIntersecting)
.sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top);
if (visible[0]?.target?.id) setActive(visible[0].target.id);
},
{ rootMargin: "-88px 0px -55% 0px", threshold: [0, 0.1, 0.25, 0.5, 1] }
);
els.forEach((el) => observer.observe(el));
return () => observer.disconnect();
}, [ids]);
if (variant === "mobile") {
return (
<details className="chapter-outline-mobile">
<summary>In this chapter</summary>
<OutlineBody
groups={groups}
complete={complete}
count={count}
total={total}
active={active}
showTitle={false}
/>
</details>
);
}
return (
<nav className="chapter-outline" aria-label="In this chapter">
<OutlineBody
groups={groups}
complete={complete}
count={count}
total={total}
active={active}
showTitle
/>
</nav>
);
}
@@ -0,0 +1,24 @@
import Link from "next/link";
export default function ReaderCrumbs({ items }) {
return (
<nav className="crumbs" aria-label="Breadcrumb">
<ol>
{items.map((item, i) => (
<li key={item.label}>
{i > 0 ? (
<span className="crumbs-sep" aria-hidden="true">
/
</span>
) : null}
{item.current || !item.href ? (
<span aria-current="page">{item.label}</span>
) : (
<Link href={item.href}>{item.label}</Link>
)}
</li>
))}
</ol>
</nav>
);
}
@@ -0,0 +1,32 @@
import Link from "next/link";
export default function ReaderFooter() {
return (
<footer className="footer reader-footer">
<div className="foot-in">
<div className="foot-top">
<div>
<div className="logo">
AiBook<b>.</b>
<span className="dot">fun</span>
</div>
<p className="foot-blurb">
Reading demo. Not the live book. Workflows sit inside a chapter,
not on a shelf of cards.
</p>
</div>
<div className="foot-links">
<Link href="/">Home</Link>
<Link href="/read">Library</Link>
<Link href="/#get">Preview</Link>
</div>
</div>
<div className="colophon">
© 2026 WeOwnAI · MIT-licensed docs · This page is a reading-environment demo.
<br />
Activation is stored in this browser only. No chatbot. No live client data.
</div>
</div>
</footer>
);
}
@@ -0,0 +1,40 @@
import { useEffect, useState } from "react";
import Link from "next/link";
export default function ReaderNav({ here = "library" }) {
const [scrolled, setScrolled] = useState(false);
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 12);
onScroll();
window.addEventListener("scroll", onScroll, { passive: true });
return () => window.removeEventListener("scroll", onScroll);
}, []);
return (
<nav className={`nav reader-nav${scrolled ? " scrolled" : ""}`}>
<div className="nav-in">
<Link className="logo" href="/">
AiBook<b>.</b>
<span className="dot">fun</span>
</Link>
<div className="nav-links reader-links">
{here === "library" ? (
<span className="nav-current" aria-current="page">
Library
</span>
) : (
<Link href="/read" className="nav-title">
Library
</Link>
)}
</div>
<Link href="/#get" className="btn btn-primary nav-cta">
Get the preview
</Link>
</div>
</nav>
);
}
@@ -0,0 +1,60 @@
/** Same terminal chrome as the marketing Recipe (.term / .term-bar). */
export function TermRE01() {
return (
<div className="term" role="img" aria-label="Sample terminal output from the workflow">
<div className="term-bar">
<i></i>
<i></i>
<i></i>
<span>agent — property-brief · sample dataset (non-confidential)</span>
</div>
<pre>
<span className="c-dim">{"$ "}</span>
<span className="c-user">{"brief"}</span>
{" --input "}
<span className="c-key">{"sample_listings.csv"}</span>
{" --template market-1pager\n\n"}
<span className="c-dim">{"✓ redacted 3 fields (owner_name, phone, exact_address)\n✓ 41 comps in radius · median $/sqft computed\n\n"}</span>
<span className="c-ok">{"MARKET BRIEF — Maple Heights (sample)\n"}</span>
{" · Median list: $420/sqft (▲ 4.1% QoQ)\n · Days on market: 22 (was 31)\n · Inventory: 1.8 mo — seller-leaning\n · Read: price to comp, expect <2 wks at ask\n\n"}
<span className="c-dim">{"# cost this run: $0.03 · model: claude · 2,140 tokens"}</span>
</pre>
</div>
);
}
export function TermRE02() {
return (
<div className="term" role="img" aria-label="Sample terminal output from the listing-copy workflow">
<div className="term-bar">
<i></i>
<i></i>
<i></i>
<span>agent — listing-copy · sample comps (public facts)</span>
</div>
<pre>
<span className="c-dim">{"$ "}</span>
<span className="c-user">{"listing-copy"}</span>
{" --input "}
<span className="c-key">{"sample_comps.json"}</span>
{" --voice house-voice --out draft.md\n\n"}
<span className="c-dim">{"✓ used 6 public comps (no CRM fields present)\n✓ 184 words · reading grade 8\n\n"}</span>
<span className="c-ok">{"LISTING DRAFT · 14xx Cedar (sample street, public facts)\n"}</span>
{" · Bright corner lot, 3 bed / 2 bath, maple kitchen from 2019.\n · Priced to the block: comps closed $398–$441/sqft in 60 days.\n · No owner name, phone, or showing list in the prompt.\n\n"}
<span className="c-dim">{"# cost this run: $0.02 · model: claude · 1,280 tokens"}</span>
</pre>
</div>
);
}
const TERMS = {
"re-01": TermRE01,
"re-02": TermRE02,
};
export default function TermOutput({ id }) {
const Cmp = TERMS[id];
if (!Cmp) return null;
return <Cmp />;
}
@@ -0,0 +1,262 @@
import { useState } from "react";
import Link from "next/link";
import TermOutput from "./TermOutput";
const JUMP = [
{ id: "kit", label: "Kit" },
{ id: "problem", label: "Problem" },
{ id: "actors", label: "Actors" },
{ id: "setup", label: "Setup" },
{ id: "safeguards", label: "Safeguards" },
{ id: "method", label: "Method" },
{ id: "evidence", label: "Evidence" },
{ id: "tryit", label: "Try-it" },
];
function ShieldCheck() {
return (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path
d="M8 1.5 2.5 4v3.5c0 3 2.3 5.4 5.5 7 3.2-1.6 5.5-4 5.5-7V4L8 1.5Z"
stroke="#1C5D4C"
strokeWidth="1.3"
strokeLinejoin="round"
/>
<path
d="m5.6 8 1.7 1.7L10.6 6"
stroke="#1C5D4C"
strokeWidth="1.3"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
function CheckMark() {
return (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<circle cx="8" cy="8" r="7" stroke="currentColor" strokeWidth="1.4" />
<path
d="m5.2 8.2 1.8 1.8 3.8-4"
stroke="currentColor"
strokeWidth="1.4"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
async function copyText(text) {
try {
await navigator.clipboard.writeText(text);
return true;
} catch {
try {
const el = document.createElement("textarea");
el.value = text;
el.setAttribute("readonly", "");
el.style.position = "fixed";
el.style.left = "-9999px";
document.body.appendChild(el);
el.select();
const ok = document.execCommand("copy");
el.remove();
return ok;
} catch {
return false;
}
}
}
function WorkflowKit({ recipe }) {
const k = recipe.kit;
if (!k) return null;
const rows = [
["You run", k.youRun],
["Tools", (k.tools || []).join(" · ")],
["Files", (k.files || []).join(" · ")],
["Model", k.model],
["Time", recipe.time],
["Cost", recipe.cost],
["You produce", k.artifact],
].filter(([, v]) => v);
return (
<dl className="workflow-kit" id={`${recipe.anchor}-kit`} aria-label="What this workflow uses">
{rows.map(([label, value]) => (
<div key={label}>
<dt>{label}</dt>
<dd>{value}</dd>
</div>
))}
</dl>
);
}
function Field({ anchor, name, label, children }) {
return (
<div className="row" id={`${anchor}-${name}`}>
<h4 className="k">{label}</h4>
<div className="v">{children}</div>
</div>
);
}
export default function WorkflowBlock({
recipe,
complete = false,
onToggleComplete,
focused = false,
index = 1,
total = 1,
}) {
const [copied, setCopied] = useState(false);
const a = recipe.anchor;
const onShare = async () => {
const ok = await copyText(recipe.shareBlurb);
if (!ok) return;
setCopied(true);
window.setTimeout(() => setCopied(false), 1800);
};
return (
<article
id={a}
className={`recipe recipe-nested${focused ? " recipe-focus" : ""}`}
aria-labelledby={`${a}-title`}
>
<div className="recipe-top">
<span className="recipe-id">
Workflow {index} of {total} · <b>{recipe.id}</b> · v{recipe.version} · {recipe.time} · {recipe.cost}
</span>
<span className="recipe-vert">{recipe.vertical}</span>
</div>
<div className="recipe-body">
<h3 className="recipe-title" id={`${a}-title`}>
{recipe.title}
</h3>
<WorkflowKit recipe={recipe} />
<nav className="recipe-jump" aria-label="In this workflow">
{JUMP.map((j) => (
<a key={j.id} href={`#${a}-${j.id}`}>
{j.label}
</a>
))}
</nav>
<Field anchor={a} name="problem" label="Problem">
{recipe.problem} <span className="sub">{recipe.problemJob}</span>
</Field>
<Field anchor={a} name="actors" label="Actors">
<ul className="plain-list">
{recipe.actors.map((line) => (
<li key={line}>{line}</li>
))}
</ul>
</Field>
<Field anchor={a} name="setup" label="Setup">
<ul className="plain-list">
{recipe.setup.map((line) => (
<li key={line}>{line}</li>
))}
</ul>
</Field>
<Field anchor={a} name="safeguards" label="Safeguards">
{recipe.safeguards.map((line) => (
<div className="guard" key={line}>
<ShieldCheck />
<span>{line}</span>
</div>
))}
</Field>
<Field anchor={a} name="method" label="Method">
<ol className="steps">
{recipe.method.map((step, i) => (
<li key={i}>
<div className="step-copy">
{step.text}
{step.term ? <TermOutput id={step.term} /> : null}
</div>
</li>
))}
</ol>
</Field>
<Field anchor={a} name="evidence" label="Evidence">
{recipe.evidence.map((line) => (
<p key={line} className="evidence-p">
{line}
</p>
))}
</Field>
<Field anchor={a} name="tryit" label="Try-it">
<p>
About {recipe.tryit.minutes} minutes. {recipe.tryit.sample}{" "}
{recipe.tryit.produce}
</p>
<p className="sub-line">
{recipe.tryit.done}{" "}
<a className="inline-sample" href={recipe.tryit.href} download>
{recipe.tryit.hrefLabel}
</a>
</p>
<p>
<span className="chip">◷ {recipe.tryit.chip}</span>
</p>
{onToggleComplete ? (
<div className="tryit-actions">
<button
type="button"
className={`btn ${complete ? "btn-primary tryit-done" : "btn-ghost"}`}
aria-pressed={complete}
onClick={() => onToggleComplete(recipe.id)}
>
{complete ? <CheckMark /> : null}
{complete ? "Counted as activation (demo)" : "Mark complete"}
</button>
</div>
) : null}
</Field>
<Field anchor={a} name="share" label="Share">
<p>Copy a short result line. Share the outcome, not the recipe text.</p>
<div className="tryit-actions">
<button type="button" className="btn btn-ghost" onClick={onShare}>
{copied ? "Copied" : "Copy result line"}
</button>
</div>
</Field>
<Field anchor={a} name="record" label="Record">
<div className="recipe-record">
<span>Author: {recipe.author}</span>
<span>Sources: {recipe.sources}</span>
<span>Last updated: {recipe.lastUpdated}</span>
{focused ? (
<span>
<Link href={`/read/real-estate#${recipe.anchor}`}>
Back to the chapter
</Link>
</span>
) : (
<span>
<Link href={`/read/recipe/${recipe.id}`}>Open on paper</Link>
</span>
)}
</div>
</Field>
</div>
</article>
);
}
@@ -0,0 +1,35 @@
export default function WorkflowRail({ recipes, complete = {}, total }) {
return (
<aside className="chapter-rail" aria-label="Workflows in this chapter">
<p className="spec">Workflows in this chapter</p>
<ol className="rail-list">
{recipes.map((r, i) => {
const done = !!complete[r.id];
return (
<li key={r.id}>
<a className={`rail-card${done ? " is-done" : ""}`} href={`#${r.anchor}`}>
<span className="rail-kicker">
{i + 1} of {total} · {r.id}
</span>
<span className="rail-title">{r.shortTitle}</span>
<span className="rail-meta">
{r.time} · {r.cost}
{done ? " · done" : ""}
</span>
{r.kit && r.kit.tools && r.kit.tools.length ? (
<span className="rail-kit">{r.kit.tools.join(" · ")}</span>
) : null}
{r.kit && r.kit.artifact ? (
<span className="rail-kit rail-out">{r.kit.artifact}</span>
) : null}
</a>
</li>
);
})}
</ol>
<a className="rail-skip" href={`#${recipes[0]?.anchor}-tryit`}>
Skip to the first Try-it
</a>
</aside>
);
}
@@ -0,0 +1,43 @@
import { useCallback, useEffect, useMemo, useState } from "react";
function keyFor(id) {
return `aibook-demo-activation:${id}`;
}
/**
* Demo-only activation state. Completing a Try-it writes
* localStorage key `aibook-demo-activation:<RECIPE-ID>`.
*/
export default function useActivation(ids) {
const list = useMemo(() => ids, [ids.join("|")]);
const [complete, setComplete] = useState(() =>
Object.fromEntries(list.map((id) => [id, false]))
);
useEffect(() => {
const next = {};
list.forEach((id) => {
try {
next[id] = window.localStorage.getItem(keyFor(id)) === "1";
} catch {
next[id] = false;
}
});
setComplete(next);
}, [list]);
const toggle = useCallback((id) => {
setComplete((prev) => {
const value = !prev[id];
try {
window.localStorage.setItem(keyFor(id), value ? "1" : "0");
} catch {
/* private mode: still toggle in memory */
}
return { ...prev, [id]: value };
});
}, []);
const count = list.filter((id) => complete[id]).length;
return { complete, toggle, count, total: list.length };
}
+311
View File
@@ -0,0 +1,311 @@
/**
* Sample chapter + nested recipes for the reading demo.
* Imported by pages under /read. Not a CMS.
*/
export const LIBRARY = [
{
num: "01",
name: "Real Estate",
slug: "real-estate",
href: "/read/real-estate",
desc: "Market briefs and listings, without leaking client data",
status: "ready",
},
{
num: "02",
name: "Financial Advisors",
slug: "financial-advisors",
desc: "Portfolio summaries that stay compliant and reviewed",
status: "coming",
},
{
num: "03",
name: "Fractional C-Suite",
slug: "fractional-c-suite",
desc: "Board updates and plans with real escalation paths",
status: "coming",
},
{
num: "04",
name: "Higher Ed",
slug: "higher-ed",
desc: "Course and research workflows with academic integrity",
status: "coming",
},
{
num: "05",
name: "Communities",
slug: "communities",
desc: "Moderation and programming that respects members",
status: "coming",
},
{
num: "06",
name: "Technology",
slug: "technology",
desc: "Agent patterns, evals, and the responsible defaults",
status: "coming",
},
];
const RE01 = {
id: "RE-01",
anchor: "re-01",
version: "1.2",
time: "~15 min",
cost: "≈ $0.03",
vertical: "Real Estate",
shortTitle: "Market brief",
title: "Draft a property-market brief with an AI agent without leaking client data.",
problem:
"You need a neighborhood market brief for a client meeting this week. The listing sheet and client notes cannot go into a public model.",
problemJob:
"Job: turn messy local data into a credible one-pager in minutes, safely.",
actors: [
"Listing agent runs it.",
"Client receives the brief.",
"Model may draft and classify. A human must review before send.",
],
setup: [
"Tools: local redaction script (brief CLI), Claude or your usual model.",
"Sample files: sample_listings.csv, market-1pager template.",
"Cost: about $0.03 on the sample run (2,140 tokens).",
],
safeguards: [
"Redaction runs on your machine. Raw client data never reaches the model.",
"A human checklist is required before the brief is shared. The checklist is part of the recipe.",
"Stop if identifiers remain after the strip report. Do not prompt until owner_name, phone, and exact_address are gone.",
],
method: [
{
text: "Strip identifiers from the source data locally (a provided script does this).",
},
{
text: "Prompt the agent with the anonymized sample and a fixed brief template.",
term: "re-01",
},
{
text: "Review the draft against the checklist before anything leaves your machine.",
},
],
evidence: [
"A one-pager brief on Maple Heights (sample), ready for a meeting once a human signs the checklist.",
"Sample metrics from that run: median $420/sqft, 22 days on market, 1.8 months of inventory.",
],
tryit: {
minutes: 15,
sample: "Use the included sample_listings.csv (no live client file).",
produce: "Produce the market-1pager brief and walk the human checklist.",
done: "Mark complete when you have a brief you would send after review. Completing this is the activation demo.",
href: "/samples/sample_listings.csv",
hrefLabel: "sample_listings.csv",
chip: "cost to try ≈ $0.03",
},
shareBlurb:
"Ran RE-01 on sample comps. Maple Heights median $420/sqft, 22 DOM.",
author: "Founding library · sample",
sources: "Sample MLS packet (non-confidential); market-1pager template shipped with the recipe.",
lastUpdated: "31 Aug 2026",
kit: {
youRun: "Listing agent",
tools: ["brief CLI (local redaction)", "Claude"],
files: ["sample_listings.csv", "market-1pager template"],
model: "Claude",
artifact: "One-pager market brief",
},
};
const RE02 = {
id: "RE-02",
anchor: "re-02",
version: "1.0",
time: "~12 min",
cost: "≈ $0.02",
vertical: "Real Estate",
shortTitle: "Listing copy",
title: "Rewrite a listing description from public comps without pasting the client address book.",
problem:
"You need listing copy that sounds like this house, not every house on the street. The CRM holds owner notes and the showing list. Those do not go into a public model.",
problemJob:
"Job: draft 180-word listing copy from public facts only, then edit it yourself.",
actors: [
"Listing agent runs it.",
"The public listing receives the copy.",
"Model drafts. A human edits, files, and posts to MLS.",
],
setup: [
"Tools: listing-copy CLI, listing-voice template, Claude or your usual model.",
"Sample files: sample_comps.json (public comps only).",
"Cost: about $0.02 on the sample run (1,280 tokens).",
],
safeguards: [
"Prompt only with public listing facts. No CRM export, no showing list, no owner notes.",
"A human edits the draft before it hits MLS. Do not auto-post.",
"Stop if a private note, phone, or exact owner name appears in the draft.",
],
method: [
{
text: "Export public comps for the block. Leave the CRM closed.",
},
{
text: "Run listing-copy against the sample comps and the house-voice template.",
term: "re-02",
},
{
text: "Edit the draft. Cut anything that could only have come from a private note.",
},
],
evidence: [
"A 184-word listing draft, public facts only, reading grade 8.",
"Comps on the block closed between $398 and $441/sqft in 60 days. The draft prices to that range without naming a client.",
],
tryit: {
minutes: 12,
sample: "Use the included sample_comps.json (public comps, no address book).",
produce: "Produce a ~180-word listing description and a human edit pass.",
done: "Mark complete when the draft has no private fields. Completing this is the activation demo.",
href: "/samples/sample_comps.json",
hrefLabel: "sample_comps.json",
chip: "cost to try ≈ $0.02",
},
shareBlurb:
"Ran RE-02 on sample comps. 184-word listing draft, public facts only.",
author: "Founding library · sample",
sources: "Public comps sample packet; listing-voice template shipped with the recipe.",
lastUpdated: "31 Aug 2026",
kit: {
youRun: "Listing agent",
tools: ["listing-copy CLI", "Claude"],
files: ["sample_comps.json", "listing-voice template"],
model: "Claude",
artifact: "180-word listing draft",
},
};
export const RECIPES = [RE01, RE02];
export const RECIPES_BY_ID = {
"RE-01": RE01,
"RE-02": RE02,
// Old demo URLs. Displayed ID is RE-01 / RE-02.
"RE-04": RE01,
"RE-05": RE02,
};
export const CHAPTER = {
slug: "real-estate",
vertical: "Real Estate",
edition: "2026",
authors: "Founding library · sample",
title: "Work the listing without leaking the client",
promise:
"In this chapter you run two jobs a realtor actually has this week, on sample data, without putting a client file in a public model.",
lastUpdated: "31 Aug 2026",
skip: [
{ id: "RE-01", href: "#re-01", title: "Market brief" },
{ id: "RE-02", href: "#re-02", title: "Listing copy" },
],
stakes: {
id: "stakes",
heading: "The stakes",
paragraphs: [
"A listing that stalls because the market brief is late is a lost weekend. A listing that leaks because you pasted the client sheet into a public model is a lost license. Real estate work runs on both clocks: the showing at 4pm, and the file that must never leave the office.",
"The failure is not that AI sits unused. It is a one-pager that is late, generic, or built from a client name that should not have been in the prompt. Buyers notice fluff. Brokers notice a privacy incident. Neither is recoverable in the same week.",
],
},
constraints: {
id: "constraints",
heading: "Constraints you cannot ignore",
paragraphs: [
"You already work in MLS exports, a CRM, and a phone that rings during the write-up. Done is a brief the client can read in a meeting, with numbers you can stand behind, reviewed by a human. Public models are useful for draft and classify. They are not a filing cabinet.",
"Owner names, phones, exact addresses, and showing lists stay on your machine. Comps, medians, and days on market can travel, once identifiers are stripped. If a field could pick one household out of the block, it does not go in the prompt.",
],
},
practice: {
id: "practice",
heading: "How we work here",
paragraphs: [
"Redact locally. Prompt with a sample or a stripped file. Review against a checklist. Share the artifact, not the workflow text. The first job this week is the neighborhood market brief. Run it on sample comps before you touch a live listing.",
],
},
between: {
id: "between",
heading: "The brief is half the meeting",
paragraphs: [
"The brief gets you into the room with numbers. The other half is the listing copy: public comps, a description that does not sound like every other house on the street, and an address book that never belongs in the prompt. Same rule. Different job.",
],
},
further: [
{ id: "RE-01", href: "#re-01", title: "Draft a property-market brief without leaking client data" },
{ id: "RE-02", href: "#re-02", title: "Rewrite a listing description from public comps" },
{ id: "RE-03", title: "Offer-response notes from public remarks (later)", coming: true },
],
sources: [
"Sample MLS packet shipped with this chapter (non-confidential).",
"market-1pager and listing-voice templates in the recipe kit.",
"Local redaction fields: owner_name, phone, exact_address.",
],
};
/** Outline groups for the chapter map. Headings come from the essay objects. */
export function buildOutline(chapter, recipes) {
return [
{
label: "Start",
items: [{ id: "need", label: "What you need" }],
},
{
label: "Essay",
items: [chapter.stakes, chapter.constraints, chapter.practice, chapter.between].map((s) => ({
id: s.id,
label: s.heading,
})),
},
{
label: "Workflows",
items: recipes.map((r) => ({
id: r.anchor,
recipeId: r.id,
label: r.id + " · " + r.shortTitle,
time: r.time,
shortTitle: r.shortTitle,
tools: r.kit && r.kit.tools ? r.kit.tools.join(", ") : "",
})),
},
{
label: "End",
items: [
{ id: "further", label: "Further workflows" },
{ id: "sources", label: "Sources" },
],
},
];
}
/** Union of recipe kits for the chapter "What you need" strip. */
export function collectChapterKit(recipes) {
const tools = [];
const files = [];
const models = [];
const add = (arr, value) => {
if (value && !arr.includes(value)) arr.push(value);
};
recipes.forEach((r) => {
const k = r.kit || {};
(k.tools || []).forEach((item) => add(tools, item));
(k.files || []).forEach((item) => add(files, item));
add(models, k.model);
});
return {
tools,
files,
models,
tryits: recipes.map((r) => ({
id: r.id,
time: r.time,
cost: r.cost,
artifact: r.kit && r.kit.artifact,
})),
};
}
-3
View File
@@ -1,9 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
// Deploy layer (deploy/docker/Dockerfile) builds the standalone
// output. No runtime behavior change for preview/dev.
output: 'standalone',
// A stray package-lock.json sits at the repo root; pin the workspace root here
// so Turbopack doesn't infer the wrong one.
turbopack: {
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "aibook-fun-marketing",
"version": "1.0.0",
"private": true,
"description": "AIBook.fun — pre-launch marketing site (field-guide design)",
"description": "AiBook.fun — pre-launch marketing site (field-guide design)",
"license": "MIT",
"scripts": {
"dev": "next dev -p 3000",
+2 -2
View File
@@ -18,10 +18,10 @@ export default function Home() {
return (
<>
<Head>
<title>AIBook.fun — a field guide to AI agents at work</title>
<title>AiBook.fun · a field guide to AI agents at work</title>
<meta
name="description"
content="A living, crowd-written field guide to using AI agents responsibly at work. Tested workflows you can run — launching on Kickstarter, Sept 26, 2026."
content="An authored field guide of runnable AI workflows for work. Updated as the tools change. Kickstarter Sept 26, 2026. $47/yr."
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
+56
View File
@@ -0,0 +1,56 @@
import Head from "next/head";
import Link from "next/link";
import ReaderNav from "../../components/reader/ReaderNav";
import ReaderFooter from "../../components/reader/ReaderFooter";
import { LIBRARY, RECIPES } from "../../data/sample-chapter";
export default function ReadLibrary() {
return (
<>
<Head>
<title>Library · AiBook.fun reading demo</title>
<meta
name="description"
content="Library for the 2026 AiBook.fun field guide. Six verticals. One preview chapter open."
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<ReaderNav />
<main>
<section className="section contents reader-library">
<div className="wrap reader-wide">
<span className="spec demo-chip">Reading demo · not the live book</span>
<h1 className="library-title">Library</h1>
<p className="library-lede">
Six verticals for the 2026 edition.
</p>
<div className="toc">
{LIBRARY.map((item) =>
item.status === "ready" ? (
<Link href={item.href} key={item.num}>
<span className="num">{item.num}</span>
<span className="name">{item.name}</span>
<span className="desc">{item.desc}</span>
<span className="toc-count">{RECIPES.length} workflows</span>
<span className="arrow" aria-hidden="true">
→
</span>
</Link>
) : (
<div className="toc-soon" key={item.num} aria-disabled="true">
<span className="num">{item.num}</span>
<span className="name">{item.name}</span>
<span className="desc">{item.desc}</span>
<span className="soon">Coming</span>
</div>
)
)}
</div>
</div>
</section>
</main>
<ReaderFooter />
</>
);
}
+208
View File
@@ -0,0 +1,208 @@
import { useEffect, useMemo } from "react";
import Head from "next/head";
import ReaderNav from "../../components/reader/ReaderNav";
import ReaderCrumbs from "../../components/reader/ReaderCrumbs";
import ReaderFooter from "../../components/reader/ReaderFooter";
import WorkflowBlock from "../../components/reader/WorkflowBlock";
import ChapterOutline from "../../components/reader/ChapterOutline";
import WorkflowRail from "../../components/reader/WorkflowRail";
import ChapterKit from "../../components/reader/ChapterKit";
import useActivation from "../../components/reader/useActivation";
import { CHAPTER, RECIPES, buildOutline } from "../../data/sample-chapter";
const RECIPE_IDS = RECIPES.map((r) => r.id);
const ESSAY_KEYS = ["stakes", "constraints", "practice"];
function Essay({ id, heading, paragraphs }) {
return (
<section className="essay" id={id}>
<h2>{heading}</h2>
{paragraphs.map((p) => (
<p key={p}>{p}</p>
))}
</section>
);
}
export default function RealEstateChapter() {
const { complete, toggle, count, total } = useActivation(RECIPE_IDS);
const [first, second] = RECIPES;
const outline = useMemo(() => buildOutline(CHAPTER, RECIPES), []);
const essayGroup = outline.find((g) => g.label === "Essay");
const workflowGroup = outline.find((g) => g.label === "Workflows");
useEffect(() => {
const hash = window.location.hash;
if (!hash) return;
const el = document.getElementById(hash.slice(1));
if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
}, []);
return (
<>
<Head>
<title>{CHAPTER.title} · AiBook.fun reading demo</title>
<meta name="description" content={CHAPTER.promise} />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<ReaderNav here="chapter" />
<main>
<article className="chapter-page">
<div className="wrap reader-wide">
<ReaderCrumbs
items={[
{ href: "/read", label: "Library" },
{ label: CHAPTER.vertical, current: true },
]}
/>
</div>
<div className="wrap reader-wide chapter-shell">
<ChapterOutline
groups={outline}
complete={complete}
count={count}
total={total}
/>
<div className="chapter-col">
<span className="spec demo-chip">Reading demo · not the live book</span>
<p className="spec chapter-kicker">
{CHAPTER.vertical} · {CHAPTER.edition} edition
</p>
<h1 className="chapter-title">{CHAPTER.title}</h1>
<p className="chapter-by">{CHAPTER.authors}</p>
<ChapterOutline
variant="mobile"
groups={outline}
complete={complete}
count={count}
total={total}
/>
<p className="chapter-promise">{CHAPTER.promise}</p>
<ChapterKit recipes={RECIPES} />
<section className="chapter-map" aria-label="What's in this chapter">
<h2 className="chapter-map-title">What's in this chapter</h2>
<div className="chapter-map-block">
<p className="spec">Essay</p>
<ul>
{essayGroup.items.map((item) => (
<li key={item.id}>
<a href={`#${item.id}`}>{item.label}</a>
</li>
))}
</ul>
</div>
<div className="chapter-map-block">
<p className="spec">Workflows</p>
<ul>
{workflowGroup.items.map((item) => (
<li key={item.id}>
<a href={`#${item.id}`}>
{item.recipeId} · {item.shortTitle} · {item.time}
{item.tools ? ` · ${item.tools}` : ""}
</a>
</li>
))}
</ul>
</div>
</section>
<div className="skip-row">
<span className="skip-label">Skip to a Try-it</span>
{RECIPES.map((r) => (
<a key={r.id} className="skip-chip" href={`#${r.anchor}`}>
{r.id}
<span className="skip-chip-job">{r.shortTitle}</span>
</a>
))}
</div>
{ESSAY_KEYS.map((key) => (
<Essay
key={key}
id={CHAPTER[key].id}
heading={CHAPTER[key].heading}
paragraphs={CHAPTER[key].paragraphs}
/>
))}
<p className="spec workflow-kicker">
Workflow 1 of {RECIPES.length} in this chapter
</p>
<WorkflowBlock
recipe={first}
index={1}
total={RECIPES.length}
complete={!!complete[first.id]}
onToggleComplete={toggle}
/>
<Essay
id={CHAPTER.between.id}
heading={CHAPTER.between.heading}
paragraphs={CHAPTER.between.paragraphs}
/>
<p className="spec workflow-kicker">
Workflow 2 of {RECIPES.length} in this chapter
</p>
<WorkflowBlock
recipe={second}
index={2}
total={RECIPES.length}
complete={!!complete[second.id]}
onToggleComplete={toggle}
/>
<section className="end-matter" id="further">
<h2>Further workflows in this vertical</h2>
<ul className="further-list">
{CHAPTER.further.map((item) => (
<li key={item.id}>
{item.coming ? (
<>
<span className="recipe-id">
<b>{item.id}</b>
</span>{" "}
{item.title}
</>
) : (
<>
<a href={item.href}>
<span className="recipe-id">
<b>{item.id}</b>
</span>
</a>{" "}
{item.title}
</>
)}
</li>
))}
</ul>
</section>
<section className="end-sources" id="sources">
<h2>Sources</h2>
<ul className="further-list">
{CHAPTER.sources.map((s) => (
<li key={s}>{s}</li>
))}
</ul>
<p className="chapter-updated">Last updated: {CHAPTER.lastUpdated}</p>
</section>
</div>
<WorkflowRail recipes={RECIPES} complete={complete} total={total} />
</div>
</article>
</main>
<ReaderFooter />
</>
);
}
+91
View File
@@ -0,0 +1,91 @@
import Head from "next/head";
import Link from "next/link";
import { useRouter } from "next/router";
import ReaderNav from "../../../components/reader/ReaderNav";
import ReaderCrumbs from "../../../components/reader/ReaderCrumbs";
import ReaderFooter from "../../../components/reader/ReaderFooter";
import WorkflowBlock from "../../../components/reader/WorkflowBlock";
import useActivation from "../../../components/reader/useActivation";
import { RECIPES, RECIPES_BY_ID } from "../../../data/sample-chapter";
export default function RecipeFocus() {
const router = useRouter();
const raw = typeof router.query.id === "string" ? router.query.id : "";
const recipe = RECIPES_BY_ID[raw] || RECIPES_BY_ID[raw.toUpperCase()] || null;
const { complete, toggle } = useActivation(recipe ? [recipe.id] : []);
if (!router.isReady) {
return (
<>
<ReaderNav here="chapter" />
<main>
<div className="wrap reader-wide recipe-focus-page">
<p className="spec">Loading recipe…</p>
</div>
</main>
</>
);
}
if (!recipe) {
return (
<>
<Head>
<title>Recipe not in this demo · AiBook.fun</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<ReaderNav />
<main>
<div className="wrap reader-wide recipe-focus-page">
<span className="spec demo-chip">Reading demo · not the live book</span>
<h1 className="chapter-title">This recipe is not in the sample.</h1>
<p className="library-lede">
The demo ships two nested workflows, RE-01 and RE-02, inside the Real
Estate chapter.
</p>
<p>
<Link href="/read/real-estate" className="btn btn-primary">
Back to the chapter
</Link>
</p>
</div>
</main>
<ReaderFooter />
</>
);
}
return (
<>
<Head>
<title>{`${recipe.id} on paper · AiBook.fun reading demo`}</title>
<meta name="description" content={recipe.title} />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<ReaderNav here="chapter" />
<main>
<div className="wrap reader-wide recipe-focus-page">
<ReaderCrumbs
items={[
{ href: "/read", label: "Library" },
{ href: "/read/real-estate", label: "Real Estate" },
{ label: recipe.id, current: true },
]}
/>
<span className="spec demo-chip">Reading demo · not the live book</span>
<p className="spec chapter-kicker">Print / focus view</p>
<WorkflowBlock
recipe={recipe}
index={Math.max(RECIPES.findIndex((r) => r.id === recipe.id) + 1, 1)}
total={RECIPES.length}
complete={!!complete[recipe.id]}
onToggleComplete={toggle}
focused
/>
</div>
</main>
<ReaderFooter />
</>
);
}
@@ -0,0 +1,19 @@
{
"note": "Public comps only. No CRM fields, no owner names, no phones, no showing lists.",
"block": "14xx Cedar (sample street)",
"subject": {
"beds": 3,
"baths": 2,
"sqft": 1320,
"year_kitchen": 2019,
"lot": "corner, public record"
},
"comps": [
{ "id": "C1", "closed_price_sqft": 398, "dom": 19, "beds": 3, "baths": 2, "closed_days_ago": 18 },
{ "id": "C2", "closed_price_sqft": 441, "dom": 11, "beds": 3, "baths": 2, "closed_days_ago": 27 },
{ "id": "C3", "closed_price_sqft": 412, "dom": 22, "beds": 3, "baths": 2, "closed_days_ago": 41 },
{ "id": "C4", "closed_price_sqft": 425, "dom": 16, "beds": 3, "baths": 3, "closed_days_ago": 9 },
{ "id": "C5", "closed_price_sqft": 405, "dom": 28, "beds": 2, "baths": 2, "closed_days_ago": 55 },
{ "id": "C6", "closed_price_sqft": 433, "dom": 14, "beds": 3, "baths": 2, "closed_days_ago": 33 }
]
}
@@ -0,0 +1,7 @@
id,neighborhood,list_price,sqft,dom,owner_name,phone,exact_address,beds,baths
MH-01,Maple Heights,504000,1200,18,Jane Client,555-0140,12 Oak Street,3,2
MH-02,Maple Heights,612000,1450,24,Sam Owner,555-0141,88 Birch Avenue,3,2
MH-03,Maple Heights,459000,1100,31,R. Patel,555-0142,4 Cedar Court,2,2
MH-04,Maple Heights,670000,1580,12,Lee Family Trust,555-0143,21 Maple Drive,4,3
MH-05,Maple Heights,538000,1288,22,A. Gomez,555-0144,9 Pine Lane,3,2
MH-06,Maple Heights,481000,1140,27,Hidden,555-0145,16 Walnut Place,3,1
1 id neighborhood list_price sqft dom owner_name phone exact_address beds baths
2 MH-01 Maple Heights 504000 1200 18 Jane Client 555-0140 12 Oak Street 3 2
3 MH-02 Maple Heights 612000 1450 24 Sam Owner 555-0141 88 Birch Avenue 3 2
4 MH-03 Maple Heights 459000 1100 31 R. Patel 555-0142 4 Cedar Court 2 2
5 MH-04 Maple Heights 670000 1580 12 Lee Family Trust 555-0143 21 Maple Drive 4 3
6 MH-05 Maple Heights 538000 1288 22 A. Gomez 555-0144 9 Pine Lane 3 2
7 MH-06 Maple Heights 481000 1140 27 Hidden 555-0145 16 Walnut Place 3 1
+467 -11
View File
@@ -1,7 +1,7 @@
@import "tailwindcss";
/* ============================================================
AIBook.fun — "field guide" design system
AiBook.fun — "field guide" design system
Tokens live in @theme so they're available BOTH as CSS vars
(var(--color-pine)) and as Tailwind utilities (bg-pine, font-display).
============================================================ */
@@ -104,21 +104,33 @@ h1, h2, h3 { text-wrap: balance; margin: 0; }
/* ============ NAV ============ */
.nav {
position: sticky; top: 0; z-index: 50;
background: color-mix(in srgb, var(--color-paper) 82%, transparent);
backdrop-filter: blur(14px) saturate(1.3); -webkit-backdrop-filter: blur(14px) saturate(1.3);
background: var(--color-paper);
border-bottom: 1px solid transparent; transition: border-color 0.3s, box-shadow 0.3s;
}
.nav.scrolled { border-bottom-color: var(--color-line); box-shadow: var(--sh-sm); }
.nav-in {
position: relative;
max-width: var(--wrap); margin: 0 auto; padding: 0 28px; height: 68px;
display: flex; align-items: center; justify-content: space-between; gap: 20px;
}
.logo { display: flex; align-items: baseline; gap: 2px; font-family: var(--font-display); font-weight: 900; font-size: 21px; letter-spacing: -0.02em; }
.logo {
display: flex; align-items: baseline; gap: 2px;
font-family: var(--font-display); font-weight: 900; font-size: 21px; letter-spacing: -0.02em;
flex: none; position: relative; z-index: 1;
}
.logo b { color: var(--color-pine); }
.logo .dot { color: var(--color-muted); font-weight: 500; }
.nav-links { display: flex; align-items: center; gap: 30px; font-size: 14.5px; font-weight: 600; color: var(--color-muted); }
.nav-links {
display: flex; align-items: center; gap: 30px;
font-size: 14.5px; font-weight: 600; color: var(--color-muted);
position: absolute; left: 50%; transform: translateX(-50%);
}
.nav-links a { transition: color 0.18s; }
.nav-links a:hover { color: var(--color-ink); }
.nav-actions {
display: flex; align-items: center; gap: 10px;
flex: none; margin-left: auto; position: relative; z-index: 1;
}
.nav-cta { font-size: 14px; padding: 10px 18px; }
/* mobile hamburger toggle (hidden on desktop) */
@@ -144,6 +156,7 @@ h1, h2, h3 { text-wrap: balance; margin: 0; }
@media (max-width: 860px) {
.nav-links { display: none; }
.nav-actions { display: none; }
.nav-cta { display: none; } /* CTA moves into the menu */
.nav-toggle { display: inline-flex; }
.nav-menu {
@@ -281,7 +294,7 @@ h1, h2, h3 { text-wrap: balance; margin: 0; }
/* ============ RECIPE (value centerpiece) ============ */
.recipe-head { max-width: 40rem; margin-bottom: 44px; }
.recipe-head h2 { font-family: var(--font-display); font-weight: 900; font-size: clamp(2rem, 4.3vw, 3.3rem); letter-spacing: -0.025em; line-height: 1.02; margin: 16px 0 18px; }
.recipe-head h2 { font-family: var(--font-display); font-weight: 900; font-size: clamp(2rem, 4.3vw, 3.3rem); letter-spacing: -0.025em; line-height: 1.15; margin: 16px 0 18px; }
.recipe-head p { color: var(--color-muted); font-size: 1.08rem; }
.recipe { background: var(--color-card); border: 1px solid var(--color-line); border-radius: 20px; box-shadow: var(--sh-lg); overflow: hidden; }
.recipe-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 20px 28px; border-bottom: 1px solid var(--color-line); background: linear-gradient(var(--color-card), var(--color-paper)); }
@@ -327,7 +340,7 @@ h1, h2, h3 { text-wrap: balance; margin: 0; }
/* ============ CONTENTS (table-of-contents) ============ */
.contents { background: var(--color-paper-2); border-top: 1px solid var(--color-line); border-bottom: 1px solid var(--color-line); }
.contents h2 { font-family: var(--font-display); font-weight: 900; font-size: clamp(1.9rem, 4vw, 3rem); letter-spacing: -0.025em; margin: 14px 0 34px; max-width: 20ch; }
.contents h2 { font-family: var(--font-display); font-weight: 900; font-size: clamp(1.9rem, 4vw, 3rem); letter-spacing: -0.025em; line-height: 1.2; margin: 14px 0 34px; max-width: 20ch; }
.toc { border-top: 1px solid var(--color-line-2); }
.toc a { display: grid; grid-template-columns: 52px 1fr auto auto; align-items: center; gap: 20px; padding: 22px 8px; border-bottom: 1px solid var(--color-line); transition: background 0.2s, padding 0.2s; }
.toc a:hover { background: var(--color-pine-wash); padding-left: 16px; }
@@ -352,7 +365,7 @@ h1, h2, h3 { text-wrap: balance; margin: 0; }
@media (max-width: 600px) { .letter-in { padding: 0 20px; } }
/* ============ AUTHORS ============ */
.authors h2 { font-family: var(--font-display); font-weight: 900; font-size: clamp(1.9rem, 3.6vw, 2.7rem); letter-spacing: -0.025em; margin: 14px 0 10px; }
.authors h2 { font-family: var(--font-display); font-weight: 900; font-size: clamp(1.9rem, 3.6vw, 2.7rem); letter-spacing: -0.025em; line-height: 1.2; margin: 14px 0 10px; }
.authors .lede { color: var(--color-muted); max-width: 38rem; margin-bottom: 38px; }
.auth-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.auth { background: var(--color-card); border: 1px solid var(--color-line); border-radius: 16px; padding: 24px; box-shadow: var(--sh-sm); transition: box-shadow 0.2s, transform 0.2s; }
@@ -372,7 +385,7 @@ h1, h2, h3 { text-wrap: balance; margin: 0; }
/* ============ EMAIL CAPTURE ============ */
.capture { background: var(--color-paper-2); border-top: 1px solid var(--color-line); border-bottom: 1px solid var(--color-line); }
.capture-in { max-width: 640px; margin: 0 auto; text-align: center; padding: 0 28px; }
.capture h2 { font-family: var(--font-display); font-weight: 900; font-size: clamp(2rem, 4vw, 3rem); letter-spacing: -0.025em; line-height: 1.02; margin: 16px 0 14px; }
.capture h2 { font-family: var(--font-display); font-weight: 900; font-size: clamp(2rem, 4vw, 3rem); letter-spacing: -0.025em; line-height: 1.15; margin: 16px 0 14px; }
.capture p { color: var(--color-muted); font-size: 1.06rem; margin-bottom: 28px; }
.capture form { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
.capture .fine { font-family: var(--font-mono); font-size: 11.5px; color: var(--color-muted); margin-top: 18px; }
@@ -381,7 +394,7 @@ h1, h2, h3 { text-wrap: balance; margin: 0; }
/* ============ TIERS PREVIEW ============ */
.tiers-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; margin-bottom: 34px; }
.tiers-head h2 { font-family: var(--font-display); font-weight: 900; font-size: clamp(1.9rem, 3.6vw, 2.7rem); letter-spacing: -0.025em; margin: 12px 0 0; }
.tiers-head h2 { font-family: var(--font-display); font-weight: 900; font-size: clamp(1.9rem, 3.6vw, 2.7rem); letter-spacing: -0.025em; line-height: 1.2; margin: 12px 0 0; }
.tiers-note { font-family: var(--font-mono); font-size: 12px; color: var(--color-muted); max-width: 22rem; text-align: right; line-height: 1.6; }
.tier-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.tier { background: var(--color-card); border: 1px solid var(--color-line); border-radius: 18px; padding: 30px 26px; display: flex; flex-direction: column; transition: box-shadow 0.2s, transform 0.2s; }
@@ -399,7 +412,7 @@ h1, h2, h3 { text-wrap: balance; margin: 0; }
@media (max-width: 820px) { .tier-grid { grid-template-columns: 1fr; } .tiers-note { text-align: left; } }
/* ============ FAQ ============ */
.faq h2 { font-family: var(--font-display); font-weight: 900; font-size: clamp(1.9rem, 3.6vw, 2.7rem); letter-spacing: -0.025em; margin-bottom: 34px; }
.faq h2 { font-family: var(--font-display); font-weight: 900; font-size: clamp(1.9rem, 3.6vw, 2.7rem); letter-spacing: -0.025em; line-height: 1.2; margin-bottom: 34px; }
.qa { border-top: 1px solid var(--color-line); }
.qa details { border-bottom: 1px solid var(--color-line); padding: 6px 0; }
.qa summary { cursor: pointer; list-style: none; padding: 20px 0; display: flex; align-items: center; justify-content: space-between; gap: 20px; font-family: var(--font-display); font-weight: 600; font-size: 1.2rem; letter-spacing: -0.02em; }
@@ -421,3 +434,446 @@ h1, h2, h3 { text-wrap: balance; margin: 0; }
.foot-links a:hover { color: #f7f5f0; }
.colophon { padding-top: 26px; font-family: var(--font-mono); font-size: 11.5px; color: #7a7266; letter-spacing: 0.02em; line-height: 1.8; }
@media (max-width: 600px) { .foot-in { padding: 48px 20px 40px; } }
/* ============ READER DEMO ============ */
/* Layout the landing page does not already have. Reader pages use a wider wrap.
Same tokens, same ~20px cards and 999px pills. Do not restyle the homepage recipe. */
.demo-chip {
display: inline-flex; align-items: center; gap: 8px;
font-family: var(--font-mono); font-size: 11px; font-weight: 500;
letter-spacing: 0.12em; text-transform: uppercase;
color: var(--color-amber);
background: rgba(180, 121, 31, 0.08);
border: 1px solid rgba(180, 121, 31, 0.22);
padding: 5px 12px; border-radius: 999px;
margin-bottom: 22px;
}
.reader-nav .nav-in,
.reader-footer .foot-in,
.wrap.reader-wide {
max-width: min(1520px, calc(100vw - 40px));
}
.crumbs {
padding: 4px 0 18px;
font-size: 13.5px;
}
.crumbs ol {
display: flex; flex-wrap: wrap; align-items: center;
list-style: none; margin: 0; padding: 0;
}
.crumbs li { display: flex; align-items: center; }
.crumbs-sep {
margin: 0 10px; color: var(--color-muted); font-weight: 400;
}
.crumbs a { color: var(--color-pine); font-weight: 600; }
.crumbs a:hover { color: var(--color-pine-deep); }
.crumbs [aria-current="page"] { color: var(--color-ink); font-weight: 600; }
.reader-nav .nav-title {
font-size: 14.5px; font-weight: 600; color: var(--color-ink);
}
.reader-nav .nav-title:hover { color: var(--color-pine); }
.reader-nav .reader-links { gap: 22px; }
.reader-nav .nav-current {
font-size: 14.5px; font-weight: 600; color: var(--color-ink);
max-width: 22ch; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
@media (max-width: 860px) {
.reader-nav .nav-links {
display: flex; align-items: center; gap: 16px; font-size: 13.5px;
}
.reader-nav .nav-cta {
display: inline-flex; font-size: 13px; padding: 8px 14px;
}
.reader-nav .nav-current { display: none; }
.reader-nav .nav-toggle { display: none; }
}
.chapter-page { padding: 48px 0 96px; }
.chapter-shell {
display: grid;
grid-template-columns: 240px minmax(0, 1fr);
gap: 32px 40px;
align-items: start;
}
@media (min-width: 1080px) {
.chapter-shell {
grid-template-columns: 240px minmax(0, 1fr) 280px;
}
}
.chapter-col { min-width: 0; }
.chapter-kicker { margin: 8px 0 14px; }
.chapter-title {
font-family: var(--font-display); font-weight: 900;
font-size: clamp(2.1rem, 4.6vw, 3.4rem);
letter-spacing: -0.028em; line-height: 1.15; margin: 0 0 12px;
max-width: 22ch;
}
.chapter-by {
font-family: var(--font-mono); font-size: 12.5px; color: var(--color-muted);
letter-spacing: 0.04em; margin-bottom: 20px;
}
.chapter-promise {
font-size: 1.12rem; line-height: 1.62; color: var(--color-ink); margin: 0 0 28px;
max-width: 46rem;
}
.chapter-outline {
position: sticky;
top: 68px;
z-index: 30;
align-self: start;
background: var(--color-paper);
border-right: 1px solid var(--color-line);
padding: 16px 20px 28px 0;
max-height: calc(100vh - 68px);
overflow-y: auto;
}
.outline-progress {
font-family: var(--font-mono); font-size: 11.5px; color: var(--color-muted);
letter-spacing: 0.04em; margin: 0 0 14px;
}
.outline-heading {
font-family: var(--font-display); font-weight: 600;
font-size: 1.08rem; letter-spacing: -0.02em; margin: 0 0 16px;
}
.outline-group { margin: 0 0 18px; }
.outline-group:last-child { margin-bottom: 0; }
.outline-group-label { margin: 0 0 8px; }
.outline-group ul { list-style: none; margin: 0; padding: 0; }
.outline-group li { margin: 0; }
.outline-group a {
display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
padding: 5px 0 5px 10px;
border-left: 2px solid transparent;
font-size: 13.5px; line-height: 1.35; color: var(--color-muted);
}
.outline-group a:hover { color: var(--color-ink); }
.outline-group a.is-active {
color: var(--color-pine); border-left-color: var(--color-pine); font-weight: 600;
}
.outline-done {
font-family: var(--font-mono); font-size: 12px; color: var(--color-pine); flex: none;
}
.chapter-rail {
position: sticky;
top: 84px;
align-self: start;
display: none;
}
@media (min-width: 1080px) {
.chapter-rail { display: block; }
}
.chapter-rail .spec { margin: 0 0 14px; }
.rail-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.rail-card {
display: flex; flex-direction: column; gap: 6px;
padding: 16px 18px;
background: var(--color-card);
border: 1px solid var(--color-line);
border-radius: 16px;
box-shadow: var(--sh-sm);
transition: border-color 0.18s, transform 0.14s var(--ease), box-shadow 0.18s;
}
.rail-card:hover {
border-color: var(--color-pine-tint);
transform: translateY(-1px);
box-shadow: var(--sh-md);
}
.rail-card.is-done { border-color: var(--color-pine-tint); background: var(--color-pine-wash); }
.rail-kicker {
font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.1em;
text-transform: uppercase; color: var(--color-pine);
}
.rail-title {
font-family: var(--font-display); font-weight: 600;
font-size: 1.15rem; letter-spacing: -0.02em; line-height: 1.2;
color: var(--color-ink);
}
.rail-meta {
font-family: var(--font-mono); font-size: 12px; color: var(--color-muted);
letter-spacing: 0.02em;
}
.rail-skip {
display: inline-block; margin-top: 16px;
font-family: var(--font-mono); font-size: 12.5px; font-weight: 600;
color: var(--color-pine);
}
.rail-skip:hover { color: var(--color-pine-deep); }
.chapter-outline-mobile {
margin: 0 0 24px;
padding: 10px 16px 12px;
border: 1px solid var(--color-line);
border-radius: 12px;
background: var(--color-card);
}
.chapter-outline-mobile summary {
cursor: pointer; list-style: none;
font-family: var(--font-display); font-weight: 600;
font-size: 1.05rem; letter-spacing: -0.02em;
padding: 6px 0;
}
.chapter-outline-mobile summary::-webkit-details-marker { display: none; }
.chapter-outline-mobile[open] summary { margin-bottom: 10px; }
.chapter-outline-mobile .outline-progress { margin-top: 4px; }
.chapter-kit {
margin: 0 0 28px;
padding: 18px 20px 16px;
background: var(--color-pine-wash);
border: 1px solid var(--color-pine-tint);
border-radius: 16px;
}
.chapter-kit-title {
font-family: var(--font-display); font-weight: 600;
font-size: 1.2rem; letter-spacing: -0.02em;
margin: 0 0 6px;
}
.chapter-kit-lede {
font-size: 14.5px; color: var(--color-muted);
margin: 0 0 16px;
}
.kit-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px 28px;
margin: 0;
}
@media (min-width: 900px) {
.kit-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
.kit-grid { grid-template-columns: 1fr; }
}
.kit-grid dt {
font-family: var(--font-mono); font-size: 11px; font-weight: 500;
letter-spacing: 0.12em; text-transform: uppercase;
color: var(--color-pine); margin: 0 0 6px;
}
.kit-grid dd { margin: 0; font-size: 14.5px; line-height: 1.4; color: var(--color-ink); }
.kit-grid ul { list-style: none; margin: 0; padding: 0; }
.kit-grid li { margin: 0 0 4px; }
.kit-grid li:last-child { margin-bottom: 0; }
.workflow-kit {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
gap: 12px 16px;
margin: 4px 0 8px;
padding: 14px 0 16px;
border-bottom: 1px dashed var(--color-line-2);
}
.workflow-kit dt {
font-family: var(--font-mono); font-size: 11px; font-weight: 500;
letter-spacing: 0.1em; text-transform: uppercase;
color: var(--color-pine); margin: 0 0 4px;
}
.workflow-kit dd {
margin: 0; font-size: 14px; line-height: 1.4; color: var(--color-ink);
}
.rail-kit {
font-size: 12.5px; line-height: 1.35; color: var(--color-muted);
}
.rail-out { color: var(--color-ink); }
.chapter-map {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px 40px;
margin: 0 0 8px;
padding: 18px 0 6px;
border-top: 1px solid var(--color-line);
}
.chapter-map-title { grid-column: 1 / -1; }
@media (max-width: 720px) {
.chapter-map { grid-template-columns: 1fr; }
}
.chapter-map-title {
font-family: var(--font-display); font-weight: 600;
font-size: 1.2rem; letter-spacing: -0.02em;
margin: 0 0 16px;
}
.chapter-map-block { margin: 0 0 16px; }
.chapter-map-block .spec { margin: 0 0 8px; }
.chapter-map-block ul { margin: 0; padding: 0 0 0 1.1em; }
.chapter-map-block li { margin: 0 0 6px; }
.chapter-map-block a { color: var(--color-pine); font-weight: 600; }
.chapter-map-block a:hover { color: var(--color-pine-deep); }
.skip-row {
display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
margin: 0 0 48px; padding: 16px 0;
border-top: 1px dashed var(--color-line-2);
border-bottom: 1px dashed var(--color-line-2);
}
.skip-label {
font-family: var(--font-mono); font-size: 11.5px; font-weight: 500;
letter-spacing: 0.12em; text-transform: uppercase; color: var(--color-pine);
margin-right: 4px;
}
.skip-chip {
display: inline-flex; align-items: baseline; gap: 8px;
font-family: var(--font-mono); font-size: 12.5px; color: var(--color-pine);
background: var(--color-pine-wash); border: 1px solid var(--color-pine-tint);
padding: 7px 13px; border-radius: 999px;
transition: background 0.18s, transform 0.14s var(--ease);
}
.skip-chip:hover { background: var(--color-pine-tint); transform: translateY(-1px); }
.skip-chip:focus-visible { outline: 2px solid var(--color-pine); outline-offset: 3px; }
.skip-chip-job {
font-family: var(--font-body); font-size: 13px; font-weight: 600;
color: var(--color-ink); letter-spacing: 0; text-transform: none;
}
.essay,
.recipe-nested,
.end-matter,
.end-sources,
.recipe-nested .row {
scroll-margin-top: 88px;
}
.essay { margin: 0 0 36px; max-width: 46rem; }
.essay h2 {
font-family: var(--font-display); font-weight: 600;
font-size: 1.45rem; letter-spacing: -0.02em; line-height: 1.2;
margin: 0 0 12px;
}
.essay p { color: var(--color-ink); margin: 0 0 14px; }
.essay p:last-child { margin-bottom: 0; }
.workflow-kicker { margin: 8px 0 10px; }
.recipe-nested {
margin: 0 0 52px;
}
.recipe-nested .step-copy { min-width: 0; flex: 1; }
.recipe-nested .step-copy .term { margin-top: 12px; }
.recipe-nested h4.k { margin: 0; font-weight: 500; }
.recipe-nested .term {
overflow-x: auto;
overflow-y: hidden;
}
.recipe-nested .term pre { overflow-x: auto; }
.recipe-jump {
display: flex; flex-wrap: wrap; gap: 8px 16px;
margin: 0 0 8px; padding: 0 0 16px;
border-bottom: 1px dashed var(--color-line-2);
font-size: 13.5px;
}
.recipe-jump a { color: var(--color-pine); font-weight: 600; }
.recipe-jump a:hover { color: var(--color-pine-deep); }
.recipe-jump a:focus-visible { outline: 2px solid var(--color-pine); outline-offset: 2px; }
.plain-list { margin: 0; padding: 0 0 0 1.1em; }
.plain-list li { margin: 0 0 6px; }
.plain-list li:last-child { margin-bottom: 0; }
.evidence-p { margin: 0 0 10px; }
.evidence-p:last-child { margin-bottom: 0; }
.sub-line { color: var(--color-muted); font-size: 14.5px; margin: 8px 0 12px; }
.inline-sample {
font-family: var(--font-mono); font-size: 13px; color: var(--color-pine);
border-bottom: 1px solid var(--color-pine-tint);
}
.inline-sample:hover { color: var(--color-pine-deep); }
.tryit-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
.tryit-actions .btn { font-size: 14px; padding: 11px 18px; }
.tryit-done { gap: 8px; }
.recipe-record {
display: flex; flex-direction: column; gap: 6px;
font-size: 14.5px; color: var(--color-muted);
}
.recipe-record a { color: var(--color-pine); font-weight: 600; }
.recipe-record a:hover { color: var(--color-pine-deep); }
.end-matter {
margin-top: 56px; padding-top: 28px;
border-top: 1px solid var(--color-line);
}
.end-sources { margin-top: 32px; }
.end-matter h2,
.end-sources h2 {
font-family: var(--font-display); font-weight: 600;
font-size: 1.35rem; letter-spacing: -0.02em; margin: 0 0 12px;
}
.end-matter h2 + .further-list { margin-bottom: 8px; }
.further-list { margin: 0 0 8px; padding: 0 0 0 1.1em; color: var(--color-ink); }
.further-list li { margin: 0 0 8px; }
.further-list a { color: var(--color-pine); font-weight: 600; }
.chapter-updated {
font-family: var(--font-mono); font-size: 12px; color: var(--color-muted);
letter-spacing: 0.04em; margin-top: 18px;
}
.library-title {
font-family: var(--font-display); font-weight: 900;
font-size: clamp(1.9rem, 4vw, 3rem); letter-spacing: -0.025em;
line-height: 1.15; margin: 14px 0 16px;
white-space: nowrap;
}
.library-lede { color: var(--color-muted); max-width: 38rem; margin-bottom: 34px; }
.toc .toc-soon {
display: grid; grid-template-columns: 52px 1fr auto auto;
align-items: center; gap: 20px; padding: 22px 8px;
border-bottom: 1px solid var(--color-line);
color: var(--color-muted);
}
.toc .soon {
font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.12em;
text-transform: uppercase; color: var(--color-muted);
background: var(--color-card); border: 1px solid var(--color-line);
padding: 4px 10px; border-radius: 999px; white-space: nowrap;
}
.reader-library .toc a {
grid-template-columns: 52px 1fr auto auto auto;
}
.toc-count {
font-family: var(--font-mono); font-size: 11.5px; font-weight: 500;
letter-spacing: 0.08em; text-transform: uppercase;
color: var(--color-pine); white-space: nowrap;
}
@media (max-width: 720px) {
.toc .toc-soon .desc { display: none; }
.toc .toc-soon { grid-template-columns: 40px 1fr auto; }
.reader-library .toc a { grid-template-columns: 40px 1fr auto auto; }
}
.recipe-focus-page { padding: 40px 0 96px; }
.recipe-focus-page .demo-chip { margin-bottom: 12px; }
.recipe-focus-page .recipe { max-width: none; }
.focus-back {
font-family: var(--font-mono); font-size: 13px; color: var(--color-muted);
margin: 0 0 28px;
}
.focus-back a { color: var(--color-pine); font-weight: 600; }
@media (max-width: 959px) {
.chapter-shell { grid-template-columns: 1fr; gap: 0; }
.chapter-outline { display: none; }
.chapter-rail { display: none; }
}
@media (min-width: 960px) {
.chapter-outline-mobile { display: none; }
}
@media print {
.reader-nav, .chapter-outline, .chapter-outline-mobile, .chapter-rail, .reader-footer, .skip-row, .tryit-actions, .demo-chip, .recipe-jump {
display: none !important;
}
.recipe-nested { break-inside: avoid; box-shadow: none; }
}
+224
View File
@@ -0,0 +1,224 @@
---
status: draft-for-review
type: chapter-template
edition: 2026
vertical: # real-estate | financial-advisors | fractional-c-suite | higher-ed | communities | technology
title: ""
authors: []
recipe_ids: [XX-01, XX-02]
last_updated: 2026-08-31
---
# Chapter structure (for review)
This is the blank chapter, matching PRD §5.4 (locked 2026-08-31). Review the shape before anyone writes a real vertical.
**How to use it.** Copy this file to `workflows/[vertical-slug].md` (example: `workflows/real-estate.md`). Replace `XX` with the vertical prefix. Leave this file as the blank.
**What a chapter is.** A substantial essay for one vertical. Full workflows sit inside the argument, at the point they earn, not in an appendix and not as a stack of cards.
**What a workflow is.** The unit of practice. Read it, run the Try-it (~15 min), share the result. That Try-it is what counts as activation.
**Rules that do not move.**
- Skip-to-Try-it at the top. Activation does not wait for the essay.
- Safeguards before Method. Data handling is read before anyone pastes a client list.
- Method shows real tool output, not a description of it.
- Nested recipes stay open. Do not hide Method behind "click to reveal."
- Every recipe has a stable ID and a heading it can link to.
- Every recipe names its kit (who runs it, tools, files, model, time, cost, artifact). The chapter page shows the union at the top and the kit on each nested recipe.
- No chatbot on the page. No crypto or Web3 language.
- PDF must match this stack: essay + in-place recipes.
**Vertical prefixes**
| Vertical | Slug | ID prefix |
|:--|:--|:--|
| Real Estate | `real-estate` | `RE` |
| Financial Advisors | `financial-advisors` | `FA` |
| Fractional C-Suite | `fractional-c-suite` | `CS` |
| Higher Ed | `higher-ed` | `HE` |
| Communities | `communities` | `CM` |
| Technology | `technology` | `TE` |
Fill every `[bracket]`. Two nested recipes are shown so the essay-wraps-workflow pattern is obvious. Add more at the points in the argument they belong. Delete the unused slot rather than leaving a hollow block.
---
# [Chapter title]
[Vertical] · 2026 edition · [Author names]
## What this chapter is for
[One short promise. The job this vertical's reader is trying to get done this week, and what they will be able to run by the end of the chapter.]
**Skip to a Try-it:** [XX-01](#xx-01) · [XX-02](#xx-02)
## What you need
The chapter page shows this before the essay. Union of the nested workflows. Named tools, sample files, Try-it time, sample-run cost. No live client data.
- Tools: [named]
- Files: [named samples we ship]
- Model: [named, or "the model you already use"]
- Time: [each Try-it]
- Cost: [sample-run total, or "unknown"]
## [Essay: the stakes]
[Why this work is hard here. Specific to the vertical, not a generic AI preamble. Name the actual failure: a listing that stalls, a client file that leaks, a committee that will not move.]
## [Essay: constraints]
[What you cannot ignore in this vertical. Tools people already use. Compliance, clients, time. What "done" looks like for them.]
## [Essay: how we work here]
[The practice this chapter argues for. Then the first workflow, at the moment the argument needs proof.]
---
<a id="xx-01"></a>
### [Job title. This is the workflow title, written as the job.]
**XX-01** · v0.1 · ~[N] min · ~$[cost or "free with tools you already have"]
#### Kit
Shown at the top of the nested recipe. Inventory, not instructions. Setup below still explains how to use these.
- You run: [role]
- Tools: [named tools, versions if it matters]
- Files: [sample files we ship]
- Model: [named, or "the model you already use"]
- Time: ~[N] min
- Cost: [amount or "free with tools you already have"]
- You produce: [artifact]
#### Problem
[The real task. One job, not a category.]
#### Actors
- Who runs it: [role]
- Who is affected: [client, student, team]
- What the model is allowed to do: [draft / classify / retrieve]. What a human must still do: [send / approve / file]
#### Setup
- Tools: [named tools, versions if it matters]
- Sample files: [what we ship with this recipe, or "use the anonymized packet below"]
- Cost: [model/tool cost if known. If unknown, say so.]
#### Safeguards
Read this before the steps.
- Data handling: [what never goes into the prompt. What is ok if stripped.]
- Human oversight: [the checkpoint before anything leaves the building]
- Failure modes: [how this goes wrong in this vertical]
- Escalation: [who you call, and when you stop]
#### Method
Ordered steps. Paste the actual tool output inside the step that produced it. A screenshot or a quoted block beats a paraphrase.
1. [Step]
```
[real output]
```
2. [Step]
3. [Step]
#### Evidence
[What "it worked" looks like. An artifact, a number, a before/after. Not "the user felt more confident."]
#### Try it (~15 min)
- Sample data: [what they use so they do not need a live client]
- What to produce: [the artifact]
- Done when: [a check they can mark. Completing this is activation.]
#### Share the result
[What they post: the outcome, not the workflow text. Point at the community template when it exists. Events, not content.]
**Author:** [name] · **Sources:** [links or citations] · **Last updated:** [date]
---
## [Essay continues]
[The argument picks back up. What the first recipe proved, what it did not. Then the next workflow, when the next claim needs proof.]
---
<a id="xx-02"></a>
### [Second job title]
**XX-02** · v0.1 · ~[N] min · ~$[cost]
#### Kit
Shown at the top of the nested recipe. Inventory, not instructions. Setup below still explains how to use these.
- You run: [role]
- Tools: [named tools, versions if it matters]
- Files: [sample files we ship]
- Model: [named, or "the model you already use"]
- Time: ~[N] min
- Cost: [amount or "free with tools you already have"]
- You produce: [artifact]
#### Problem
[ ]
#### Actors
[ ]
#### Setup
[ ]
#### Safeguards
[ ]
#### Method
1. [ ]
2. [ ]
#### Evidence
[ ]
#### Try it (~15 min)
[ ]
#### Share the result
[ ]
**Author:** [name] · **Sources:** [ ] · **Last updated:** [date]
---
## Further workflows in this vertical
- [XX-01](#xx-01) — [job title]
- [XX-02](#xx-02) — [job title]
- [Later IDs, once assigned]
## Sources
[Chapter-level sources. Recipe-level citations stay on the recipe.]
**Last updated:** 2026-08-31