diff --git a/HANDOFF.md b/HANDOFF.md index 11e15f9..ab13105 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -1,10 +1,10 @@ -# Handoff: UI polish — feed, login, and shell +# Handoff: threaded reply views ## What this project is Dudesky is a Bluesky client built with TanStack Start (React, SSR, file-based routing). It uses ATProto OAuth to authenticate users via their Bluesky handle. Stack: TanStack Start + Vite, Tailwind CSS v4, `@atproto/oauth-client-node` for OAuth, `better-sqlite3` for persistence. -## What was built last session +## What was built in previous sessions ### Database-backed OAuth stores (`src/lib/db.ts`, `src/lib/oauth-client.ts`) @@ -25,13 +25,18 @@ Uses `createServerFn` (not a raw loader) for all server-only work — `getCookie The server function returns a mapped subset of the feed data (not raw ATProto types) to avoid a type incompatibility with `createServerFn`'s serialization constraints (`{ [x: string]: unknown }` vs `{ [x: string]: {} }`). +### Feed UI polish (`src/routes/feed.tsx`) + +- Cards now use `.island-shell` (frosted glass style) instead of bare `border rounded-lg` +- Outer wrapper uses `bg-[--bg-base]` for the page background color token + ## Current state of key files ``` src/lib/db.ts ← SQLite setup, creates oauth_state + oauth_session tables src/lib/oauth-client.ts ← NodeOAuthClient with DB-backed stateStore + sessionStore src/routes/callback.tsx ← sets DID cookie, redirects to /feed -src/routes/feed.tsx ← createServerFn fetches timeline; basic card UI (needs polish) +src/routes/feed.tsx ← createServerFn fetches timeline; island-shell card UI src/routes/login.tsx ← plain unstyled form; working, needs polish src/routes/__root.tsx ← shell with Header + Footer components, devtools, theme init script src/components/Header.tsx ← sticky nav with "Feed" link chip; uses design tokens @@ -39,13 +44,9 @@ src/components/Footer.tsx ← copyright + "Built with TanStack Start" line src/styles.css ← Tailwind v4 + custom design system (see below) ``` -## What needs to be done: UI cleanup - -The auth flow and data loading all work end-to-end. The feed renders but looks rough. The next session is purely visual polish — no logic changes needed. +## Design system -### Design system already in place - -`src/styles.css` has a full set of CSS custom properties and utility classes to use: +`src/styles.css` has a full set of CSS custom properties and utility classes: **Color tokens** (light + dark + `prefers-color-scheme` variants): - `--sea-ink` / `--sea-ink-soft` — primary text colors @@ -66,24 +67,56 @@ The auth flow and data loading all work end-to-end. The feed renders but looks r - `.rise-in` — entrance animation (opacity + translateY, 700ms) - `.feature-card` — card with hover lift +To use design tokens as Tailwind values: `text-[--sea-ink-soft]`, `bg-[--surface]`, `border-[--line]` etc. Tailwind v4 wraps `--` prefixed values in `var()` automatically. + **Fonts**: Manrope (sans body), Fraunces (serif display) -### Specific things to polish +## Remaining UI polish (carry-over) + +These were not finished last session: + +**`src/routes/feed.tsx`:** +- `text-gray-500` on the handle should be `text-[--sea-ink-soft]` (hardcoded color, won't respect dark mode) +- No timestamp — add `createdAt: (item.post.record as { createdAt?: string }).createdAt ?? null` to the mapped return in `getTimeline`, then render it +- No avatar fallback for posts where `author.avatar` is null +- No `pendingComponent` or `errorComponent` on the route + +**`src/routes/login.tsx`:** +- Form has zero styling — needs centered card layout, `.island-shell`, lagoon accent on the button + +**`src/routes/__root.tsx`:** +- Page title is still "TanStack Start Starter" — should be "Dudesky" -**`src/routes/feed.tsx` — the main job:** -- Post cards are bare `border rounded-lg` — should use `.island-shell` and the design token colors -- Avatar images have no fallback for missing avatars -- No timestamp on posts (it's available: `(item.post.record as { createdAt?: string }).createdAt`) -- The feed data shape currently mapped in `getTimeline` only extracts `uri`, `text`, `author.{handle,displayName,avatar}` — if you need `createdAt` or other fields, add them to the mapped return object in the server function -- No loading/pending state (`pendingComponent` on the route) -- No error state (`errorComponent` on the route) +## Next: threaded reply views -**`src/routes/login.tsx` — unstyled:** -- The form (``, `