From c64afb43f5c6071980831ad7544add9159125ae2 Mon Sep 17 00:00:00 2001 From: "Rafael T. Ballestiero" Date: Sun, 14 Jun 2026 13:08:20 +0200 Subject: [PATCH 01/13] docs(idea): equanimitech ritual app (alarm-triggered wake-up) --- ...tech-ritual-app-alarm-triggered-wake-up.md | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 docs/ideas/2026-06-14-equanimitech-ritual-app-alarm-triggered-wake-up.md diff --git a/docs/ideas/2026-06-14-equanimitech-ritual-app-alarm-triggered-wake-up.md b/docs/ideas/2026-06-14-equanimitech-ritual-app-alarm-triggered-wake-up.md new file mode 100644 index 0000000..eae7358 --- /dev/null +++ b/docs/ideas/2026-06-14-equanimitech-ritual-app-alarm-triggered-wake-up.md @@ -0,0 +1,21 @@ +--- +$signature: + $type: tech.equanimi.secretariat.signature + signer: did:key:z6MkpcX3mHt44yNEDPDWJic8ocJdagzERxx5u2Qh1dWcVRVN + signerRole: agent + docHash: sha256:1529782c2d40f06353014034e0c8e5774703cbb782a2716dd7aaf12d02c218b1 + signedAt: 2026-06-14T11:08:20.212327Z + signature: ed25519:U708eN8QlsOSB0694A6+xR5k1pXfFmyK3Pv6OqHCzo79PksgDrTpnb6SVszeqAqwXUtCMV1p0gGDJNpgwTgvDg== +type: idea +--- +# equanimitech ritual app (alarm-triggered wake-up) + +Captured 2026-06-07. + +Seed: iOS Shortcuts Personal Automation has an ALARM trigger (when wake alarm stopped, iOS 16+) + time-of-day trigger. A shortcut can surface the wake-up protocol hands-free on waking: show/speak the 5 steps (pills→sun→hydrate→Vipassana 1-3→movement), start a meditation timer, log to Things/Health — staying off-screen (sun not screen). + +Productize: the consumer face of the whole personal-OS system built tonight — an equanimitech wake-up / ritual app. Same family as keel (focus gate), sign-off (disconnect contract), vice-block (drogues), and the zoom-as-granularity / generative-UI idea. Thesis: calm tech that gets out of the way (fade-by-design, sovereignty, embodied). Likely Expo / React Native (have vercel-react-native + expo skills). MVP = alarm→ritual checklist + meditation timer; later = the full day loop (wake→focus→sign-off). + +Start cheap: an iOS Shortcut prototype (no app) to validate the alarm→ritual flow before building. Related ideas: zoom-as-granularity dial; drogues blocker (already in keel product). Equanimitech-analyzer the design before building. + +Captured via /triage on 2026-06-14 from the Things inbox. \ No newline at end of file From b113a0979a1f3530f29891c2bf45bcd338768a0e Mon Sep 17 00:00:00 2001 From: "Rafael T. Ballestiero" Date: Sun, 14 Jun 2026 13:08:28 +0200 Subject: [PATCH 02/13] docs(idea): try out paca for equanimitech (install script in notes) --- ...-for-equanimitech-install-script-in-notes.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 docs/ideas/2026-06-14-try-out-paca-for-equanimitech-install-script-in-notes.md diff --git a/docs/ideas/2026-06-14-try-out-paca-for-equanimitech-install-script-in-notes.md b/docs/ideas/2026-06-14-try-out-paca-for-equanimitech-install-script-in-notes.md new file mode 100644 index 0000000..1b2fadb --- /dev/null +++ b/docs/ideas/2026-06-14-try-out-paca-for-equanimitech-install-script-in-notes.md @@ -0,0 +1,17 @@ +--- +$signature: + $type: tech.equanimi.secretariat.signature + signer: did:key:z6MkpcX3mHt44yNEDPDWJic8ocJdagzERxx5u2Qh1dWcVRVN + signerRole: agent + docHash: sha256:4bea17ec02348610e7fe6fdd2e9aa80a06dfdd30f991ad6764d8016713fe19b3 + signedAt: 2026-06-14T11:08:28.191999Z + signature: ed25519:SBswZeys3nC+gDzBPYyWjojLOJJCThw2IemjI+Ceo29Hep9XyBcYEjzri0uLa26kGfdl7IALISdvaRxyltezAA== +type: idea +--- +# try out paca for equanimitech (install script in notes) + +Let's try out paca for equanimitech: + +`curl -fsSL https://github.com/Paca-AI/paca/releases/latest/download/install.sh | bash` + +Captured via /triage on 2026-06-14 from the Things inbox. \ No newline at end of file From af9d526aa90ddcc8f40bc707f6c89aee1b529017 Mon Sep 17 00:00:00 2001 From: "Rafael T. Ballestiero" Date: Sun, 14 Jun 2026 13:08:36 +0200 Subject: [PATCH 03/13] =?UTF-8?q?docs(idea):=20versowriter.app=20=E2=80=94?= =?UTF-8?q?=20equanimitech=20pricing/comms=20inspiration=20(one-time-purch?= =?UTF-8?q?ase=20model)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...quanimitech-pricing-comms-inspiration-one-t.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 docs/ideas/2026-06-14-versowriter-app-equanimitech-pricing-comms-inspiration-one-t.md diff --git a/docs/ideas/2026-06-14-versowriter-app-equanimitech-pricing-comms-inspiration-one-t.md b/docs/ideas/2026-06-14-versowriter-app-equanimitech-pricing-comms-inspiration-one-t.md new file mode 100644 index 0000000..2776f5c --- /dev/null +++ b/docs/ideas/2026-06-14-versowriter-app-equanimitech-pricing-comms-inspiration-one-t.md @@ -0,0 +1,15 @@ +--- +$signature: + $type: tech.equanimi.secretariat.signature + signer: did:key:z6MkpcX3mHt44yNEDPDWJic8ocJdagzERxx5u2Qh1dWcVRVN + signerRole: agent + docHash: sha256:9d39f83bccf98254df52960b78e20c3471e75477f78223e0ce18bf2dd02fab9e + signedAt: 2026-06-14T11:08:36.757783Z + signature: ed25519:QB/VS6sAYEksycu4LUR81bOfkaxeF1LZr5BvduVnfv1d0OpTZzMficBqM47k3i7DT7E4EoMJdrMKjrygxI0xDw== +type: idea +--- +# versowriter.app — equanimitech pricing/comms inspiration (one-time-purchase model) + +An example of equanimitech (and business model — one time purchase): https://www.versowriter.app/ — want to find inspiration on pricing / design etc. + +Captured via /triage on 2026-06-14 from the Things inbox. \ No newline at end of file From b0461e374155cf60427494a4adcf3703dc9c370b Mon Sep 17 00:00:00 2001 From: "Rafael T. Ballestiero" Date: Wed, 17 Jun 2026 18:41:41 +0200 Subject: [PATCH 04/13] docs(notes): garden design spec and Phase 1 implementation plan Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/2026-06-17-notes-blog-design.md | 209 +++++++++++ docs/2026-06-17-notes-garden-plan.md | 513 +++++++++++++++++++++++++++ 2 files changed, 722 insertions(+) create mode 100644 docs/2026-06-17-notes-blog-design.md create mode 100644 docs/2026-06-17-notes-garden-plan.md diff --git a/docs/2026-06-17-notes-blog-design.md b/docs/2026-06-17-notes-blog-design.md new file mode 100644 index 0000000..23fd729 --- /dev/null +++ b/docs/2026-06-17-notes-blog-design.md @@ -0,0 +1,209 @@ +# Notes: an evergreen stacked-notes garden for equanimi.tech + +**Date:** 2026-06-17 +**Status:** design approved, pending spec review → implementation plan + +## Problem + +equanimitech's writing is scattered. Essays live on Substack (`rafaba.substack.com`, +"Mindful Cyborg" era), and ~2,000+ lines of newer, on-brand prose sit unread across +the monorepo (`torchbearer/docs`, `keel/docs`, `penceive/docs`, `site/docs`, the +landing page itself). Substack is not equanimitech: someone else's chrome, no +sovereignty over the reading surface. The repo prose has no home at all. + +We want a reading surface on `equanimi.tech` that (a) gathers this corpus, (b) +embodies the framework rather than just describing it — specifically principle #5, +**Attentional Granularity** (depth on demand) — and (c) keeps RSS as the subscribe +path so we never self-host email. + +Reference look/interaction: Andy Matuschak's notes (evergreen, interlinked, +**stacked sliding columns**) over lutr.dev's chronological feed. The garden suits an +interlinked conceptual corpus; a chronological blog does not. + +## Solution + +An evergreen **notes garden** built entirely inside the existing `/site` Astro +project using native Content Collections. Atomic, interlinked notes — not dated +essays. Granularity is expressed as **per-section expansion** (native +`
`). Internal links open as **stacked columns** (Matuschak-style), added as +a progressive-enhancement layer so the garden is fully usable without it. + +### Decisions (locked) + +- **Paradigm:** evergreen garden (interlinked atomic notes), not a chronological blog. +- **Newsletter:** stays on Substack as the email channel. The garden is the canonical + home and links back. We do not self-host email. RSS is the on-site subscribe path. +- **Name / route:** "Notes" at `/notes`, individual notes at `/notes/`. +- **Granularity = per-section expansion** via native `
`/``. + Zero JS, accessible, no-CSS-degradable. Replaces the earlier document-level zoom. +- **Format:** Markdown. `
` is authored as raw HTML in markdown. **MDX + deferred** — adopt only if collapsible sections get repetitive enough to want a + `` component. Neither images nor zoom need MDX. +- **Interlinking:** plain markdown links to `/notes/` for v1. Wikilinks + (`[[slug]]`, needs one remark dep) are the likely first upgrade if linking is tedious. +- **Stacking:** Matuschak-style columns, built in **Phase 2** as progressive + enhancement (vanilla JS, ~120 lines). Degrades to normal navigation. +- **Orbit / spaced repetition:** deferred. Embedding hosted Orbit would fail + principle #1 (Local-First Ownership); a local-first SR build is its own project and + overlaps Penceive. Not v1, possibly never on the site. +- **Content lives in `site/src/content/notes/`** — site/ deploys standalone; sibling + repos are unavailable at build time. Publishing = curating a copy into the site. + +## Content model + +### Collection — `src/content/notes/*.md` + +`src/content/config.ts` defines the `notes` collection (Zod schema, build-time validated): + +| field | type | required | notes | +|---|---|---|---| +| `title` | string | yes | the note's name | +| `summary` | string | yes | one-line handle; used in index, RSS, OG, and as link preview | +| `date` | date | yes | for RSS ordering + a quiet "last tended" stamp; de-emphasized | +| `tags` | string[] | no | thematic clusters (`#framework`, `#sovereignty`, `#attention`) | +| `status` | enum `evergreen`/`budding`/`seedling` | no | garden maturity; default `budding` | +| `related` | string[] (slugs) | no | explicit cross-links surfaced at note foot | +| `hero` | image | no | optional featured image (Astro image) | +| `draft` | boolean | no | default false; excluded from index + RSS | + +Body = markdown. May contain `
` for per-section expansion and plain links to +other notes for interlinking. + +## Components (Phase 1 — no JS) + +Each unit has one purpose, inherits existing styles, is independently checkable. + +### 1. Shared shell — `src/layouts/Base.astro` + +`index.astro` currently inlines head + masthead + footer. Extract a `Base.astro` +(head + masthead + footer + ``) and refactor `index.astro` onto it, so the +landing page, `/notes`, and note pages share one shell. Targeted in-scope cleanup — +all current markup/classes preserved, no redesign. + +### 2. Collection config — `src/content/config.ts` + +The `notes` schema above. + +### 3. Note page — `src/layouts/Note.astro` + `src/pages/notes/[...slug].astro` + +`[...slug].astro` does `getCollection('notes')` → `getStaticPaths`, renders body via +`Note.astro`. Layout: centered ~660px reading column, eyebrow (read-time · +`status` · tags), `

` title, optional hero, prose (inherits `global.css`), a +"related notes" list at the foot (from `related` + back-links where cheap). Read-time += full-content word-count / 200, computed at build. + +### 4. Per-section expansion + +Collapsible sections are native `
handle…full…
` +authored in markdown. Styled in `global.css` to match the design system (the summary +is the coarse view; open reveals depth). No JS; full content stays in the DOM for +crawlers and the no-CSS fallback. + +### 5. Index + entry — `src/pages/notes/index.astro` + a "Start here" note + +`/notes` lists notes (title · summary · tags · status), grouped by cluster or listed +newest-first. One note is designated the **"Start here"** entry (e.g. the thesis), the +garden's front door. No pagination yet (revisit at ~25 notes). + +### 6. RSS — `src/pages/rss.xml.js` + +`@astrojs/rss` (the one new dependency). Emits non-draft notes ordered by date at +`/rss.xml`; autodiscovery `` in `Base.astro` head. + +### 7. Navigation edits — in `Base.astro` + +Masthead nav gains "Notes" (`/notes`). Footer gains an RSS link and a "Notes" entry. +Existing "Newsletter → Substack" links stay. + +## Components (Phase 2 — stacking, progressive enhancement) + +### 8. Stacked columns — `src/scripts/stack.js` + +Vanilla JS, ~120 lines. Intercepts clicks on internal `/notes/` links → fetches +the target note's rendered HTML → appends it as a sticky column to the right → pushes +`?stacked=a,b,c` URL state (History API; back/forward works). On load with `?stacked=`, +hydrates the columns. Disabled below a viewport breakpoint and when JS is off — links +just navigate. Changes zero content; if it proves fiddly, Phase 1 stands alone. + +This is the site's **first client-side JS** (config currently states "no JS framework, +no client-side routing"). It is progressive enhancement, not a framework — done with +eyes open. + +## Architecture / data flow + +``` +src/content/notes/*.md ──getCollection('notes')──> /notes (index, clustered) + ├──getStaticPaths────────────> /notes/ (static page) + └──@astrojs/rss──────────────> /rss.xml +Phase 2: internal-link click ──fetch /notes/──> append column + ?stacked= URL +``` + +All static, built at `astro build`, deployed to Vercel as today. + +## Error handling + +- Draft / future-dated notes excluded from index + RSS via filter. +- Malformed frontmatter fails the build (Zod) — caught at build, never runtime. +- Missing hero: layout renders without it. +- Phase 2: a fetch failure or no-JS falls back to plain navigation (the note's own page). + +## Testing + +Static site; verification is build + visual check. + +- `astro build` succeeds with all seed notes (schema validation green). +- `/notes` lists the seed set; every note links to a working page. +- `
` sections expand/collapse; full text present with CSS disabled. +- `/rss.xml` is well-formed with the expected item count. +- Light/dark render; reading column centered ~660px; masthead/footer match landing. +- Phase 2: stacking opens columns + updates URL; back/forward restores; narrow + viewport and JS-off both fall back to navigation. + +## Seed content (launch without writing anything new) + +Primary seed = the internal corpus (curated copies into `src/content/notes/`). +Opening cluster, interlinked: + +| note (working title) | source | status | +|---|---|---| +| **Start here / The thesis** | `site/src/pages/index.astro` (thesis + framework) | evergreen | +| **The Boat** | `torchbearer/docs/2026-05-31-the-boat.md` | evergreen (stamped) | +| **Adaptive Granularity** | `torchbearer/docs/2026-05-28-adaptive-granularity-seven-granularities.md` | evergreen — *the note the garden embodies* | +| **Glance / Ask / Click** | `torchbearer/docs/2026-06-07-glance-ask-click.md` | evergreen (stamped) | +| **UI navigates, MCP does the work** | `torchbearer/docs/2026-05-17-ui-navigates-mcp-does-the-work.md` | budding | +| **Personal OS** | `keel/docs/2026-06-08-personal-os-article-draft.md` | budding | +| **Penceive as infrastructure (the Wake)** | `penceive/docs/ideas/2026-05-31-penceive-as-infrastructure.md` | evergreen (stamped) | +| **Stamped by humans** | `torchbearer/docs/2026-05-26-stamped-by-humans-drafting-brief.md` | seedling (brief → essay) | +| **Deferred extracts** (reference layer) | `site/docs/2026-05-14-deferred-extracts…md` | seedling | + +Natural interlinks already present: Boat ↔ each project · Adaptive Granularity ↔ +this garden's zoom · Glance/Ask/Click ↔ UI-navigates-MCP · Stamped-by-humans ↔ +Tom Bedor reference ↔ Secretariat. + +**Backlog (not blocker):** the nine-principle write-ups (only a roadmap + +deferred-extracts reference exist). Publish on a cadence; the garden grows. + +**Substack archive:** the 6 Mindful Cyborg essays are an *optional secondary* import, +later — they are chronological-essay shaped and less central than the internal corpus. + +## Out of scope (YAGNI — add when needed) + +Email capture/sending · spaced repetition / Orbit · wikilink syntax · MDX components · +tag/cluster archive pages · pagination · search · comments · automated sync from +source repos · porting the 6 Substack essays. + +## Build sequence + +**Phase 1 — the garden (no JS):** +1. Extract `Base.astro`; refactor `index.astro` onto it. +2. Add `src/content/config.ts` with the `notes` schema. +3. Build `Note.astro` + `[...slug].astro`; style `
`; add one seed note; verify build. +4. Build `/notes/index.astro` (clustered) + designate "Start here". +5. Add `@astrojs/rss` + `rss.xml.js`; verify feed. +6. Wire nav/footer links + RSS autodiscovery in `Base.astro`. +7. Curate the opening seed notes from the corpus (frontmatter + light edit + interlinks); + final build + visual check. + +**Phase 2 — stacking (progressive enhancement):** +8. Build `stack.js`: link interception, column append, `?stacked=` URL state, hydrate-on-load. +9. Responsive + no-JS fallback; verify back/forward and degradation. diff --git a/docs/2026-06-17-notes-garden-plan.md b/docs/2026-06-17-notes-garden-plan.md new file mode 100644 index 0000000..d6e9600 --- /dev/null +++ b/docs/2026-06-17-notes-garden-plan.md @@ -0,0 +1,513 @@ +# Notes Garden (Phase 1) Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Ship an evergreen, interlinked notes garden at `equanimi.tech/notes` with per-section expansion and RSS, seeded from the existing repo prose, with zero client-side JS. + +**Architecture:** Build inside the existing Astro static site. A `notes` Content Collection holds atomic markdown notes; one note layout renders them in a centered reading column with native `
` for depth-on-demand; an index page lists them; an `@astrojs/rss` endpoint emits the feed. A shared `Base.astro` shell is extracted from `index.astro` so the landing page and the garden wear the same `≃` chrome. Stacking columns are deliberately out of this phase. + +**Tech Stack:** Astro 4 (static), Astro Content Collections (Zod), `@astrojs/rss`, hand-rolled CSS in `global.css`, pnpm. No JS framework. No test runner. + +## Global Constraints + +- Output is `static`; `inlineStylesheets: "always"`; deployed to Vercel. (`astro.config.mjs`) +- `site: "https://equanimi.tech"`. Canonical/OG URLs use this origin. +- No JS framework, no client-side routing in Phase 1. (`astro.config.mjs` comment is load-bearing.) +- Preserve all existing markup, class names, and the `≃` design system when refactoring. No redesign. +- Package manager is **pnpm** (never npm/yarn). +- **No em dashes** in any copy or commit message (use a colon, comma, or period). +- Verification per task = `pnpm build` succeeds (Zod schema validates) + a targeted `dist/` check. There is no unit-test framework and we are not adding one. +- Prefer `for...of` over `forEach` in any `.astro` script blocks. + +--- + +### Task 1: Extract `Base.astro` shared shell + +**Files:** +- Create: `src/layouts/Base.astro` +- Modify: `src/pages/index.astro` (replace inlined head/masthead/footer with ``) + +**Interfaces:** +- Produces: `Base.astro` accepting props `{ title: string; description: string; path: string; tagline?: string }`. Renders ``, `` (meta/OG/canonical/favicon/font preload built from props, `og:url` and canonical = `https://equanimi.tech` + `path`), `
` (brand glyph + wordmark + nav; renders `

` only if `tagline` provided), a `` for page body, and the existing `

`. Nav links: GitHub, Newsletter (Substack), Contact. + +- [ ] **Step 1: Create `Base.astro`** by moving the head, masthead, and footer markup verbatim out of `index.astro`. Parameterize the page-specific bits with props. + +```astro +--- +import "../styles/global.css"; +interface Props { + title: string; + description: string; + path: string; // leading-slash path, e.g. "/" or "/notes" + tagline?: string; // masthead tagline; homepage only +} +const { title, description, path, tagline } = Astro.props; +const url = `https://equanimi.tech${path}`; +--- + + + + + + {title} + + + + + + + + + + + + + + + + +
+ + + equanimi.tech + + {tagline &&

{tagline}

} + +
+ +
+ +
+ + +``` + +- [ ] **Step 2: Refactor `index.astro`** to use `Base`. Remove the now-duplicated head/masthead/footer; keep all `
`/hero/section content as the slotted body. The file's frontmatter becomes: + +```astro +--- +import Base from "../layouts/Base.astro"; +import Section from "../components/Section.astro"; +import Project from "../components/Project.astro"; +const title = "equanimi.tech"; +const description = "An open studio building technology that preserves attention and cultivates equanimity."; +--- + +
+

We, the users, are being used.

+
+
+ {/* ... existing Section/Project content unchanged ... */} +
+ +``` + +Keep every existing `
`, ``, and prose block inside `
` exactly as-is. + +- [ ] **Step 3: Build and verify homepage parity** + +Run: `pnpm build` +Expected: build succeeds. Then `grep -c 'class="masthead"' dist/index.html` returns `1`, and `grep -c 'We, the users, are being used.' dist/index.html` returns `1`. + +- [ ] **Step 4: Visual parity check** + +Run: `pnpm preview` and open `/`. Confirm masthead, hero, all sections, and footer render identically to before (the only intended change: nav now has a "Notes" link, footer "Read" column). + +- [ ] **Step 5: Commit** + +```bash +git add src/layouts/Base.astro src/pages/index.astro +git commit -m "refactor(site): extract Base.astro shell shared by landing page and garden" +``` + +--- + +### Task 2: Define the `notes` content collection + +**Files:** +- Create: `src/content/config.ts` + +**Interfaces:** +- Produces: a `notes` collection (`type: 'content'`) with schema `{ title: string; summary: string; date: Date; tags?: string[]; status?: 'evergreen'|'budding'|'seedling'; related?: string[]; hero?: image; draft?: boolean }`. `status` defaults to `'budding'`, `draft` defaults to `false`. Later tasks import via `getCollection('notes')`. + +- [ ] **Step 1: Write the collection config** + +```ts +import { defineCollection, z } from "astro:content"; + +const notes = defineCollection({ + type: "content", + schema: ({ image }) => + z.object({ + title: z.string(), + summary: z.string(), + date: z.coerce.date(), + tags: z.array(z.string()).optional(), + status: z.enum(["evergreen", "budding", "seedling"]).default("budding"), + related: z.array(z.string()).optional(), + hero: image().optional(), + draft: z.boolean().default(false), + }), +}); + +export const collections = { notes }; +``` + +- [ ] **Step 2: Add a throwaway note so the collection is non-empty for the build** + +Create `src/content/notes/_smoke.md`: + +```md +--- +title: Smoke note +summary: Temporary note to validate the collection builds. +date: 2026-06-17 +status: seedling +draft: true +--- + +Temporary. Deleted in Task 7. +``` + +- [ ] **Step 3: Build to verify schema validates** + +Run: `pnpm build` +Expected: build succeeds with no Zod errors. (Draft note produces no page yet; that wiring is Task 3.) + +- [ ] **Step 4: Commit** + +```bash +git add src/content/config.ts src/content/notes/_smoke.md +git commit -m "feat(notes): define notes content collection schema" +``` + +--- + +### Task 3: Note layout + dynamic route + `
` styling + +**Files:** +- Create: `src/layouts/Note.astro` +- Create: `src/pages/notes/[...slug].astro` +- Modify: `src/styles/global.css` (append `.note`, `.note__eyebrow`, `details`/`summary` rules) + +**Interfaces:** +- Consumes: `Base.astro` (Task 1), `getCollection('notes')` (Task 2). +- Produces: static pages at `/notes/` for every non-draft note. `Note.astro` props: `{ note: CollectionEntry<'notes'>; readingTime: number }`. + +- [ ] **Step 1: Write `Note.astro`** + +```astro +--- +import Base from "./Base.astro"; +import type { CollectionEntry } from "astro:content"; +interface Props { note: CollectionEntry<"notes">; readingTime: number; } +const { note, readingTime } = Astro.props; +const { Content } = await note.render(); +const { title, summary, status, tags = [] } = note.data; +--- + +
+ ← Notes +

