diff --git a/apps/web/src/routes/+page.svelte b/apps/web/src/routes/+page.svelte index 5b27911..ea2c8ee 100644 --- a/apps/web/src/routes/+page.svelte +++ b/apps/web/src/routes/+page.svelte @@ -156,7 +156,13 @@ @@ -477,6 +483,20 @@ background: var(--rule); } + /* A squeezed rule between wrapped rows is noise; let it disappear. */ + @media (max-width: 40rem) { + footer .rule { + display: none; + } + } + + footer a { + color: inherit; + display: inline-block; + padding: 0.45rem 0.25rem; + margin: -0.45rem -0.25rem; + } + .valediction { font-style: italic; } diff --git a/docs/NEXT.md b/docs/NEXT.md index 1dad8ab..e5b9c8f 100644 --- a/docs/NEXT.md +++ b/docs/NEXT.md @@ -2,7 +2,7 @@ The flight plan. Each item carries enough context to start cold; update this file whenever an item lands (move it to "Done") or a new one is queued. Decisions made while working an item still go through `decisions/` as usual. -_Last updated: 2026-08-26 (**PRs #27, #28 and #31 are all merged and deployed.** mooring.page now serves the demo-first landing page (PD-10) — verified live: the apex carries the Open Graph card, `/s/jzweifel.dev` renders with the claim banner and `noindex`, and the domain lock, sign-off band and republished `signOff` lexicon from the earlier PRs are all in place. **In flight: the postmark cut-off fix on `claude/signoff-stamp-cutoff-aab504` (below), not yet merged.** The queue below is otherwise current. Critique trends, two separate targets: the rendered **theme** ran 25 → 31 → 29 → 32, and the **landing page** has one run at 21/40 — snapshots in `.impeccable/critique/`)._ +_Last updated: 2026-08-26 (**PRs #27, #28 and #31 are all merged and deployed.** mooring.page now serves the demo-first landing page (PD-10) — verified live: the apex carries the Open Graph card, `/s/jzweifel.dev` renders with the claim banner and `noindex`, and the domain lock, sign-off band and republished `signOff` lexicon from the earlier PRs are all in place. **In flight on `claude/signoff-stamp-cutoff-aab504` (both below, not yet merged): the postmark cut-off fix and the landing footer's attribution row.** The queue below is otherwise current. Critique trends, two separate targets: the rendered **theme** ran 25 → 31 → 29 → 32, and the **landing page** has one run at 21/40 — snapshots in `.impeccable/critique/`)._ ## Where things stand @@ -21,7 +21,7 @@ Done so far: OAuth login (loopback dev client; hosted-client path ready pending 3. *Volume behavior*: every section is an uncapped list — decide caps/pagination ("latest N") before a user with 40 posts finds the missing answer. Posts/writing already honor per-section `limit` in the site record; the question is defaults and UI. 4. *Residual*: no RSS; postcard hero still unexercised by a real record (flip `heroSection.style` on a site record to demo); mono-metadata density (the detector's standing flat-type finding, 10.9–11.5px cluster — deliberate system, revisit only if it keeps bothering reviewers). - **Thin deletion-honoring cache** over the direct PDS reads (ADR 0010 §4) — deliberately reordered below hosting on 2026-08-07: rendering reads live per request, which is correct until there is traffic to cache. The demo-first landing page (PD-10) raises the pressure: the apex now invites uncached live reads for arbitrary handles, so abuse or traffic on the lookup form is the trigger. Revisit once sites are actually served; when it comes up, start from Jetstream v2's snapshot+tail replay (`research/2026-08-14-bluesky-protocol-services.md`) rather than a relay consumer. -- **Landing-page critique follow-ups, design-decision tier** (queued 2026-08-25; snapshot `.impeccable/critique/2026-08-26T01-52-10Z__apps-web-src-routes-page-svelte.md`, scored 21/40 — the three P1s and the mechanical P2s are fixed; what remains needs product calls): gloss or drop "standard.site"/"sifa" jargon for the non-technical launch audience; a pricing signal ("free subdomain" reads as an unpriced paywall); substantiate the ownership claim (source/AGPL/docs link, a human in the footer); accept a pasted DID in the lookup (currently lowercased and rejected as a typo); distinguish resolver outages from typos in the error copy; and the big swing — show a real rendered site on the landing page instead of describing one ("you've built a rendering engine and put a text ad in front of it"). +- **Landing-page critique follow-ups, design-decision tier** (queued 2026-08-25; snapshot `.impeccable/critique/2026-08-26T01-52-10Z__apps-web-src-routes-page-svelte.md`, scored 21/40 — the three P1s and the mechanical P2s are fixed; what remains needs product calls): gloss or drop "standard.site"/"sifa" jargon for the non-technical launch audience; a pricing signal ("free subdomain" reads as an unpriced paywall); accept a pasted DID in the lookup (currently lowercased and rejected as a typo); distinguish resolver outages from typos in the error copy; and the big swing — show a real rendered site on the landing page instead of describing one ("you've built a rendering engine and put a text ad in front of it"). - **Explore extracting themeability, and a second theme — possibly nautical** (queued 2026-08-25, Jacob's hunch): "Mooring" reads as boats to plenty of people before it reads as airships, and the professional-presence theme is currently the only theme, its palette and motifs woven through `SiteLayout`/`SiteSections` rather than sitting behind a seam. Two questions to explore together: (1) what a theme contract would look like (tokens? component set? the `theme.colors` override mechanism already hints at one) and whether extracting it is worth the indirection while there is exactly one theme; (2) whether a harbor/nautical variant (same letter-and-postmark bones, different motif and palette) is a cheap second theme that meets boat-minded visitors where they land. Mock on the design canvas before building; ADR 0008 scope discipline applies — this is exploration, not a committed v1 item. ## Standing / background @@ -34,6 +34,7 @@ Done so far: OAuth login (loopback dev client; hosted-client path ready pending ## Done +- 2026-08-26 — **The landing footer names a human and points at the source** (same branch as the postmark fix; **not merged, not deployed**). Jacob's call: the page asked visitors to trust it with their handle while offering no way to find out who wrote it or read the code. The footer row now reads "Made for the Atmosphere by **Jacob Zweifel**" (→ `jzweifel.dev`, itself a Mooring site, so the byline doubles as a second example) and "**Source on Tangled (AGPL-3.0)**" (→ `tangled.org/jzweifel.dev/fahrenheit`, the canonical URL for the `sh.tangled.repo` record in Jacob's PDS; the GitHub mirror is deliberately not linked — the Atmosphere-native forge is the one that fits the pitch). Link styling and the negative-margin tap padding are lifted from the site theme's own footer, and the connecting rule now hides below 40rem the way the theme's does, so the wrapped three-line stack on a phone has no squeezed rule in it. No new colors: the links inherit `--muted`, which clears 4.5:1 on paper in both schemes (5.05 light, 5.41 dark) and stays underlined. **This closes the "substantiate the ownership claim" clause of the queued landing-critique item** ("you've built a rendering engine and put a text ad in front of it" and the rest still stand). Verified at desktop and 375px. - 2026-08-26 — **The sign-off postmark stopped cutting off long handles** (committed on `claude/signoff-stamp-cutoff-aab504`; **not merged, not deployed**). A new user's site — `timheffley.xyz`, 14 characters — rendered as "TIMHEFFLEY.X…" in the postmark ring. The ring's type was fixed at 0.62rem with `white-space: nowrap` + `text-overflow: ellipsis`, so every handle wider than the ring was guaranteed to truncate; `timheffley.xyz` was simply the first one to cross the line. The handle span now carries `--handle-chars` from `site.handle.length` and sizes itself: `clamp(0.45rem, calc(5.9rem / (0.74 * var(--handle-chars))), 0.62rem)` — the design's size for short handles, shrinking through the middle, floored where the mono type stops being readable, and past the floor `overflow-wrap: anywhere` wraps to a second line instead of truncating. The ellipsis is gone rather than layered over. The arithmetic only works because the ring is monospace (character count *is* text width at ~0.74em per character including tracking); the usable 5.9rem is the 7.5rem diameter less the 2px ring, which `box-sizing: border-box` folds in, and the 0.5rem padding — a first pass at 6.3rem overflowed by 1.4px and wrapped. Verified in a browser against the live render of `/s/timheffley.xyz`: 14 characters on one line inside the ring, `jacobzweifel.bsky.social` (24) and a 31-character DID fallback wrapping to two, none clipped. The landing page's postmark reads a hardcoded `mooring.page` and the OG card is a static PNG, so neither shares the fault. - 2026-08-25 — **The demo-first landing page landed** (PD-10). The apex asks for a handle ("Your site is already written.") and redirects to `/s/[handle]`, resolving the handle server-side so a typo fails inline instead of 404ing; input is normalized (trim, lowercase, leading `@` dropped) by a helper shared with the login action. Every `/s/` preview now renders a claim banner — "This is me — claim it" links to `/login?handle=…` prefilled (deliberately one click, never straight to `authorize()` on GET: prefetchers and crawlers would fire real OAuth flows) — and always carries `noindex`, since the preview path is never the canonical address and unclaimed handles shouldn't rank. The landing page finally wears the site theme (airmail band, warm paper, postmark "par avion"). Found and fixed in verification: the banner needed `color-scheme: dark` so auto-darkening browsers (Chrome's force-dark, default on many Androids) don't invert its hardcoded navy. Banner shows unconditionally on `/s/`, owner or not — revisit if it grates. **Merged as PR #31 and deployed 2026-08-26**, with the critique fixes below in the same deploy; smoke-tested live (apex OG tags, `/s/` preview + banner + `noindex`). - 2026-08-26 — **The landing page took its first critique, and the P1s are fixed** (dual-assessment, 21/40, snapshot in `.impeccable/critique/`; remaining design-decision items are queued above). Copy first, on Jacob's call: em-dash asides removed throughout, and "Own the record" became **"Yours to keep"** — portability as a plain benefit ("leave anytime and everything comes with you"), since the record-ownership framing only sells to protocol-literate readers. Then the three P1s: the lookup form runs through `use:enhance` so the button disables into "Assembling…" and a status line holds through the redirect (the wait for a live PDS read was the page's least-designed moment and the whole demo-first thesis hinges on it); the landing branch emits Open Graph tags against a 1200×630 airmail card at `apps/web/static/og-card.png` (authored as SVG, rasterized with `sharp` — `qlmanage` mangles the scale, and base64-through-the-browser is a context sink); and "Or peek at an example site first" links `/s/jzweifel.dev` so a skeptical visitor sees output before typing their own handle. Mechanical P2s in the same pass: a distinct `--warn` wine for errors with a leading mark, so failure stops wearing the CTA's exact accent red; `aria-invalid`/`aria-describedby` wired and focus kept in the field on a failed submit; 44px controls and a 16px input (iOS zoom-on-focus); input border raised to non-text contrast; the airmail stripe keeps paper-white bands in the dark scheme (they were resolving to `--paper` = `#101520`, degrading the barber pole to generic diagonal stripes); fact titles promoted to real `

`s; the facts joined the entrance rise. Verified live in both schemes at desktop and 375px.