diff --git a/README.md b/README.md
index 0dd2dff..1bed9ac 100644
--- a/README.md
+++ b/README.md
@@ -6,144 +6,40 @@ Private by default. Works offline. Open source.
---
-## What it's for
+Write a note. When it's about something you meant to do, it comes back later and asks one
+question — *anything come of this?* — with four answers: **Not yet · Add update · Done · Let go.**
-You write things down and then you forget them. Not because you're careless — because a note just
-sits there. Nothing about it ever asks for your attention again.
+No due dates, no streaks, no guilt.
-DailyNote is a normal notes app: open it, write, close it. Nothing to set up, no account, no
-internet needed. But when a note is about something you actually meant to do, it comes back to you
-later and asks one question:
+The ones worth showing people, you can publish to a **Feed** — note by note, afterwards, and only
+if you want to. Nothing is public unless you say so, and writing needs no account at all.
-> **Anything come of this?**
-
-You get four answers. *Not yet.* *Add update.* *Done.* *Let go.*
-
-That's the whole idea. Not reminders, not deadlines, not a streak you'll feel bad about breaking.
-Just a note that shows up again at a sensible moment and gives you an easy way to say what
-happened — including "nothing, and I'm letting it go."
-
-There are no due dates and no overdue badges anywhere in this app. Feeling guilty is the thing we
-are trying to avoid, not the thing we're trying to cause.
-
-## And if you want, you can share
-
-Some of what you write turns out to be worth showing people. A thing you said you'd learn, and
-then did. A project that went somewhere.
-
-So there's a **Feed**. You can publish a note you already wrote, or write a post straight to the
-feed if that's what you feel like. You can read what other people have shared and follow the ones
-worth following.
-
-Two promises about it:
-
-- **Your notes are private and stay that way.** Publishing is something you choose, note by note,
- afterwards. Nothing you write is public unless you say so.
-- **You never have to.** No account is needed to write notes. If you never publish anything, you
- haven't missed out on anything — you just have a notes app, which is the point.
-
-The writing screen never asks who's going to see it. Posting lives on its own tab, behind its own
-composer, and tells you it's public before you type a word.
-
-## What makes it different
-
-Most feeds are full of people saying what they're *about* to do. "I'm going to learn Rust" is easy
-to post and worth nothing.
-
-Here, the thing that shows up in the feed is a **thread**: the original note, plus what actually
-happened to it over time. When one resurfaces six weeks later carrying *"Done — here's what I
-built"*, that's something no other feed has. Follow-through is the whole product, pointed inward
-first and outward second.
-
----
+📖 **[The longer version](docs/about.md)** — the idea, the sharing, accounts, privacy
+· 📐 [What it is, precisely](docs/product.md) · 🔑 [Accounts setup](docs/auth.md)
## Status
-Being built in the open, by one person, part-time. It runs, and it's already usable for notes.
-
-**Two things are honest to say up front:** there's no server yet, so the social side runs against
-local storage with a few sample authors standing in for other people. And syncing between devices
-isn't built, so your notes live on the device that wrote them.
-
-| | Rollout 1 — the notes app | |
-|---|---|---|
-| 0 | Foundations | ✅ done |
-| 1 | A good local notes app | ✅ mostly there |
-| 2 | Capture surfaces — share sheet, URL scheme | — |
-| 3 | Follow-through — the differentiator | 🚧 notes come back; the four-answer card is next |
-| 4 | Accounts and sync | 🚧 sign-in done, sync not |
-| 5 | Import and expansion | — |
-| 6 | Ship | — |
-
-| | Rollout 2 — the social layer ([plan](docs/plan-rollout-2.md)) | |
-|---|---|---|
-| 2.0 | Identity — profiles and handles | ✅ done |
-| 2.1 | Publishing | 🚧 works in the app; public web pages not built |
-| 2.2 | Follows and a chronological feed | ✅ done |
-| 2.3 | Conversation and safety | 🚧 likes, block and report done; comments not |
-| 2.4 | Themes as data, wallpapers | — |
-| 2.5 | Discovery | — |
-
-Full plans: [docs/plan.md](docs/plan.md) · [docs/plan-rollout-2.md](docs/plan-rollout-2.md).
-What the product *is*, as opposed to how it gets built: [docs/product.md](docs/product.md).
-
-## Accounts
-
-You don't need one to write notes. You never will — that isn't a trial, it's the design.
-
-An account is asked for at exactly one moment: when you want to put something where other people
-can read it. There are three ways in, and they all end up at the same account:
-
-- **Google**
-- **A six-digit code by email** — no password, so there's nothing to forget and nothing to leak
-- **Sign in with Apple** — on iOS
-
-Signing out leaves every note exactly where it is. They were never the account's.
-
-Setting this up for your own build takes a few console steps: [docs/auth.md](docs/auth.md).
-
-## Privacy
-
-**This app does not use end-to-end encryption, and the server can read your notes.** Notes are
-encrypted in transit and at rest. Any note can be marked **local-only**, and those never leave your
-device: publishing one is refused in code, and the server schema carries a constraint that makes a
-published local-only note impossible to store at all.
-
-That's a deliberate trade: end-to-end encryption would permanently rule out server-side search. The
-whole server is open source and self-hostable, which is our substitute for "trust us." See
-[ADR 0002](docs/adr/0002-no-end-to-end-encryption.md).
-
-There's also **no integration with Apple Notes or Google Keep**. Neither has an API to build
-against, so it's dropped rather than promised
-([ADR 0003](docs/adr/0003-no-notes-app-integrations.md)).
-
----
+Built in the open, by one person, part-time. Usable for notes today.
-## For developers
+Two things to know before cloning: **there's no server yet**, so the social side runs against local
+storage with a few sample authors standing in for other people, and **there's no sync**, so notes
+live on the device that wrote them.
-### Layout
+**[Rollout 1 — the notes app](docs/plan.md)**
-```
-apps/mobile Expo app (expo-router, NativeWind) MIT
-packages/core pure TS domain logic, no RN, no Supabase MIT
-packages/db Drizzle schema + Postgres migrations AGPL-3.0
-supabase migrations, RLS policies AGPL-3.0
-docs product.md, the rollout plans, auth.md, ADRs
-```
+| ✅ | Foundations · a good local notes app |
+|---|---|
+| 🚧 | Follow-through (notes come back; the four-answer card is next) · accounts (sync is next) |
+| — | Share sheet and URL scheme · import · ship |
-`packages/core` holds hashtag parsing, title derivation, the review scheduler, search ranking and
-feed composition. These are the pieces most likely to have subtle bugs and the most annoying to
-debug through a UI, so they're pure functions with unit tests and no simulator involved.
+**[Rollout 2 — the social layer](docs/plan-rollout-2.md)**
-Two seams worth knowing about:
+| ✅ | Profiles and handles · follows and the feed |
+|---|---|
+| 🚧 | Publishing (works in-app; public web pages not built) · safety (no comments yet) |
+| — | Themes and wallpapers · discovery |
-- **`apps/mobile/src/db/social-repo.ts`** is the entire social storage layer. When there's a real
- server, that one file gets reimplemented over HTTP and nothing else changes.
-- **Feed rules are code, not database policy.** Row-level security answers one question — "is this
- row public" — and following, blocking and ordering are decided in `packages/core/src/social.ts`,
- where they can be tested.
-
-### Getting started
+## Getting started
```bash
npm install
@@ -151,9 +47,8 @@ npm start # Expo dev server
npm run android # or: npm run ios
```
-Requires Node ≥ 20.19.
-
-You'll need a **development build** rather than Expo Go — Google Sign-In is native code:
+Requires Node ≥ 20.19, and a **development build** rather than Expo Go — Google Sign-In is native
+code:
```bash
npx expo prebuild --clean
@@ -161,8 +56,7 @@ npx expo run:android
```
Sign-in needs credentials. Without them the app still launches, still takes notes and still reads
-the feed; it just can't sign anyone in. Copy `apps/mobile/.env.example` to `.env.local` and see
-[docs/auth.md](docs/auth.md).
+the feed. Copy `apps/mobile/.env.example` to `.env.local` and see [docs/auth.md](docs/auth.md).
### Checks
@@ -174,7 +68,27 @@ npm run lint
All three run in CI on every PR.
-### Database
+## Layout
+
+```
+apps/mobile Expo app (expo-router, NativeWind) MIT
+packages/core pure TS domain logic, no RN, no Supabase MIT
+packages/db Drizzle schema + Postgres migrations AGPL-3.0
+supabase migrations, RLS policies AGPL-3.0
+docs about.md, product.md, the plans, auth.md, ADRs
+```
+
+`packages/core` holds hashtag parsing, title derivation, the review scheduler, search ranking and
+feed composition — the pieces most likely to have subtle bugs and the most annoying to debug
+through a UI, so they're pure functions with unit tests and no simulator involved.
+
+Two seams worth knowing about:
+
+- **`apps/mobile/src/db/social-repo.ts`** is the entire social storage layer. When there's a real
+ server, that one file gets reimplemented over HTTP and nothing else changes.
+- **Feed rules are code, not database policy.** Row-level security answers one question — "is this
+ row public" — while following, blocking and ordering are decided in
+ `packages/core/src/social.ts`, where they can be tested.
The app is local-only until sync lands, so nothing here touches Postgres day to day. To work on the
schema, see [supabase/README.md](supabase/README.md).
diff --git a/apps/mobile/src/components/feed-card.tsx b/apps/mobile/src/components/feed-card.tsx
index 9ab8b6f..88eec68 100644
--- a/apps/mobile/src/components/feed-card.tsx
+++ b/apps/mobile/src/components/feed-card.tsx
@@ -80,30 +80,29 @@ export function FeedCard({
const name = item.displayName ?? `@${item.handle}`;
const completed = event === 'followed-through';
+ // Three sibling targets rather than one card with controls nested inside it:
+ // the byline goes to the author, the body goes to the thread, and the like
+ // acts in place. Nesting them made a button inside a button -- invalid on the
+ // web surface, and a screen reader announcing one row as a single control
+ // with mystery children on every platform.
return (
- router.push({ pathname: '/post/[id]', params: { id: item.id } })}
+
-
-
- router.push({ pathname: '/profile/[handle]', params: { handle: item.handle } })
- }
- className="active:opacity-60"
- >
-
-
+
+ router.push({ pathname: '/profile/[handle]', params: { handle: item.handle } })
+ }
+ className="flex-row items-center gap-2.5 active:opacity-60"
+ >
+
@@ -118,22 +117,30 @@ export function FeedCard({
- {completed ? (
-
- ) : null}
-
+ {completed ? : null}
+
- router.push({ pathname: '/post/[id]', params: { id: item.id } })}
+ className="active:opacity-70"
>
- {feedTitle(item)}
-
- {preview.length > 0 ? (
-
- {preview}
+
+ {feedTitle(item)}
- ) : null}
+ {preview.length > 0 ? (
+
+ {preview}
+
+ ) : null}
+
@@ -146,7 +153,7 @@ export function FeedCard({
) : null}
{item.viewCount > 0 ? : null}
-
+
{!last ? : null}
diff --git a/docs/about.md b/docs/about.md
new file mode 100644
index 0000000..1652da9
--- /dev/null
+++ b/docs/about.md
@@ -0,0 +1,94 @@
+# The longer version
+
+The friendly explanation. For what the product *is* as a set of decisions —
+what's in, what's out, and which rules are not up for renegotiation — see
+[product.md](product.md), which is the authoritative one.
+
+## Why a note that comes back
+
+You write things down and then you forget them. Not because you're careless — because a note just
+sits there. Nothing about it ever asks for your attention again.
+
+DailyNote is a normal notes app: open it, write, close it. Nothing to set up, no account, no
+internet needed. But when a note is about something you actually meant to do, it comes back to you
+later and asks one question:
+
+> **Anything come of this?**
+
+You get four answers. *Not yet.* *Add update.* *Done.* *Let go.*
+
+That's the whole idea. Not reminders, not deadlines, not a streak you'll feel bad about breaking.
+Just a note that shows up again at a sensible moment and gives you an easy way to say what
+happened — including "nothing, and I'm letting it go."
+
+There are no due dates and no overdue badges anywhere in this app. Feeling guilty is the thing we
+are trying to avoid, not the thing we're trying to cause.
+
+The intervals are a loose ladder — **+2d → +7d → +21d → +60d** — and answering *Not yet* pushes it
+along. Tags are inline `#hashtags` parsed out of what you wrote; there's no tag picker. Writing
+`#do` promotes a note to a commitment, the same as tapping **Follow up**.
+
+## The sharing part
+
+Some of what you write turns out to be worth showing people. A thing you said you'd learn, and
+then did. A project that went somewhere.
+
+So there's a **Feed**. You can publish a note you already wrote, or write a post straight to the
+feed if that's what you feel like. You can read what other people have shared, follow the ones
+worth following, and block or report the ones that aren't.
+
+Two promises about it:
+
+- **Your notes are private and stay that way.** Publishing is something you choose, note by note,
+ afterwards. Nothing you write is public unless you say so.
+- **You never have to.** No account is needed to write notes. If you never publish anything, you
+ haven't missed out on anything — you just have a notes app, which is the point.
+
+The writing screen never asks who's going to see it. Posting lives on its own tab, behind its own
+composer, and tells you it's public before you type a word. That separation is structural, not a
+matter of taste — see rules 1 to 3 in [product.md](product.md).
+
+## What makes it different
+
+Most feeds are full of people saying what they're *about* to do. "I'm going to learn Rust" is easy
+to post and worth nothing.
+
+Here, the thing that appears in the feed is a **thread**: the original note, plus what actually
+happened to it over time. Feed order is by last activity rather than by creation date, so a thread
+resurfacing six weeks later carrying *"Done — here's what I built"* comes back to the top. That's
+something no other feed has, and it's why threads were built before publishing was.
+
+Follow-through is the whole product, pointed inward first and outward second.
+
+## Accounts
+
+You don't need one to write notes, and you never will — that isn't a trial tier, it's the design.
+
+An account is asked for at exactly one moment: when you want to put something where other people
+can read it. Three ways in, all landing on the same account:
+
+- **Google**
+- **A six-digit code by email** — no password, so there's nothing to forget and nothing to leak
+- **Sign in with Apple** — on iOS
+
+Your handle is separate from how you signed in, and is never prefilled from it. Pseudonymous
+accounts are allowed on purpose. Signing out leaves every note exactly where it is; they were
+never the account's.
+
+Setting this up for your own build: [auth.md](auth.md).
+
+## Privacy, and the trade behind it
+
+**This app does not use end-to-end encryption, and the server can read your notes.** Notes are
+encrypted in transit and at rest. Any note can be marked **local-only**, and those never leave your
+device: publishing one is refused in code, and the server schema carries a constraint that makes a
+published local-only note impossible to store at all.
+
+That's deliberate. End-to-end encryption would permanently rule out server-side search, which is a
+feature worth more here than a guarantee we'd then have to work around. The whole server is open
+source and self-hostable, which is our substitute for "trust us." The reasoning is written up in
+[ADR 0002](adr/0002-no-end-to-end-encryption.md).
+
+There's also **no integration with Apple Notes or Google Keep**. Neither has an API to build
+against, so it's dropped rather than promised ([ADR 0003](adr/0003-no-notes-app-integrations.md)).
+Capture is the composer, the share sheet, and a `dailynote://` link.