{readingTime} min read · {status}{tags.length ? ` · ${tags.map((t) => `#${t}`).join(" ")}` : ""}

+

{title}

+
+ +
+
+ +``` + +- [ ] **Step 2: Write `[...slug].astro`** (reading time computed from word count at build) + +```astro +--- +import { getCollection } from "astro:content"; +import Note from "../../layouts/Note.astro"; + +export async function getStaticPaths() { + const notes = await getCollection("notes", ({ data }) => !data.draft); + return notes.map((note) => { + const words = note.body.trim().split(/\s+/).length; + const readingTime = Math.max(1, Math.round(words / 200)); + return { params: { slug: note.slug }, props: { note, readingTime } }; + }); +} +const { note, readingTime } = Astro.props; +--- + +``` + +- [ ] **Step 3: Append styles to `global.css`** (match the existing prose/reading scale; ~660px column) + +```css +/* --- Notes garden --- */ +.note { max-width: 42rem; margin-inline: auto; padding: 4rem 1.25rem 6rem; } +.note__back { display: inline-block; margin-bottom: 2rem; font-size: 0.9rem; opacity: 0.7; } +.note__eyebrow { font-size: 0.85rem; letter-spacing: 0.02em; opacity: 0.65; margin: 0 0 0.5rem; } +.note__title { font-size: clamp(1.8rem, 4vw, 2.6rem); line-height: 1.15; margin: 0 0 2rem; } +.note__body details { border-left: 2px solid currentColor; padding-left: 1rem; margin: 1.5rem 0; opacity: 0.95; } +.note__body summary { cursor: pointer; font-weight: 600; } +.note__body summary::-webkit-details-marker { color: currentColor; } +``` + +- [ ] **Step 4: Flip the smoke note to non-draft temporarily and build** + +Temporarily set `draft: false` in `src/content/notes/_smoke.md`, then: +Run: `pnpm build` +Expected: build succeeds; `test -f dist/notes/_smoke/index.html` exits 0; `grep -c 'min read' dist/notes/_smoke/index.html` returns `1`. Then revert `draft: true`. + +- [ ] **Step 5: Commit** + +```bash +git add src/layouts/Note.astro src/pages/notes/[...slug].astro src/styles/global.css +git commit -m "feat(notes): note layout, dynamic route, and per-section details styling" +``` + +--- + +### Task 4: Notes index + "Start here" entry + +**Files:** +- Create: `src/pages/notes/index.astro` + +**Interfaces:** +- Consumes: `Base.astro`, `getCollection('notes')`. +- Produces: a page at `/notes` listing non-draft notes newest-first (title link, summary, status, tags). A note whose slug is `start-here` (if present) is pinned to the top under a "Start here" heading. + +- [ ] **Step 1: Write the index page** + +```astro +--- +import Base from "../../layouts/Base.astro"; +import { getCollection } from "astro:content"; +const all = (await getCollection("notes", ({ data }) => !data.draft)).sort( + (a, b) => b.data.date.valueOf() - a.data.date.valueOf() +); +const start = all.find((n) => n.slug === "start-here"); +const rest = all.filter((n) => n.slug !== "start-here"); +const description = "An evergreen garden of notes on attention, sovereignty, and equanimity."; +--- + +
+

Notes

+

{description}

+ {start && ( +
+

Start here

+ + {start.data.title} + {start.data.summary} + +
+ )} + +
+ +``` + +- [ ] **Step 2: Append index styles to `global.css`** + +```css +.notes-index { max-width: 42rem; margin-inline: auto; padding: 4rem 1.25rem 6rem; } +.notes-index__title { font-size: clamp(1.8rem, 4vw, 2.6rem); margin: 0 0 0.5rem; } +.notes-index__intro { opacity: 0.7; margin: 0 0 3rem; } +.notes-index__eyebrow { font-size: 0.85rem; letter-spacing: 0.02em; opacity: 0.65; margin: 0 0 0.5rem; } +.notes-index__list { list-style: none; padding: 0; margin: 2rem 0 0; } +.note-card { display: grid; gap: 0.25rem; padding: 1rem 0; border-top: 1px solid color-mix(in srgb, currentColor 15%, transparent); text-decoration: none; } +.note-card__title { font-weight: 600; } +.note-card__summary { opacity: 0.75; } +.note-card__meta { font-size: 0.8rem; opacity: 0.55; } +``` + +- [ ] **Step 3: Build and verify** + +Run: `pnpm build` +Expected: build succeeds; `test -f dist/notes/index.html` exits 0; `grep -c 'note-card' dist/notes/index.html` returns at least `1` once real notes exist (Task 7). With only the draft smoke note, the list is empty but the page builds. + +- [ ] **Step 4: Commit** + +```bash +git add src/pages/notes/index.astro src/styles/global.css +git commit -m "feat(notes): garden index with pinned Start here entry" +``` + +--- + +### Task 5: RSS feed + +**Files:** +- Create: `src/pages/rss.xml.js` +- Modify: `package.json` (add `@astrojs/rss`) + +**Interfaces:** +- Consumes: `getCollection('notes')`, `context.site` (= `https://equanimi.tech`). +- Produces: a valid RSS document at `/rss.xml` with one `` per non-draft note (title, summary as description, link, pubDate). The autodiscovery `` already exists in `Base.astro` (Task 1). + +- [ ] **Step 1: Install the official RSS package** + +Run: `pnpm add @astrojs/rss` +Expected: `@astrojs/rss` appears under dependencies in `package.json`. + +- [ ] **Step 2: Write the endpoint** + +```js +import rss from "@astrojs/rss"; +import { getCollection } from "astro:content"; + +export async function GET(context) { + const notes = (await getCollection("notes", ({ data }) => !data.draft)).sort( + (a, b) => b.data.date.valueOf() - a.data.date.valueOf() + ); + return rss({ + title: "equanimi.tech Notes", + description: "An evergreen garden of notes on attention, sovereignty, and equanimity.", + site: context.site, + items: notes.map((note) => ({ + title: note.data.title, + description: note.data.summary, + pubDate: note.data.date, + link: `/notes/${note.slug}/`, + })), + }); +} +``` + +- [ ] **Step 3: Build and verify the feed is well-formed** + +Run: `pnpm build` +Expected: build succeeds; `test -f dist/rss.xml` exits 0; `grep -c '` links. + +- [ ] **Step 1: Curate each note.** For each source file below, read it, convert to a self-contained note body, write frontmatter, and replace cross-references with markdown links to sibling notes. Source → destination map: + +| destination slug | source file | status | +|---|---|---| +| `start-here` | `../../torchbearer/docs` thesis + `site/src/pages/index.astro` framework prose | evergreen | +| `the-boat` | `../../torchbearer/docs/2026-05-31-the-boat.md` | evergreen | +| `adaptive-granularity` | `../../torchbearer/docs/2026-05-28-adaptive-granularity-seven-granularities.md` | evergreen | +| `glance-ask-click` | `../../torchbearer/docs/2026-06-07-glance-ask-click.md` | evergreen | +| `ui-navigates-mcp-does-the-work` | `../../torchbearer/docs/2026-05-17-ui-navigates-mcp-does-the-work.md` | budding | +| `personal-os` | `../../keel/docs/2026-06-08-personal-os-article-draft.md` | budding | +| `penceive-as-infrastructure` | `../../penceive/docs/ideas/2026-05-31-penceive-as-infrastructure.md` | evergreen | +| `stamped-by-humans` | `../../torchbearer/docs/2026-05-26-stamped-by-humans-drafting-brief.md` | seedling | + +Frontmatter template (fill per note; keep `summary` to one line; **no em dashes**; strip any `$attestation`/signature blocks from stamped sources): + +```md +--- +title: The Boat +summary: Why equanimity is the load-bearing part you cannot see. +date: 2026-05-31 +status: evergreen +tags: [framework] +related: [adaptive-granularity, penceive-as-infrastructure] +--- + +Body in markdown. Use
for depth-on-demand where a section has a +coarse summary and a deeper expansion. Link siblings inline, e.g. +[Adaptive Granularity](/notes/adaptive-granularity). +``` + +For `adaptive-granularity` specifically: render at least one `
` block so the note that explains depth-on-demand demonstrates it. + +- [ ] **Step 2: Delete the smoke note** + +```bash +rm src/content/notes/_smoke.md +``` + +- [ ] **Step 3: Build and verify the garden is populated** + +Run: `pnpm build` +Expected: build succeeds (all 8 notes pass Zod); then: +- `ls dist/notes | grep -c index.html` reflects 8 note dirs + the index. +- `grep -c 'note-card' dist/notes/index.html` returns `7` (rest) plus the pinned start-here card. +- `grep -c '' dist/rss.xml` returns `8`. + +- [ ] **Step 4: Visual check** + +Run: `pnpm preview`. Visit `/notes` (Start here pinned, 7 listed), click into 3 notes, confirm interlinks resolve, expand a `
` on `adaptive-granularity`, toggle light/dark. + +- [ ] **Step 5: Commit** + +```bash +git add src/content/notes +git commit -m "content(notes): seed the garden with eight interlinked notes from the corpus" +``` + +--- + +## Self-Review + +**Spec coverage:** collection schema (T2), note page + per-section details (T3), index + Start here (T4), RSS + autodiscovery (T1 head + T5), shared Base shell + nav/footer wiring (T1), seed from corpus + drop the 6-Substack-port to optional (T6). Phase 2 stacking intentionally excluded. No gaps. + +**Placeholders:** none. T6 is curation (read source, write note), not a code placeholder; the frontmatter template and source map are concrete. + +**Type consistency:** `getCollection('notes', ({data}) => !data.draft)` used identically in T3/T4/T5. `Note.astro` props `{ note, readingTime }` match what `[...slug].astro` passes. Slug `start-here` referenced in T4 matches the file created in T6. `summary` field used as description in T3/T4/T5 matches the schema in T2. From deefba4e154d491c110647f514fccd7ec1deb970 Mon Sep 17 00:00:00 2001 From: "Rafael T. Ballestiero" Date: Wed, 17 Jun 2026 18:41:41 +0200 Subject: [PATCH 05/13] refactor(site): extract Base.astro shell shared by landing page and garden Co-Authored-By: Claude Opus 4.8 (1M context) --- src/layouts/Base.astro | 101 +++++++++ src/pages/index.astro | 483 +++++++++++++++++------------------------ 2 files changed, 302 insertions(+), 282 deletions(-) create mode 100644 src/layouts/Base.astro diff --git a/src/layouts/Base.astro b/src/layouts/Base.astro new file mode 100644 index 0000000..70652ea --- /dev/null +++ b/src/layouts/Base.astro @@ -0,0 +1,101 @@ +--- +import "../styles/global.css"; + +interface Props { + title: string; + description: string; + path: string; // leading-slash path, e.g. "/" or "/notes" + tagline?: string; // masthead tagline; homepage only +} + +const { title, description, path, tagline } = Astro.props; +const url = `https://equanimi.tech${path}`; +--- + + + + + + {title} + + + + + + + + + + + + + + + + +
+ + + equanimi.tech + + {tagline &&

{tagline}

} + +
+ + + +
+ +
+ + diff --git a/src/pages/index.astro b/src/pages/index.astro index a98425d..ec29e84 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,5 +1,5 @@ --- -import "../styles/global.css"; +import Base from "../layouts/Base.astro"; import Section from "../components/Section.astro"; import Project from "../components/Project.astro"; @@ -7,291 +7,210 @@ const title = "equanimi.tech"; const description = "An open studio building technology that preserves attention and cultivates equanimity."; --- - - - - - - {title} - - - - - - - - - - - - - - - -
- - - equanimi.tech - -

An open studio building technology that preserves attention and cultivates equanimity.

- -
- -
-

We, the users, are being used.

-
+ +
+

We, the users, are being used.

+
+ +
+ {/* §2 Thesis */} +
+
+

Engagement makes you want what feels good and reject what feels bad.

+

Engagement tech makes us more reactive.

+

Equanimity helps us observe feelings, good or bad, and look past them to what really matters.

+

Equanimitech makes us more intentional.

+
+

+ The framework draws on Vipassana practice, where awareness and + equanimity are taught as the two wings of wisdom. We treat + this lineage as a working hypothesis: technology may be able to + support, in small ways, what the practice has long cultivated. + Whether it can is what we are here to find out. +

+

+ Can we design interfaces that sustain and cultivate equanimity? +

+
+ + {/* §3 Framework */} +
+

+ Sovereignty over data is the foundation. Respecting attention is the + moment-to-moment practice. Cultivating equanimity is the long-term + outcome. Nine principles in three layers, each with a design test. +

+ +
+
+

Sovereignty

+
    +
  1. +

    Local-First Ownership

    +

    Does this work offline? If our servers shut down, does the tool keep working?

    +
  2. +
  3. +

    Holistic Control

    +

    Can the user disable any feature without breaking the whole?

    +
  4. +
  5. +

    Modification Rights

    +

    Can a technical user fork it? Can a non-technical user freeze the version?

    +
  6. +
+
+ +
+

Awareness

+
    +
  1. +

    Peripheral Presence

    +

    Can the user safely ignore this for hours?

    +
  2. +
  3. +

    Attentional Granularity

    +

    Does content depth track attentional depth, gross to subtle?

    +
  4. +
  5. +

    Bounded Experiences

    +

    Does this interaction have a natural end? If the user stops, is that a feature?

    +
  6. +
+
+ +
+

Equanimity

+
    +
  1. +

    Strategic Friction

    +

    Is the compulsive path harder than the intentional one?

    +
  2. +
  3. +

    Fade-by-Design

    +

    The user needs the tool less over time, through internalization. If a user stopped after six months, would we celebrate or panic?

    +
  4. +
  5. +

    Downstream Allocation

    +

    The user fills the slots. Recommender systems are upstream allocators; whiteboards with magnets are downstream.

    +
  6. +
+
+
-
- {/* §2 Thesis */} -
-
-

Engagement makes you want what feels good and reject what feels bad.

-

Engagement tech makes us more reactive.

-

Equanimity helps us observe feelings, good or bad, and look past them to what really matters.

-

Equanimitech makes us more intentional.

-
-

- The framework draws on Vipassana practice, where awareness and - equanimity are taught as the two wings of wisdom. We treat - this lineage as a working hypothesis: technology may be able to - support, in small ways, what the practice has long cultivated. - Whether it can is what we are here to find out. +

+ A design hypothesis, not a validated causal model: the principles + create the structural conditions under which equanimity can emerge. + They do not produce it. +

+
+ + {/* §5 The first question (measurement gap) */} +
+
+

+ Before that question can be answered, a smaller one comes + first: how do we measure equanimity in a product, not just in a + practitioner?

-

- Can we design interfaces that sustain and cultivate equanimity? +

+ Equanimity can be measured in people. The EQUA-S scale (Dambrun, + Juneau, Ricard) validates the construct in trained practitioners. + No instrument yet measures it passively in products. The leap from + "reduces compulsion" to "nurtures equanimity" is plausible but + unproven.

-
- - {/* §3 Framework */} -
-

- Sovereignty over data is the foundation. Respecting attention is the - moment-to-moment practice. Cultivating equanimity is the long-term - outcome. Nine principles in three layers, each with a design test. +

+ Closing this measurement gap is our first investigation. + The principles above are how we hope to design; the gap is what + we need to solve so we can know whether the design works.

- -
-
-

Sovereignty

-
    -
  1. -

    Local-First Ownership

    -

    Does this work offline? If our servers shut down, does the tool keep working?

    -
  2. -
  3. -

    Holistic Control

    -

    Can the user disable any feature without breaking the whole?

    -
  4. -
  5. -

    Modification Rights

    -

    Can a technical user fork it? Can a non-technical user freeze the version?

    -
  6. -
-
- -
-

Awareness

-
    -
  1. -

    Peripheral Presence

    -

    Can the user safely ignore this for hours?

    -
  2. -
  3. -

    Attentional Granularity

    -

    Does content depth track attentional depth, gross to subtle?

    -
  4. -
  5. -

    Bounded Experiences

    -

    Does this interaction have a natural end? If the user stops, is that a feature?

    -
  6. -
-
- -
-

Equanimity

-
    -
  1. -

    Strategic Friction

    -

    Is the compulsive path harder than the intentional one?

    -
  2. -
  3. -

    Fade-by-Design

    -

    The user needs the tool less over time, through internalization. If a user stopped after six months, would we celebrate or panic?

    -
  4. -
  5. -

    Downstream Allocation

    -

    The user fills the slots. Recommender systems are upstream allocators; whiteboards with magnets are downstream.

    -
  6. -
-
-
- -

- A design hypothesis, not a validated causal model: the principles - create the structural conditions under which equanimity can emerge. - They do not produce it. + +

+ + {/* §6 Deeper question */} +
+
+

+ Engagement was a measurement choice. The metric became the product, + and the product became the water we swim in. We have forgotten + there was ever anything else.

-
- - {/* §5 The first question (measurement gap) */} -
-
-

- Before that question can be answered, a smaller one comes - first: how do we measure equanimity in a product, not just in a - practitioner? -

-

- Equanimity can be measured in people. The EQUA-S scale (Dambrun, - Juneau, Ricard) validates the construct in trained practitioners. - No instrument yet measures it passively in products. The leap from - "reduces compulsion" to "nurtures equanimity" is plausible but - unproven. -

-

- Closing this measurement gap is our first investigation. - The principles above are how we hope to design; the gap is what - we need to solve so we can know whether the design works. -

-
-
- - {/* §6 Deeper question */} -
-
-

- Engagement was a measurement choice. The metric became the product, - and the product became the water we swim in. We have forgotten - there was ever anything else. -

-

- Goodhart's Law in slow motion: when a measure becomes a target, it - ceases to be a good measure. Metrics don't just describe the - thing. They shape it. A platform optimized for engagement, - sustained over years, makes humans more reactive. A platform - optimized for something else would make humans something else. -

-

- The honest question isn't whether AI will outpace human intellect. - It already has, in narrow ways, and the trend continues. The - honest question is whether the technology we build alongside it - leaves room for what intellect alone has never reached. -

-
-
- - {/* §6 The work (was §7 Work) */} -
-

Four working projects. Different scales. Same principles.

- -
- - - - - - - -
-
- - {/* §8 Door */} -
-
-

- If you're building something in this direction, or thinking about it, - come in. The door is open. -

- -

- For occasional field notes, there is the - newsletter. -

-
-
-
- - {/* §9 Footer */} -
- +
+ + {/* §6 The work (was §7 Work) */} +
+

Four working projects. Different scales. Same principles.

+ +
+ + + + + + + +
+
+ + {/* §8 Door */} +
+
+

+ If you're building something in this direction, or thinking about it, + come in. The door is open. +

+ +

+ For occasional field notes, there is the + newsletter.

-
- - + + + From e0ebe3752c82b75da556fca40af7792f91e9657b Mon Sep 17 00:00:00 2001 From: "Rafael T. Ballestiero" Date: Wed, 17 Jun 2026 18:44:54 +0200 Subject: [PATCH 06/13] feat(notes): collection schema, note layout, garden index, and RSS feed Per-section depth-on-demand via native
. One new dependency (@astrojs/rss). No client-side JS. Co-Authored-By: Claude Opus 4.8 (1M context) --- package.json | 3 + pnpm-lock.yaml | 78 +++++++++++++++++++ src/content/config.ts | 19 +++++ src/layouts/Note.astro | 24 ++++++ src/pages/notes/[...slug].astro | 16 ++++ src/pages/notes/index.astro | 46 +++++++++++ src/pages/rss.xml.js | 20 +++++ src/styles/global.css | 132 ++++++++++++++++++++++++++++++++ 8 files changed, 338 insertions(+) create mode 100644 src/content/config.ts create mode 100644 src/layouts/Note.astro create mode 100644 src/pages/notes/[...slug].astro create mode 100644 src/pages/notes/index.astro create mode 100644 src/pages/rss.xml.js diff --git a/package.json b/package.json index 3cb3e70..7299397 100644 --- a/package.json +++ b/package.json @@ -11,5 +11,8 @@ }, "devDependencies": { "astro": "^4.16.18" + }, + "dependencies": { + "@astrojs/rss": "^4.0.18" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 792dde5..29fb337 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,10 @@ settings: importers: .: + dependencies: + '@astrojs/rss': + specifier: ^4.0.18 + version: 4.0.18 devDependencies: astro: specifier: ^4.16.18 @@ -27,6 +31,9 @@ packages: resolution: {integrity: sha512-Z9IYjuXSArkAUx3N6xj6+Bnvx8OdUSHA8YoOgyepp3+zJmtVYJIl/I18GozdJVW1p5u/CNpl3Km7/gwTJK85cw==} engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0} + '@astrojs/rss@4.0.18': + resolution: {integrity: sha512-wc5DwKlbTEdgVAWnHy8krFTeQ42t1v/DJqeq5HtulYK3FYHE4krtRGjoyhS3eXXgfdV6Raoz2RU3wrMTFAitRg==} + '@astrojs/telemetry@3.1.0': resolution: {integrity: sha512-/ca/+D8MIKEC8/A9cSaPUqQNZm+Es/ZinRv0ZAzvu2ios7POQSsVD+VOj7/hypWNsNM3T7RpfgNq7H2TU1KEHA==} engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0} @@ -392,6 +399,9 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@nodable/entities@2.2.0': + resolution: {integrity: sha512-9uGyhaQavEUMC8AIddIjau4NsnsXhou+j5sBAGojCM1oxmQpVKTWR/9JxABD6UAv12vpIms55fPZKFQEhG6uBg==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -637,6 +647,9 @@ packages: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} + anynum@1.0.0: + resolution: {integrity: sha512-xjR9/zBVnUOP6ztMIIgShjsxui80nQUQH+5xJnvrYLs+90bF25/KJqaAi8mk+B4RDtX1Nspi6fmp4YTEts8SfA==} + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -856,6 +869,13 @@ packages: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} + fast-xml-builder@1.2.0: + resolution: {integrity: sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==} + + fast-xml-parser@5.9.2: + resolution: {integrity: sha512-DYPkXnVSJHAGAkSBeVYhEo/seIpz2SLr9OQcX7m6lXaX3gvoB+DCKzFdZIEhZGI3I1DUhObBAUOT/v2xfoXz/w==} + hasBin: true + fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} @@ -996,6 +1016,9 @@ packages: resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} engines: {node: '>=18'} + is-unsafe@1.0.1: + resolution: {integrity: sha512-CLK2+VdgERgD96EYm5lUQssZYlRg2tkZnbsxZoacmSiRxiFJ4Nk4SzjCl+Ur+v3kXIY9dTIdb3IH22y1mZ56LA==} + is-wsl@3.1.1: resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} engines: {node: '>=16'} @@ -1262,6 +1285,13 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + path-expression-matcher@1.5.0: + resolution: {integrity: sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==} + engines: {node: '>=14.0.0'} + + piccolore@0.1.3: + resolution: {integrity: sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1439,6 +1469,9 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} + strnum@2.4.0: + resolution: {integrity: sha512-sHrVyWWdq28RbhjuJdZsA1SnGRJV6NiXbk6AXBxDOsgAcA+lmpUZCYjOdLBxkXMwis6RRe7dlZt4VlIWFVzkmg==} + tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} @@ -1577,6 +1610,10 @@ packages: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} + xml-naming@0.1.0: + resolution: {integrity: sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==} + engines: {node: '>=16.0.0'} + xxhash-wasm@1.1.0: resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} @@ -1605,6 +1642,9 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -1641,6 +1681,12 @@ snapshots: dependencies: prismjs: 1.30.0 + '@astrojs/rss@4.0.18': + dependencies: + fast-xml-parser: 5.9.2 + piccolore: 0.1.3 + zod: 4.4.3 + '@astrojs/telemetry@3.1.0': dependencies: ci-info: 4.4.0 @@ -1943,6 +1989,8 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@nodable/entities@2.2.0': {} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2136,6 +2184,8 @@ snapshots: ansi-styles@6.2.3: {} + anynum@1.0.0: {} + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -2407,6 +2457,20 @@ snapshots: merge2: 1.4.1 micromatch: 4.0.8 + fast-xml-builder@1.2.0: + dependencies: + path-expression-matcher: 1.5.0 + xml-naming: 0.1.0 + + fast-xml-parser@5.9.2: + dependencies: + '@nodable/entities': 2.2.0 + fast-xml-builder: 1.2.0 + is-unsafe: 1.0.1 + path-expression-matcher: 1.5.0 + strnum: 2.4.0 + xml-naming: 0.1.0 + fastq@1.20.1: dependencies: reusify: 1.1.0 @@ -2575,6 +2639,8 @@ snapshots: is-unicode-supported@2.1.0: {} + is-unsafe@1.0.1: {} + is-wsl@3.1.1: dependencies: is-inside-container: 1.0.0 @@ -3026,6 +3092,10 @@ snapshots: path-exists@4.0.0: {} + path-expression-matcher@1.5.0: {} + + piccolore@0.1.3: {} + picocolors@1.1.1: {} picomatch@2.3.2: {} @@ -3298,6 +3368,10 @@ snapshots: strip-bom@3.0.0: {} + strnum@2.4.0: + dependencies: + anynum: 1.0.0 + tinyexec@0.3.2: {} to-regex-range@5.0.1: @@ -3422,6 +3496,8 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.2.0 + xml-naming@0.1.0: {} + xxhash-wasm@1.1.0: {} yallist@3.1.1: {} @@ -3441,4 +3517,6 @@ snapshots: zod@3.25.76: {} + zod@4.4.3: {} + zwitch@2.0.4: {} diff --git a/src/content/config.ts b/src/content/config.ts new file mode 100644 index 0000000..0a2094e --- /dev/null +++ b/src/content/config.ts @@ -0,0 +1,19 @@ +import { defineCollection, z } from "astro:content"; + +const notes = defineCollection({ + type: "content", + schema: ({ image }) => + z.object({ + title: z.string(), + summary: z.string(), + date: z.coerce.date(), + tags: z.array(z.string()).optional(), + // Garden maturity. seedling = stub seeded from existing text, room to grow; + // budding = drafted; evergreen = tended and load-bearing. + status: z.enum(["evergreen", "budding", "seedling"]).default("budding"), + hero: image().optional(), + draft: z.boolean().default(false), + }), +}); + +export const collections = { notes }; diff --git a/src/layouts/Note.astro b/src/layouts/Note.astro new file mode 100644 index 0000000..ee2ddb7 --- /dev/null +++ b/src/layouts/Note.astro @@ -0,0 +1,24 @@ +--- +import Base from "./Base.astro"; +import type { CollectionEntry } from "astro:content"; + +interface Props { + note: CollectionEntry<"notes">; + readingTime: number; +} + +const { note, readingTime } = Astro.props; +const { Content } = await note.render(); +const { title, summary, status, tags = [] } = note.data; +const meta = [`${readingTime} min read`, status, ...tags.map((t) => `#${t}`)]; +--- + +
+ ← Notes +

{meta.join(" · ")}

+

{title}

+
+ +
+
+ diff --git a/src/pages/notes/[...slug].astro b/src/pages/notes/[...slug].astro new file mode 100644 index 0000000..0b79495 --- /dev/null +++ b/src/pages/notes/[...slug].astro @@ -0,0 +1,16 @@ +--- +import { getCollection } from "astro:content"; +import Note from "../../layouts/Note.astro"; + +export async function getStaticPaths() { + const notes = await getCollection("notes", ({ data }) => !data.draft); + return notes.map((note) => { + const words = note.body.trim().split(/\s+/).length; + const readingTime = Math.max(1, Math.round(words / 200)); + return { params: { slug: note.slug }, props: { note, readingTime } }; + }); +} + +const { note, readingTime } = Astro.props; +--- + diff --git a/src/pages/notes/index.astro b/src/pages/notes/index.astro new file mode 100644 index 0000000..68720fa --- /dev/null +++ b/src/pages/notes/index.astro @@ -0,0 +1,46 @@ +--- +import Base from "../../layouts/Base.astro"; +import { getCollection } from "astro:content"; + +const all = (await getCollection("notes", ({ data }) => !data.draft)).sort( + (a, b) => b.data.date.valueOf() - a.data.date.valueOf(), +); +const start = all.find((n) => n.slug === "start-here"); +const rest = all.filter((n) => n.slug !== "start-here"); + +const description = + "An evergreen garden of notes on attention, sovereignty, and equanimity."; + +function meta(note: (typeof all)[number]) { + const tags = note.data.tags ?? []; + return [note.data.status, ...tags.map((t) => `#${t}`)].join(" · "); +} +--- + +
+

Notes

+

{description}

+ + {start && ( +
+

Start here

+ + {start.data.title} + {start.data.summary} + +
+ )} + + +
+ diff --git a/src/pages/rss.xml.js b/src/pages/rss.xml.js new file mode 100644 index 0000000..da74ed5 --- /dev/null +++ b/src/pages/rss.xml.js @@ -0,0 +1,20 @@ +import rss from "@astrojs/rss"; +import { getCollection } from "astro:content"; + +export async function GET(context) { + const notes = (await getCollection("notes", ({ data }) => !data.draft)).sort( + (a, b) => b.data.date.valueOf() - a.data.date.valueOf(), + ); + return rss({ + title: "equanimi.tech Notes", + description: + "An evergreen garden of notes on attention, sovereignty, and equanimity.", + site: context.site, + items: notes.map((note) => ({ + title: note.data.title, + description: note.data.summary, + pubDate: note.data.date, + link: `/notes/${note.slug}/`, + })), + }); +} diff --git a/src/styles/global.css b/src/styles/global.css index 396c11f..6e230cf 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -601,6 +601,138 @@ main { } } +/* --------------------------------------------------------------- + Notes garden: a calm reading column + index. Inherits the stone + palette, fluid type, and prose rhythm above. + --------------------------------------------------------------- */ +.note { + max-width: var(--measure); +} +.note__back { + display: inline-block; + font-family: var(--font-mono); + font-size: var(--fs-xs); + letter-spacing: 0.06em; + text-transform: uppercase; + color: var(--color-muted); + margin-bottom: calc(var(--spacing) * 12); +} +.note__eyebrow { + font-family: var(--font-mono); + font-size: var(--fs-xs); + letter-spacing: 0.06em; + color: var(--color-muted); + margin-bottom: calc(var(--spacing) * 3); +} +.note__title { + font-size: var(--fs-2xl); + font-weight: 500; + letter-spacing: -0.02em; + margin-bottom: calc(var(--spacing) * 12); +} +/* Body prose: headings, lists, code, blockquotes within a note. */ +.note__body h2 { font-size: var(--fs-lg); margin: calc(var(--spacing) * 12) 0 calc(var(--spacing) * 4); } +.note__body h3 { font-size: var(--fs-md); margin: calc(var(--spacing) * 8) 0 calc(var(--spacing) * 3); } +.note__body p { margin-top: 1.25em; } +.note__body ul, .note__body ol { margin: 1.25em 0; padding-left: 1.4em; } +.note__body ul { list-style: disc; } +.note__body ol { list-style: decimal; } +.note__body li + li { margin-top: 0.4em; } +.note__body blockquote { + border-left: 1px solid var(--color-accent); + padding-left: calc(var(--spacing) * 6); + color: var(--color-muted); + font-style: italic; + margin: 1.5em 0; +} +.note__body code { + font-family: var(--font-mono); + font-size: 0.9em; + background: var(--color-rule); + padding: 0.1em 0.35em; + border-radius: 2px; +} +.note__body pre { + background: var(--color-rule); + padding: calc(var(--spacing) * 4); + border-radius: 4px; + overflow-x: auto; + margin: 1.5em 0; +} +.note__body pre code { background: none; padding: 0; } +.note__body a { color: var(--color-text); } +.note__body img { margin: 1.5em 0; border-radius: 4px; } + +/* Per-section expansion: depth-on-demand via native
. */ +.note__body details { + border-left: 2px solid var(--color-rule); + padding-left: calc(var(--spacing) * 5); + margin: 1.5em 0; +} +.note__body details[open] { border-left-color: var(--color-accent); } +.note__body summary { + cursor: pointer; + font-weight: 500; + color: var(--color-text); + list-style: none; +} +.note__body summary::-webkit-details-marker { display: none; } +.note__body summary::before { + content: "+ "; + font-family: var(--font-mono); + color: var(--color-accent); +} +.note__body details[open] summary::before { content: "\2212 "; } + +/* Index: a quiet list of cards. */ +.notes-index { + max-width: var(--measure); +} +.notes-index__title { + font-size: var(--fs-2xl); + font-weight: 500; + letter-spacing: -0.02em; + margin-bottom: calc(var(--spacing) * 3); +} +.notes-index__intro { + color: var(--color-muted); + max-width: var(--measure-narrow); + margin-bottom: calc(var(--spacing) * 16); +} +.notes-index__eyebrow { + font-family: var(--font-mono); + font-size: var(--fs-xs); + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--color-accent); + margin-bottom: calc(var(--spacing) * 4); +} +.notes-index__start { margin-bottom: calc(var(--spacing) * 14); } +.notes-index__list { display: flex; flex-direction: column; } +.note-card { + display: grid; + gap: calc(var(--spacing) * 1); + padding-block: calc(var(--spacing) * 5); + border-top: 1px solid var(--color-rule); + background-image: none; +} +.notes-index__start .note-card { border-top: 0; padding-top: 0; } +.note-card__title { + font-size: var(--fs-md); + font-weight: 500; + color: var(--color-text); +} +.note-card__summary { color: var(--color-muted); } +.note-card__meta { + font-family: var(--font-mono); + font-size: var(--fs-xs); + letter-spacing: 0.04em; + color: var(--color-faint); +} +@media (hover: hover) { + .note-card:hover .note-card__title { color: var(--color-accent); } +} + /* Dark mode: invert semantic vars; OKLCH stays perceptually uniform. */ @media (prefers-color-scheme: dark) { :root { From a6ca1eb289edacc19dd0d7557c2efa6a67f9f293 Mon Sep 17 00:00:00 2001 From: "Rafael T. Ballestiero" Date: Wed, 17 Jun 2026 18:44:54 +0200 Subject: [PATCH 07/13] content(notes): seed the garden spine, start-here and nine principle notes Principle notes are seedlings grown from the landing-page design tests. Attentional Granularity demonstrates the
zoom it describes. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/notes/attentional-granularity.md | 22 +++++++++++ src/content/notes/bounded-experiences.md | 15 ++++++++ src/content/notes/downstream-allocation.md | 15 ++++++++ src/content/notes/fade-by-design.md | 15 ++++++++ src/content/notes/holistic-control.md | 15 ++++++++ src/content/notes/local-first-ownership.md | 15 ++++++++ src/content/notes/modification-rights.md | 15 ++++++++ src/content/notes/peripheral-presence.md | 15 ++++++++ src/content/notes/start-here.md | 39 ++++++++++++++++++++ src/content/notes/strategic-friction.md | 15 ++++++++ 10 files changed, 181 insertions(+) create mode 100644 src/content/notes/attentional-granularity.md create mode 100644 src/content/notes/bounded-experiences.md create mode 100644 src/content/notes/downstream-allocation.md create mode 100644 src/content/notes/fade-by-design.md create mode 100644 src/content/notes/holistic-control.md create mode 100644 src/content/notes/local-first-ownership.md create mode 100644 src/content/notes/modification-rights.md create mode 100644 src/content/notes/peripheral-presence.md create mode 100644 src/content/notes/start-here.md create mode 100644 src/content/notes/strategic-friction.md diff --git a/src/content/notes/attentional-granularity.md b/src/content/notes/attentional-granularity.md new file mode 100644 index 0000000..9f58a41 --- /dev/null +++ b/src/content/notes/attentional-granularity.md @@ -0,0 +1,22 @@ +--- +title: Attentional Granularity +summary: Content depth should track attentional depth, from a glance to a deep read. +date: 2026-06-17 +status: seedling +tags: [awareness] +--- + +A principle of the [Awareness layer](/notes/start-here). A tool should let you read at the resolution your attention can spare right now, gross to subtle, without forcing the whole depth on you at once. + +**The design test** + +> Does content depth track attentional depth, gross to subtle? + +
+Show me what that means + +You just used it. The summary above is the handle; this is the next layer down. A note can offer a sentence, a paragraph, or the whole essay, and let you choose how far to descend. Depth on demand, never depth imposed. + +
+ +This note is a seedling. A fuller treatment, the seven granularities, is on its way. diff --git a/src/content/notes/bounded-experiences.md b/src/content/notes/bounded-experiences.md new file mode 100644 index 0000000..3769f0a --- /dev/null +++ b/src/content/notes/bounded-experiences.md @@ -0,0 +1,15 @@ +--- +title: Bounded Experiences +summary: An interaction should have a natural end, and stopping should count as success. +date: 2026-06-17 +status: seedling +tags: [awareness] +--- + +A principle of the [Awareness layer](/notes/start-here). The opposite of the infinite feed. An experience with an edge lets you finish, and treats your leaving as the design working, not failing. + +**The design test** + +> Does this interaction have a natural end? If the user stops, is that a feature? + +This note is a seedling. The full write-up is on its way. diff --git a/src/content/notes/downstream-allocation.md b/src/content/notes/downstream-allocation.md new file mode 100644 index 0000000..4e02f33 --- /dev/null +++ b/src/content/notes/downstream-allocation.md @@ -0,0 +1,15 @@ +--- +title: Downstream Allocation +summary: You fill the slots. The tool does not fill them for you. +date: 2026-06-17 +status: seedling +tags: [equanimity] +--- + +A principle of the [Equanimity layer](/notes/start-here). Who decides what fills your attention? An upstream allocator, like a recommender, decides for you. A downstream tool, like a whiteboard with magnets, leaves the deciding to you. + +**The design test** + +> The user fills the slots. Recommender systems are upstream allocators; whiteboards with magnets are downstream. + +This note is a seedling. The full write-up is on its way. diff --git a/src/content/notes/fade-by-design.md b/src/content/notes/fade-by-design.md new file mode 100644 index 0000000..7a1ce39 --- /dev/null +++ b/src/content/notes/fade-by-design.md @@ -0,0 +1,15 @@ +--- +title: Fade-by-Design +summary: The best tools make themselves less needed over time. +date: 2026-06-17 +status: seedling +tags: [equanimity] +--- + +A principle of the [Equanimity layer](/notes/start-here). Success is internalization. The tool teaches something the user comes to carry on their own, and so needs the tool less. + +**The design test** + +> The user needs the tool less over time, through internalization. If a user stopped after six months, would we celebrate or panic? + +This note is a seedling. The full write-up is on its way. diff --git a/src/content/notes/holistic-control.md b/src/content/notes/holistic-control.md new file mode 100644 index 0000000..89ca13f --- /dev/null +++ b/src/content/notes/holistic-control.md @@ -0,0 +1,15 @@ +--- +title: Holistic Control +summary: Every feature should be one you can switch off without breaking the whole. +date: 2026-06-17 +status: seedling +tags: [sovereignty] +--- + +A principle of the [Sovereignty layer](/notes/start-here). Control is not a single setting. It is the property that any part can be turned off, and the rest still stands. + +**The design test** + +> Can the user disable any feature without breaking the whole? + +This note is a seedling. The full write-up is on its way. diff --git a/src/content/notes/local-first-ownership.md b/src/content/notes/local-first-ownership.md new file mode 100644 index 0000000..82ea195 --- /dev/null +++ b/src/content/notes/local-first-ownership.md @@ -0,0 +1,15 @@ +--- +title: Local-First Ownership +summary: Sovereignty begins with software that is yours even when the company is gone. +date: 2026-06-17 +status: seedling +tags: [sovereignty] +--- + +The first principle of the [Sovereignty layer](/notes/start-here). Your data lives with you, and the tool keeps working whether or not anyone is still running a server for it. + +**The design test** + +> Does this work offline? If our servers shut down, does the tool keep working? + +This note is a seedling. The full write-up is on its way. diff --git a/src/content/notes/modification-rights.md b/src/content/notes/modification-rights.md new file mode 100644 index 0000000..257241b --- /dev/null +++ b/src/content/notes/modification-rights.md @@ -0,0 +1,15 @@ +--- +title: Modification Rights +summary: The technical can fork it; the non-technical can freeze it. Both stay in control. +date: 2026-06-17 +status: seedling +tags: [sovereignty] +--- + +A principle of the [Sovereignty layer](/notes/start-here). The right to change the tool, or to refuse a change, belongs to the person using it, not only to the people shipping it. + +**The design test** + +> Can a technical user fork it? Can a non-technical user freeze the version? + +This note is a seedling. The full write-up is on its way. diff --git a/src/content/notes/peripheral-presence.md b/src/content/notes/peripheral-presence.md new file mode 100644 index 0000000..1fa9c8a --- /dev/null +++ b/src/content/notes/peripheral-presence.md @@ -0,0 +1,15 @@ +--- +title: Peripheral Presence +summary: A good tool can sit at the edge of attention and be safely ignored. +date: 2026-06-17 +status: seedling +tags: [awareness] +--- + +The first principle of the [Awareness layer](/notes/start-here). Calm technology lives in the periphery. It waits there until you turn to it, and asks nothing while you do not. + +**The design test** + +> Can the user safely ignore this for hours? + +This note is a seedling. The full write-up is on its way. diff --git a/src/content/notes/start-here.md b/src/content/notes/start-here.md new file mode 100644 index 0000000..f3456a1 --- /dev/null +++ b/src/content/notes/start-here.md @@ -0,0 +1,39 @@ +--- +title: Start here +summary: An open studio building technology that preserves attention and cultivates equanimity. +date: 2026-06-17 +status: evergreen +tags: [framework] +--- + +Engagement technology makes us more reactive. It teaches us to want what feels good and reject what feels bad. Equanimitech is the wager that technology can do the opposite: help us observe feelings, good or bad, and look past them to what matters. Tools that make us more intentional, not more reactive. + +The framework is nine principles in three layers, each with a design test you can hold a product against. + +## Sovereignty + +The foundation: your data and tools are yours. + +- [Local-First Ownership](/notes/local-first-ownership) +- [Holistic Control](/notes/holistic-control) +- [Modification Rights](/notes/modification-rights) + +## Awareness + +The moment-to-moment practice: respect attention. + +- [Peripheral Presence](/notes/peripheral-presence) +- [Attentional Granularity](/notes/attentional-granularity) +- [Bounded Experiences](/notes/bounded-experiences) + +## Equanimity + +The long-term outcome: cultivate steadiness. + +- [Strategic Friction](/notes/strategic-friction) +- [Fade-by-Design](/notes/fade-by-design) +- [Downstream Allocation](/notes/downstream-allocation) + +A design hypothesis, not a validated causal model: the principles create the structural conditions under which equanimity can emerge. They do not produce it. Whether they work is what this studio is here to find out. + +The garden grows from here. Most of these notes are seedlings today. diff --git a/src/content/notes/strategic-friction.md b/src/content/notes/strategic-friction.md new file mode 100644 index 0000000..c7fa334 --- /dev/null +++ b/src/content/notes/strategic-friction.md @@ -0,0 +1,15 @@ +--- +title: Strategic Friction +summary: Make the compulsive path harder than the intentional one. +date: 2026-06-17 +status: seedling +tags: [equanimity] +--- + +The first principle of the [Equanimity layer](/notes/start-here). Friction is not always the enemy. Placed well, it tilts the easy default away from compulsion and toward intention. + +**The design test** + +> Is the compulsive path harder than the intentional one? + +This note is a seedling. The full write-up is on its way. From 82ed70b2bf34e7e83a86dd09dc6e76fbcbb881bf Mon Sep 17 00:00:00 2001 From: "Rafael T. Ballestiero" Date: Wed, 17 Jun 2026 18:54:15 +0200 Subject: [PATCH 08/13] content(notes): ground the nine principle notes in the actual corpus Rewritten from zenborg/docs/principles.md (canonical definitions + design tests), with cross-product examples from keel, respost, secretariat, signet, and lineage from torchbearer. Depth layers via
dogfood Attentional Granularity. No longer thin stubs. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/notes/attentional-granularity.md | 24 ++++++++++++++++---- src/content/notes/bounded-experiences.md | 19 ++++++++++++---- src/content/notes/downstream-allocation.md | 20 ++++++++++++---- src/content/notes/fade-by-design.md | 21 +++++++++++++---- src/content/notes/holistic-control.md | 19 ++++++++++++---- src/content/notes/local-first-ownership.md | 22 ++++++++++++++---- src/content/notes/modification-rights.md | 19 ++++++++++++---- src/content/notes/peripheral-presence.md | 19 ++++++++++++---- src/content/notes/strategic-friction.md | 20 ++++++++++++---- 9 files changed, 139 insertions(+), 44 deletions(-) diff --git a/src/content/notes/attentional-granularity.md b/src/content/notes/attentional-granularity.md index 9f58a41..99bae1f 100644 --- a/src/content/notes/attentional-granularity.md +++ b/src/content/notes/attentional-granularity.md @@ -1,12 +1,14 @@ --- title: Attentional Granularity -summary: Content depth should track attentional depth, from a glance to a deep read. +summary: Content depth should track attentional depth. Start gross, deepen only as focus settles. Gross to subtle, never the reverse. date: 2026-06-17 -status: seedling +status: evergreen tags: [awareness] --- -A principle of the [Awareness layer](/notes/start-here). A tool should let you read at the resolution your attention can spare right now, gross to subtle, without forcing the whole depth on you at once. +A principle of the [Awareness layer](/notes/start-here), and the one this garden is built on. Depth is not a property of the content; it is a relationship between content and reader, where the right depth is whatever matches the reader's current attentional state. + +The direction matters. Always gross to subtle, never the reverse. Starting with detail and asking the reader to summarize is overwhelm. Starting with the gist and letting the reader descend is honest. **The design test** @@ -15,8 +17,20 @@ A principle of the [Awareness layer](/notes/start-here). A tool should let you r
Show me what that means -You just used it. The summary above is the handle; this is the next layer down. A note can offer a sentence, a paragraph, or the whole essay, and let you choose how far to descend. Depth on demand, never depth imposed. +You just used it. The summary above is the handle; this is the next layer down. A piece of writing can offer a sentence, a paragraph, or the whole essay, and let you choose how far to descend. Depth on demand, never depth imposed. + +The full treatment is a ladder of seven granularities, from a two-word handle to a book, operationalized in the studio as the `semantic-zoom` discipline. + +
+ +
+How it shows up in the work + +- **Zenborg**: moments are one to three words, not paragraphs. Phases are coarser than clock times. The timeline shows three days, not a month. You zoom in as attention settles; the system never dumps a dashboard. +- **Respost**: envelope to glance, flap to signal intent, photo to commit, message for depth. You can stop at any layer with something complete. + +Lineage and evidence: Cognitive Load Theory (Sweller), Information Foraging (Pirolli and Card), and the gross-to-subtle progression of Vipassana body-scanning.
-This note is a seedling. A fuller treatment, the seven granularities, is on its way. +The most tended note in the garden. See also [Peripheral Presence](/notes/peripheral-presence) and [Bounded Experiences](/notes/bounded-experiences). diff --git a/src/content/notes/bounded-experiences.md b/src/content/notes/bounded-experiences.md index 3769f0a..c9874d3 100644 --- a/src/content/notes/bounded-experiences.md +++ b/src/content/notes/bounded-experiences.md @@ -1,8 +1,8 @@ --- title: Bounded Experiences -summary: An interaction should have a natural end, and stopping should count as success. +summary: Digital interactions should have natural endpoints. No infinite scroll, no autoplay, no bottomless feed. Stopping is success. date: 2026-06-17 -status: seedling +status: budding tags: [awareness] --- @@ -10,6 +10,17 @@ A principle of the [Awareness layer](/notes/start-here). The opposite of the inf **The design test** -> Does this interaction have a natural end? If the user stops, is that a feature? +> Does this interaction have a natural end? If the user stops, is that a feature or a failure? -This note is a seedling. The full write-up is on its way. +
+How it shows up in the work + +- **Zenborg**: three moments per phase, three days on the timeline, cycles with start and end dates. When you finish placing today's intentions, you are done. There is no next screen. +- **Respost**: a card ends with "fim, take your time." No autoplay, no next. +- **Glance / Ask / Click**: Ask terminates, Click terminates. The paradigm is structurally anti-feed. + +Evidence: Grüning's 2023 grayscale-screen study found a 22 to 57 minute drop in daily usage when the bottomless pull was dampened. + +
+ +A budding note. See also [Peripheral Presence](/notes/peripheral-presence) and [Fade-by-Design](/notes/fade-by-design). diff --git a/src/content/notes/downstream-allocation.md b/src/content/notes/downstream-allocation.md index 4e02f33..3bee222 100644 --- a/src/content/notes/downstream-allocation.md +++ b/src/content/notes/downstream-allocation.md @@ -1,15 +1,25 @@ --- title: Downstream Allocation -summary: You fill the slots. The tool does not fill them for you. +summary: The user fills the slots, the system does not. Recommenders are upstream allocators; a whiteboard with magnets is downstream. date: 2026-06-17 -status: seedling +status: budding tags: [equanimity] --- -A principle of the [Equanimity layer](/notes/start-here). Who decides what fills your attention? An upstream allocator, like a recommender, decides for you. A downstream tool, like a whiteboard with magnets, leaves the deciding to you. +A principle of the [Equanimity layer](/notes/start-here), and the purest expression of the thesis. Who decides what fills your attention? An upstream allocator, like a recommender, decides for you. A downstream tool leaves the deciding to you, and only surfaces context so you can decide well. **The design test** -> The user fills the slots. Recommender systems are upstream allocators; whiteboards with magnets are downstream. +> Who decided what the user is looking at right now, the user or the system? -This note is a seedling. The full write-up is on its way. +
+How it shows up in the work + +- **Zenborg**: no feed, no recommendations, no auto-placement. The system surfaces context, whispers and dormancy indicators, but the allocation decision always belongs to the person. The standing question is "where will I place my consciousness today?" +- **Respost**: the sender fills the slots. No algorithm decides what fills the screen. + +The image to hold: a recommender system is an upstream allocator that fills your slots before you arrive. A whiteboard with magnets is downstream. The slots are empty until you place them. + +
+ +A budding note, the most abstract of the nine, leaning on the others as scaffolding. See also [Strategic Friction](/notes/strategic-friction). diff --git a/src/content/notes/fade-by-design.md b/src/content/notes/fade-by-design.md index 7a1ce39..9c61776 100644 --- a/src/content/notes/fade-by-design.md +++ b/src/content/notes/fade-by-design.md @@ -1,15 +1,26 @@ --- title: Fade-by-Design -summary: The best tools make themselves less needed over time. +summary: Success means the user needs the tool less over time, through internalization. Training wheels, not crutches. date: 2026-06-17 -status: seedling +status: budding tags: [equanimity] --- -A principle of the [Equanimity layer](/notes/start-here). Success is internalization. The tool teaches something the user comes to carry on their own, and so needs the tool less. +A principle of the [Equanimity layer](/notes/start-here). The asymmetry is the whole point. The tool should teach something the user comes to carry on their own, and so needs the tool less. A graduated user is a success, not a churn metric. **The design test** -> The user needs the tool less over time, through internalization. If a user stopped after six months, would we celebrate or panic? +> If a user stopped after six months because they had internalized the skill, would we celebrate or panic? -This note is a seedling. The full write-up is on its way. +
+How it shows up in the work + +- **Zenborg**: attitude and rhythm awareness build the user's own capacity to tend their garden. Eventually the tool is a mirror reflecting patterns the user already knows, not a prompt telling them what to do. +- **keel**: nudges fire once, then go quiet. Success is the tool disappearing. The friction dial easing to nothing, because your own rhythm holds, is the tool fading on purpose. +- **Respost**: two postcards a month is a success. No streaks. + +The engagement world's tools panic when you leave. These are built to be left. + +
+ +A budding note. See also [Bounded Experiences](/notes/bounded-experiences). diff --git a/src/content/notes/holistic-control.md b/src/content/notes/holistic-control.md index 89ca13f..6772716 100644 --- a/src/content/notes/holistic-control.md +++ b/src/content/notes/holistic-control.md @@ -1,15 +1,24 @@ --- title: Holistic Control -summary: Every feature should be one you can switch off without breaking the whole. +summary: The user controls what features are active and what data flows where. No dark patterns, no forced updates, no locked features. date: 2026-06-17 -status: seedling +status: budding tags: [sovereignty] --- -A principle of the [Sovereignty layer](/notes/start-here). Control is not a single setting. It is the property that any part can be turned off, and the rest still stands. +A principle of the [Sovereignty layer](/notes/start-here). Control is not a single setting. It is the property that any part can be turned off, and the rest still stands. Defaults exist, but they can always be overridden. **The design test** -> Can the user disable any feature without breaking the whole? +> Can the user explain what this tool does and why? Can they disable any feature without breaking the whole? -This note is a seedling. The full write-up is on its way. +
+How it shows up in the work + +- **Zenborg**: phases, areas, attitudes, and cycles are all user-configurable. The Night phase can be hidden entirely. No feature is gated behind an account tier. +- **Respost**: the recipient owns whether and when to open. No read receipts, no tracking. +- **Secretariat**: cognition is pluggable. Claude Code, the API, or a local model. The principal owns the brain, not a vendor. + +
+ +A budding note. Lineage runs through Ursula Franklin's distinction between holistic and prescriptive technologies. See also [Local-First Ownership](/notes/local-first-ownership). diff --git a/src/content/notes/local-first-ownership.md b/src/content/notes/local-first-ownership.md index 82ea195..8f2c042 100644 --- a/src/content/notes/local-first-ownership.md +++ b/src/content/notes/local-first-ownership.md @@ -1,15 +1,27 @@ --- title: Local-First Ownership -summary: Sovereignty begins with software that is yours even when the company is gone. +summary: The user owns their data and computation. Not "we store it securely for you," the user possesses it. date: 2026-06-17 -status: seedling +status: budding tags: [sovereignty] --- -The first principle of the [Sovereignty layer](/notes/start-here). Your data lives with you, and the tool keeps working whether or not anyone is still running a server for it. +The foundation of the [Sovereignty layer](/notes/start-here). Ownership is not custody. The tool keeps working whether or not anyone is still running a server for it. **The design test** -> Does this work offline? If our servers shut down, does the tool keep working? +> Does this work offline? Would the user lose anything if our servers shut down tomorrow? -This note is a seedling. The full write-up is on its way. +
+How it shows up in the work + +The whole studio is built on this floor. + +- **Zenborg** keeps its vault in IndexedDB and `~/.zenborg` JSON. Sync is optional, never required. If the servers vanished tomorrow, nothing breaks. +- **keel** writes attention logs to `~/.keel/log/` as append-only JSONL, and its browser extension keeps all state in local storage. No account, no server, no sync. +- **Secretariat** is filesystem-authoritative: every document, identity, and instruction is a markdown file on disk. No database-as-truth. Keys never leave the device. +- **Respost** rides on AT Protocol records: the postcard survives a Respost shutdown because the link is the postcard. + +
+ +A budding note, grounded in the work but not yet a finished essay. See also [Modification Rights](/notes/modification-rights) and [Holistic Control](/notes/holistic-control). diff --git a/src/content/notes/modification-rights.md b/src/content/notes/modification-rights.md index 257241b..2e83be6 100644 --- a/src/content/notes/modification-rights.md +++ b/src/content/notes/modification-rights.md @@ -1,15 +1,24 @@ --- title: Modification Rights -summary: The technical can fork it; the non-technical can freeze it. Both stay in control. +summary: Open source by default. The technically capable can fork or adapt it; the non-technical can freeze it. Both stay in control. date: 2026-06-17 -status: seedling +status: budding tags: [sovereignty] --- -A principle of the [Sovereignty layer](/notes/start-here). The right to change the tool, or to refuse a change, belongs to the person using it, not only to the people shipping it. +A principle of the [Sovereignty layer](/notes/start-here). The right to change the tool, or to refuse a change, belongs to the person using it, not only to the people shipping it. Not everyone needs to modify code, but everyone should be able to, without permission. **The design test** -> Can a technical user fork it? Can a non-technical user freeze the version? +> Can a technically capable user change how this works? Can a non-technical user freeze the current version? -This note is a seedling. The full write-up is on its way. +
+How it shows up in the work + +- **Zenborg** is MIT-licensed, and its vault is plain JSON: readable, editable, forkable in any text editor. A technical user can patch it; a non-technical user can pin a released version and stay there. +- **Respost** plans a "save to my phone" export that writes a static page, so the artifact outlives the service. +- **Signet** anchors identity in a DID you hold: did:key or did:web, no certificate authority, no key server. + +
+ +A budding note, in the free-software lineage of Loy and Williams. See also [Local-First Ownership](/notes/local-first-ownership). diff --git a/src/content/notes/peripheral-presence.md b/src/content/notes/peripheral-presence.md index 1fa9c8a..52494f5 100644 --- a/src/content/notes/peripheral-presence.md +++ b/src/content/notes/peripheral-presence.md @@ -1,15 +1,24 @@ --- title: Peripheral Presence -summary: A good tool can sit at the edge of attention and be safely ignored. +summary: Technology should inform without demanding focal attention. You visit it; it does not visit you. Boring by design. date: 2026-06-17 -status: seedling +status: budding tags: [awareness] --- -The first principle of the [Awareness layer](/notes/start-here). Calm technology lives in the periphery. It waits there until you turn to it, and asks nothing while you do not. +The first principle of the [Awareness layer](/notes/start-here). Calm technology lives in the periphery. Its default mode is ambient. It moves to the center only when genuinely needed, then returns to the edge. **The design test** -> Can the user safely ignore this for hours? +> Can the user safely ignore this for hours? Does it use the periphery, light, position, a color shift, before demanding focal attention? -This note is a seedling. The full write-up is on its way. +
+How it shows up in the work + +- **Zenborg**: area dormancy indicators, attitude whispers, and rhythm signals are all ambient. No push notifications, no badges, no red dots, no modal alerts. +- **keel**: the day's intention and appetite are echoed as a single quiet status line each turn, then silence. +- **Respost**: a card arrives through a channel you already check, so there is no second inbox to manage. + +
+ +A budding note, in the calm-technology lineage of Mark Weiser and Amber Case. See also [Bounded Experiences](/notes/bounded-experiences). diff --git a/src/content/notes/strategic-friction.md b/src/content/notes/strategic-friction.md index c7fa334..ddbca27 100644 --- a/src/content/notes/strategic-friction.md +++ b/src/content/notes/strategic-friction.md @@ -1,15 +1,25 @@ --- title: Strategic Friction -summary: Make the compulsive path harder than the intentional one. +summary: Make the compulsive path harder and the intentional path easier. Strategic friction is compassionate, not bureaucratic. date: 2026-06-17 -status: seedling +status: budding tags: [equanimity] --- -The first principle of the [Equanimity layer](/notes/start-here). Friction is not always the enemy. Placed well, it tilts the easy default away from compulsion and toward intention. +The first principle of the [Equanimity layer](/notes/start-here). Not all friction is good. Bureaucratic friction is hostile. Strategic friction is compassionate: it slows automatic reactivity without blocking deliberate action. It tilts the easy default away from compulsion and toward intention. **The design test** -> Is the compulsive path harder than the intentional one? +> Is the compulsive path frictionless? If yes, it fails. Is the intentional path frictionless? If no, it fails. -This note is a seedling. The full write-up is on its way. +
+How it shows up in the work + +- **Zenborg**: the three-moments-per-phase constraint is friction by design. Adding a fourth requires deliberately removing another. +- **keel**: the intervention model is a tide driving a graduated friction dial, rendered gross to subtle: notice, then a granularity ceiling, then a delay or effort tax, then a single armed backstop. There are no walls. The hard block is kept for one defensible case only, the late-night backstop where the sleep-deprived self cannot self-assess. + +Lineage: Hadash's Decoupling Model, and James Williams on adversarial design that privileges our impulses over our intentions. + +
+ +A budding note. See also [Downstream Allocation](/notes/downstream-allocation) and [Fade-by-Design](/notes/fade-by-design). From 3a62198511dbd253789b791993994f8494da7832 Mon Sep 17 00:00:00 2001 From: "Rafael T. Ballestiero" Date: Wed, 17 Jun 2026 19:39:37 +0200 Subject: [PATCH 09/13] content(notes): rename Glance/Ask/Click reference to Glance, Press, Ask Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/notes/bounded-experiences.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/notes/bounded-experiences.md b/src/content/notes/bounded-experiences.md index c9874d3..45023bc 100644 --- a/src/content/notes/bounded-experiences.md +++ b/src/content/notes/bounded-experiences.md @@ -17,7 +17,7 @@ A principle of the [Awareness layer](/notes/start-here). The opposite of the inf - **Zenborg**: three moments per phase, three days on the timeline, cycles with start and end dates. When you finish placing today's intentions, you are done. There is no next screen. - **Respost**: a card ends with "fim, take your time." No autoplay, no next. -- **Glance / Ask / Click**: Ask terminates, Click terminates. The paradigm is structurally anti-feed. +- **Glance, Press, Ask**: a press terminates, an ask terminates. The paradigm is structurally anti-feed. Evidence: Grüning's 2023 grayscale-screen study found a 22 to 57 minute drop in daily usage when the bottomless pull was dampened. From 28a8076fb0c3b098dce51c1ed5b5006e9f6686bc Mon Sep 17 00:00:00 2001 From: "Rafael T. Ballestiero" Date: Wed, 17 Jun 2026 19:54:51 +0200 Subject: [PATCH 10/13] Decramp homepage: wide structural track, sans footer blurb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The reading column (62ch) was also constraining the structural grids, so §work projects and §framework principles were jammed into a narrow ribbon. Add a --measure-wide (84ch) track for grids and the page shell while prose self-caps to --measure. - main / .section__inner / .footer__inner use --measure-wide - .prose caps the wrapper and bare

intros to 62ch - footer blurb: mono+faint+32ch to sans+muted+46ch (reads as prose, AA) - footer columns rebalanced 1.8/1/1 with wider gap; base line muted - principle number-to-text gap loosened 0.25rem to 0.75rem - align header/body/footer to one spine (was 72/62/72) Co-Authored-By: Claude Opus 4.8 (1M context) --- src/styles/global.css | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/styles/global.css b/src/styles/global.css index 6e230cf..ebe5521 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -62,6 +62,7 @@ /* Layout */ --measure: 62ch; --measure-narrow: 48ch; + --measure-wide: 84ch; /* structural track: grids + page shell breathe wider than prose */ --page-pad-x: clamp(1.25rem, 4vw, 2.5rem); --section-gap: clamp(6rem, 12vh, 10rem); } @@ -132,7 +133,7 @@ h1, h2, h3 { /* Layout */ main { width: 100%; - max-width: 72ch; + max-width: var(--measure-wide); margin-inline: auto; padding-inline: var(--page-pad-x); padding-block: clamp(2rem, 5vw, 3.5rem) var(--section-gap); @@ -150,7 +151,8 @@ main { padding-block-start: calc(var(--section-gap) * 0.5); } -.section__inner { max-width: var(--measure); } +/* Section shell is the wide track; prose self-caps to --measure within it. */ +.section__inner { max-width: var(--measure-wide); } .section__inner--narrow { max-width: var(--measure-narrow); } .eyebrow { @@ -172,7 +174,9 @@ main { flex-shrink: 0; } -.prose p { max-width: var(--measure); } +/* Reading column stays narrow even though the section shell is wide. + .prose caps both the wrapper div and bare

intros. */ +.prose, .prose p { max-width: var(--measure); } .prose p + p { margin-top: 1.25em; } /* Masthead: sticky at top, sits above the hero and the rest */ @@ -334,7 +338,8 @@ main { .principle { display: grid; grid-template-columns: 2.25rem 1fr; - gap: calc(var(--spacing) * 1); + column-gap: calc(var(--spacing) * 3); + row-gap: 0; border-top: 1px solid var(--color-rule); padding-top: calc(var(--spacing) * 4); counter-increment: principle; @@ -483,7 +488,7 @@ main { .footer .row + .row { margin-top: calc(var(--spacing) * 1); } .footer a { color: var(--color-muted); } .footer__inner { - max-width: 72ch; + max-width: var(--measure-wide); margin-inline: auto; padding-inline: var(--page-pad-x); } @@ -494,7 +499,10 @@ main { margin-bottom: calc(var(--spacing) * 10); } @media (min-width: 640px) { - .footer__cols { grid-template-columns: 1.6fr 1fr 1fr; } + .footer__cols { + grid-template-columns: 1.8fr 1fr 1fr; + column-gap: clamp(2rem, 5vw, 4rem); + } } .footer__brand { display: flex; @@ -505,8 +513,11 @@ main { .footer__brand .brand__glyph { width: 1.3em; height: 1.3em; } .footer__brand .wordmark { color: var(--color-muted); } .footer__blurb { - max-width: 32ch; + font-family: var(--font-sans); + color: var(--color-muted); + max-width: 46ch; line-height: 1.6; + letter-spacing: normal; } .footer__head { color: var(--color-muted); @@ -516,7 +527,7 @@ main { } .footer__col p { line-height: 1.7; } .footer__base { - color: var(--color-faint); + color: var(--color-muted); border-top: 1px solid var(--color-rule); padding-top: calc(var(--spacing) * 4); } From cef874098da56372cabe0c485f1b34450c0a6a40 Mon Sep 17 00:00:00 2001 From: "Rafael T. Ballestiero" Date: Wed, 17 Jun 2026 20:11:12 +0200 Subject: [PATCH 11/13] docs(notes): record the evergreen=stamped attestation seam (build deferred) Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/2026-06-17-notes-blog-design.md | 30 ++++++++++++++++++++++++++++ src/content/config.ts | 10 ++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/docs/2026-06-17-notes-blog-design.md b/docs/2026-06-17-notes-blog-design.md index 23fd729..94c8c95 100644 --- a/docs/2026-06-17-notes-blog-design.md +++ b/docs/2026-06-17-notes-blog-design.md @@ -186,6 +186,36 @@ deferred-extracts reference exist). Publish on a cadence; the garden grows. **Substack archive:** the 6 Mindful Cyborg essays are an *optional secondary* import, later — they are chronological-essay shaped and less central than the internal corpus. +## Status and attestation (the seam) + +The `status` field is the garden's one convention, and it maps onto Secretariat's +trust model: + +- **seedling / budding** are *signature-only*. An agent may have drafted them; they + are informational, rough on purpose. +- **evergreen** is *stamped* by the principal (signet, Touch ID). The human vouches. + +Two properties fall out: + +1. Only the principal can mint evergreen. Agents draft seedlings and budding notes; + they never stamp. The top of the ladder requires Rafa's hand on the wheel. This is + "stamped by humans" enforced on the studio's own publishing. +2. The stamp is what keeps the open door safe: rough work is visibly rough, firm work + carries the seal, so everything can be shown without diluting the door's edge. + +This mirrors the crystallization gradient: `Ask -> (cache) -> Press` and +`seedling -> (stamp) -> evergreen` are the same move, paying an effortful act once to +precipitate something durable. + +At bottom this is sovereignty applied to one's own voice: publishing owned outright, +off the rented platform, the status label an honesty with oneself and the stamp simply +meaning it. + +**Build deferred.** Today `status` is an honest frontmatter label, nothing more. When +the first note is firm enough to stamp, build the attestation layer: allow a signet +`$signatures` block through the schema, run `signet verify` at build, render a verified +seal on evergreen notes. Not before. + ## Out of scope (YAGNI — add when needed) Email capture/sending · spaced repetition / Orbit · wikilink syntax · MDX components · diff --git a/src/content/config.ts b/src/content/config.ts index 0a2094e..34db97e 100644 --- a/src/content/config.ts +++ b/src/content/config.ts @@ -8,8 +8,14 @@ const notes = defineCollection({ summary: z.string(), date: z.coerce.date(), tags: z.array(z.string()).optional(), - // Garden maturity. seedling = stub seeded from existing text, room to grow; - // budding = drafted; evergreen = tended and load-bearing. + // Garden maturity, and the attestation seam: + // seedling = rough seeded thinking; budding = drafted. Both are + // signature-only (an agent may have drafted them; informational). + // evergreen = stamped by the principal (signet / Touch ID): the human + // vouches for it. Only Rafa can mint evergreen; agents never stamp. + // Build deferred: today `status` is an honest label. When the first note + // is firm enough to stamp, render a verified seal from its signet + // $signatures block (build-time `signet verify`). Until then, label only. status: z.enum(["evergreen", "budding", "seedling"]).default("budding"), hero: image().optional(), draft: z.boolean().default(false), From 9ecdfca94f4357d3dedb83199fd452a968d9dd82 Mon Sep 17 00:00:00 2001 From: "Rafael T. Ballestiero" Date: Wed, 17 Jun 2026 20:14:33 +0200 Subject: [PATCH 12/13] content(notes): park Glance, Press, Ask ladder as a private seedling (draft) draft:true, so it builds no public page and stays out of the index and RSS until the publish gate is flipped. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/notes/glance-press-ask.md | 44 +++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/content/notes/glance-press-ask.md diff --git a/src/content/notes/glance-press-ask.md b/src/content/notes/glance-press-ask.md new file mode 100644 index 0000000..aa450f1 --- /dev/null +++ b/src/content/notes/glance-press-ask.md @@ -0,0 +1,44 @@ +--- +title: Glance, Press, Ask +summary: Interfaces are not a taxonomy but a gradient. Work descends it as it recurs, from costly chat to cheap ambient glance. +date: 2026-06-17T00:00:00.000Z +status: seedling +draft: true +tags: + - interfaces + - awareness +--- + +A seedling. Scaffolding for a fuller note, parked while it is thought through. + +**Claim.** Interfaces are not a taxonomy, they are a gradient that work descends as it recurs. Each rung down is cheaper, in cognition and in compute, and more frequent than the one above. "Make everything a chatbot" puts the most expensive surface on the most frequent jobs. + +``` + cost frequency + ASK high ^ rare novel / one-off / "do this once" + | | conversation, speech, generative inference + | cache v | + PRESS mid | regular recurring / "do this often" + | | navigation, classic GUI + cached generative UI + | settle v | recognition over recall (masks memory) + v v + GLANCE low constant ambient / "is everything alright?" + observation, sight, status indicators +``` + +- **Ask** (conversation, speech, chat): the new, the rare, the one-off. Highest cognitive overhead and highest cost to run. Generative AI makes it possible, but it is the costly tier. +- **Press** (navigation: classic GUI plus cached generative UI): recurring commands. Recognition over recall, the interface masks memory. When an Ask recurs, you cache the generated UI and it crystallizes into a Press. Generate once, navigate thereafter. +- **Glance** (observation, sight, ambient status): constant background checking. The settled, watched but not touched. + +**The dynamic.** Cost falls and frequency rises as you go down. Work precipitates: Ask, then cache to Press, then settle to Glance. The discipline is to let recurring work fall to cheaper surfaces, not keep re-asking. This is the old rule made automatic: a recurring conversational command is a smell, it means a missing button, and now the engine mints the button. + +**Answers the provocation.** Voice is not a fourth rung; it is a modality of Ask. Chat is where the new lives, not where everything ends up. + +**Worked example.** A notification rides all three: it appears through Glance, is dismissed through Press, is resolved through Ask. + +

+Equanimitech roots + +[Attentional Granularity](/notes/attentional-granularity) at the interface level: match the cost of the surface to the job at hand. [Strategic Friction](/notes/strategic-friction): do not default to the costly path. A sibling of "UI navigates, MCP does the work." + +
\ No newline at end of file From 3954c8e79072369b06334685f13337aab373ef66 Mon Sep 17 00:00:00 2001 From: "Rafael T. Ballestiero" Date: Wed, 17 Jun 2026 20:20:24 +0200 Subject: [PATCH 13/13] content(notes): park garden notes as draft, resume tomorrow Scribe-drafted seedlings kept out of the public build until Rafa rewrites them in his own voice or stamps them (scribe drafts, the seal approves). Reversible; nothing deleted, nothing deployed. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/notes/attentional-granularity.md | 1 + src/content/notes/bounded-experiences.md | 1 + src/content/notes/downstream-allocation.md | 1 + src/content/notes/fade-by-design.md | 1 + src/content/notes/holistic-control.md | 1 + src/content/notes/local-first-ownership.md | 1 + src/content/notes/modification-rights.md | 1 + src/content/notes/peripheral-presence.md | 1 + src/content/notes/start-here.md | 1 + src/content/notes/strategic-friction.md | 1 + 10 files changed, 10 insertions(+) diff --git a/src/content/notes/attentional-granularity.md b/src/content/notes/attentional-granularity.md index 99bae1f..833e5aa 100644 --- a/src/content/notes/attentional-granularity.md +++ b/src/content/notes/attentional-granularity.md @@ -3,6 +3,7 @@ title: Attentional Granularity summary: Content depth should track attentional depth. Start gross, deepen only as focus settles. Gross to subtle, never the reverse. date: 2026-06-17 status: evergreen +draft: true tags: [awareness] --- diff --git a/src/content/notes/bounded-experiences.md b/src/content/notes/bounded-experiences.md index 45023bc..fe588be 100644 --- a/src/content/notes/bounded-experiences.md +++ b/src/content/notes/bounded-experiences.md @@ -3,6 +3,7 @@ title: Bounded Experiences summary: Digital interactions should have natural endpoints. No infinite scroll, no autoplay, no bottomless feed. Stopping is success. date: 2026-06-17 status: budding +draft: true tags: [awareness] --- diff --git a/src/content/notes/downstream-allocation.md b/src/content/notes/downstream-allocation.md index 3bee222..6aeceb2 100644 --- a/src/content/notes/downstream-allocation.md +++ b/src/content/notes/downstream-allocation.md @@ -3,6 +3,7 @@ title: Downstream Allocation summary: The user fills the slots, the system does not. Recommenders are upstream allocators; a whiteboard with magnets is downstream. date: 2026-06-17 status: budding +draft: true tags: [equanimity] --- diff --git a/src/content/notes/fade-by-design.md b/src/content/notes/fade-by-design.md index 9c61776..45fc2a4 100644 --- a/src/content/notes/fade-by-design.md +++ b/src/content/notes/fade-by-design.md @@ -3,6 +3,7 @@ title: Fade-by-Design summary: Success means the user needs the tool less over time, through internalization. Training wheels, not crutches. date: 2026-06-17 status: budding +draft: true tags: [equanimity] --- diff --git a/src/content/notes/holistic-control.md b/src/content/notes/holistic-control.md index 6772716..b226156 100644 --- a/src/content/notes/holistic-control.md +++ b/src/content/notes/holistic-control.md @@ -3,6 +3,7 @@ title: Holistic Control summary: The user controls what features are active and what data flows where. No dark patterns, no forced updates, no locked features. date: 2026-06-17 status: budding +draft: true tags: [sovereignty] --- diff --git a/src/content/notes/local-first-ownership.md b/src/content/notes/local-first-ownership.md index 8f2c042..cb349a1 100644 --- a/src/content/notes/local-first-ownership.md +++ b/src/content/notes/local-first-ownership.md @@ -3,6 +3,7 @@ title: Local-First Ownership summary: The user owns their data and computation. Not "we store it securely for you," the user possesses it. date: 2026-06-17 status: budding +draft: true tags: [sovereignty] --- diff --git a/src/content/notes/modification-rights.md b/src/content/notes/modification-rights.md index 2e83be6..46efccf 100644 --- a/src/content/notes/modification-rights.md +++ b/src/content/notes/modification-rights.md @@ -3,6 +3,7 @@ title: Modification Rights summary: Open source by default. The technically capable can fork or adapt it; the non-technical can freeze it. Both stay in control. date: 2026-06-17 status: budding +draft: true tags: [sovereignty] --- diff --git a/src/content/notes/peripheral-presence.md b/src/content/notes/peripheral-presence.md index 52494f5..df395cb 100644 --- a/src/content/notes/peripheral-presence.md +++ b/src/content/notes/peripheral-presence.md @@ -3,6 +3,7 @@ title: Peripheral Presence summary: Technology should inform without demanding focal attention. You visit it; it does not visit you. Boring by design. date: 2026-06-17 status: budding +draft: true tags: [awareness] --- diff --git a/src/content/notes/start-here.md b/src/content/notes/start-here.md index f3456a1..2f1fec1 100644 --- a/src/content/notes/start-here.md +++ b/src/content/notes/start-here.md @@ -3,6 +3,7 @@ title: Start here summary: An open studio building technology that preserves attention and cultivates equanimity. date: 2026-06-17 status: evergreen +draft: true tags: [framework] --- diff --git a/src/content/notes/strategic-friction.md b/src/content/notes/strategic-friction.md index ddbca27..349b24b 100644 --- a/src/content/notes/strategic-friction.md +++ b/src/content/notes/strategic-friction.md @@ -3,6 +3,7 @@ title: Strategic Friction summary: Make the compulsive path harder and the intentional path easier. Strategic friction is compassionate, not bureaucratic. date: 2026-06-17 status: budding +draft: true tags: [equanimity] ---