A calm place to write long-form, and publish it to the open social web. skypress.blog/
0

Configure Feed

Select the types of activity you want to include in your feed.

Add design doc: focus reading pages on publication & author

+100
+100
docs/superpowers/specs/2026-06-09-reading-page-author-focus-design.md
··· 1 + # Reading-page author focus — design 2 + 3 + **Date:** 2026-06-09 4 + **Status:** Approved 5 + 6 + ## Problem 7 + 8 + The reading pages (publication index and single post) lead with SkyPress's own 9 + identity — the SkyPress logo + wordmark in the header. For readers, the focus should 10 + be on the *publication* and its *author*, not on the platform. 11 + 12 + ## Goals 13 + 14 + 1. Publication page: drop the SkyPress header entirely. 15 + 2. Single post page: replace the SkyPress logo/title in the header with the 16 + **publication** logo + title. 17 + 3. Single post page: replace the publication name in the `reader__meta` eyebrow with 18 + the **author's** name, avatar, and handle. 19 + 4. Both pages: render dates in a long, human format (e.g. "June 9, 2026"). 20 + 21 + ## Non-goals 22 + 23 + - No client-side JavaScript on the reading pages (they stay server-only — see 24 + AGENTS.md hard constraint #3). 25 + - No locale negotiation: the UI is English, so dates render in a fixed 26 + `en-US` long format. ("Controlled by the browser" was considered and dropped in 27 + favour of a simpler, JS-free fixed format.) 28 + - No changes to the writer profile page, RSS feeds, theming, or OG meta. 29 + 30 + ## Design 31 + 32 + ### 1. Shared date helper (new) 33 + 34 + `src/lib/reader/dates.ts` exports a pure function: 35 + 36 + ```ts 37 + export function formatLongDate( iso: string ): string; 38 + ``` 39 + 40 + Implemented with `Intl.DateTimeFormat( 'en-US', { dateStyle: 'long', timeZone: 'UTC' } )`. 41 + 42 + - `timeZone: 'UTC'` pins the rendered day: a `2026-06-09T23:00:00Z` timestamp must not 43 + roll to the 10th (or back to the 8th) depending on the server's local zone. It also 44 + keeps unit tests deterministic. 45 + - Output example: `formatLongDate( '2026-06-09T12:00:00Z' ) === 'June 9, 2026'`. 46 + - Callers keep their own null-handling (`publishedAt ? formatLongDate( publishedAt ) : null`), 47 + so the helper only ever receives a real ISO string. 48 + 49 + ### 2. Publication page — `src/pages/[author]/[slug]/index.astro` 50 + 51 + - Remove the `<header class="masthead"><a href="/"><Logo /></a></header>` block. 52 + - Remove the now-unused `Logo` import and the `.masthead` CSS rules. 53 + - Change the article date mapping from `record.value.publishedAt?.slice( 0, 10 )` to 54 + `record.value.publishedAt ? formatLongDate( record.value.publishedAt ) : null`. 55 + 56 + The publication hero (logo, title, byline, lede) already carries publication + 57 + author identity, so no header is needed. 58 + 59 + ### 3. Single post page — `src/pages/[author]/[slug]/[rkey].astro` 60 + 61 + **Data.** Add `fetchActorProfile` (mirroring the publication page) so the author's 62 + `displayName` and `avatar` are available. Compute: 63 + 64 + - `authorName = profile.displayName ?? \`@${ handle }\`` 65 + - publication `logoUrl` via `buildGetBlobUrl( pdsUrl, did, publication.icon.ref.$link )` 66 + when `publication.icon` exists, else `null`; `initial = publication.name.charAt(0).toUpperCase()`. 67 + 68 + **Header.** Replace `<a href="/"><Logo /></a>` with a link to `pubUrl` 69 + (`/@handle/slug`) containing the publication logo (or initial-letter fallback) and 70 + the publication title. 71 + 72 + **Eyebrow (`reader__meta`).** Replace the publication-name link with an author block 73 + linking to `/@handle`: 74 + 75 + ``` 76 + [avatar] Author Name @handle · June 9, 2026 · updated June 10, 2026 · 5 min read 77 + ``` 78 + 79 + - Avatar shown only when `profile.avatar` exists. 80 + - When `displayName` is absent, show just `@handle` once (no duplicated handle). 81 + - Date(s) via `formatLongDate`. 82 + 83 + **Cleanup.** Drop the `Logo` import and the `.reader__author` rule (replaced by new 84 + author-block + header styles). 85 + 86 + ### 4. Tests 87 + 88 + - TDD: write `src/lib/reader/dates.test.ts` first — covers the long-format output, 89 + UTC pinning (a late-evening UTC timestamp stays on its calendar day), and a 90 + date-only string. 91 + - Inspect existing colocated `_*.test.ts` for these two pages; update any assertions 92 + that reference the removed masthead or the old `YYYY-MM-DD` date format. 93 + - Gate: `npm run test` and `npm run check` must pass. 94 + 95 + ## Risks / notes 96 + 97 + - Colocated tests under `src/pages/` MUST stay underscore-prefixed (AGENTS.md #8). 98 + - Single post page newly depends on the actor profile fetch; if the profile fetch 99 + fails it should degrade to `@handle` rather than erroring the page (match the 100 + publication page's tolerance).