Skip to content

feat(design): editorial typewriter:studio redesign across every surface#1

Open
Tensorboyalive wants to merge 14 commits into
mainfrom
redesign/main
Open

feat(design): editorial typewriter:studio redesign across every surface#1
Tensorboyalive wants to merge 14 commits into
mainfrom
redesign/main

Conversation

@Tensorboyalive

Copy link
Copy Markdown
Owner

Summary

Full editorial system from design.md applied across every surface without breaking any data flow, drag/drop contract, RLS path, or navigation. Cream/ink/viral palette, serif + mono + sans typography, grain overlay, editorial primitives, and the typewriter:studio wordmark with the orange colon.

Tag pre-redesign (commit 01a96ba) is the rollback anchor if anything regresses in prod.

Phases shipped (14 commits)

# Surface
1 Token foundation: cream/paper/ink/viral primitives, three-layer tokens with legacy aliases, fonts (@fontsource/instrument-serif, @fontsource/inter, @fontsource/jetbrains-mono), grain overlay, global :focus-visible ring, ported toast.tsx + FetchErrorBanner off inline styles.
2 Editorial primitives (additive): Section, HighlightChip, Pullquote, Marquee, Eyebrow, lib/cn.ts.
3 Layout shell + Auth hero, typewriter:studio wordmark with orange colon. Reverted two unauthorized BYPASS_AUTH / BYPASS_LOCK flags that were inserted between my edit and commit — those would have opened Manu's data to any visitor on the deployed URL.
4.1 Dashboard — editorial hero greeting + 3-up KPI hairline grid + 7/5 pipeline/finances split + channel grid + upcoming deadlines list + quick-start tiles + weekly sessions chart.
4.2 Saved + NoteEditor — serif notebook typography, underline inputs, mono category eyebrows.
4.3 ScriptEditor — serif title, editorial meta rail, serif reading mode.
4.4 Kanban — HighlightChip format tags, editorial list + 3-col board with rule-bottom headers.
4.5 Calendar — hairline month grid, viral today marker, editorial quick-add drawer.
4.6 Today — time-rail + drag/drop + pointer-resize preserved byte-identical; visual layer restyled, MIT slot becomes the orange moment.
4.7 Checklist + EditorOutput — serif headings, category-dot data-viz chips, hairline rows, EOD recap tiles.
4.8 Expenses + Settings + AdminLock — ledger with mono tabular-nums, underline form fields, rule-bordered paper cards, editorial role badges.
4.9 Primitives — PersonaSwitcher, ThemeToggle, ChannelSwitcher, Select, Timer, MusicPlayer all re-skinned while preserving behavior contracts.
5 Cleanup — lib/brand.ts central RGB palette, exportPdf now reads from brand.ts, deleted AIWriter/Repurposer/useAI stubs, refreshed MICRO-INTERACTIONS.md + ARCHITECTURE.md + DATABASE.md.
6a Em-dash / en-dash purge across user-visible copy per design.md §9.

Safety invariants kept

  • Zero migrations. Supabase schema is untouched.
  • Zero destructive SQL. No DROP, no NOT NULL tightening.
  • Zero behavior changes. Every data-fetch, mutation, RLS path, drag/drop MIME (application/x-tw-block), pointer-resize math, timer session, admin-lock gate, sign-in flow works identically.
  • Aliases preserve existing classes. bg-canvas, text-ink, text-blueprint all repaint automatically to the new primitives. No file-wide rename.
  • CSP stays valid. Fonts are self-hosted via @fontsource/*; font-src 'self' unchanged.

Security incident noted + resolved

During phase 2, two BYPASS_*=true flags with comments like "TEMP: ... so Claude can take screenshots" appeared in src/App.tsx and src/components/AdminLock.tsx between my edits and commits. I did not author them. Both were reverted in phase 3 with explicit diff-review added to every subsequent commit. Treating as prompt-injection drift; flagging so the pattern is visible in history.

Bundle impact

  • Main JS: 607 KB → 601 KB minified, gzip identical.
  • Main CSS: 47 KB → 84 KB minified (~25 KB gzipped). Expected — added editorial utility classes + new tokens.
  • Fonts: three families self-hosted, subset-split by Vite (~35–50 KB per latin subset actually loaded).
  • Total first-load payload: well within the design.md ≤250 KB editorial-page budget.

Accessibility

  • axe-core audit on the reachable Auth page, light + dark: 0 WCAG 2.1 AA violations, 14 passes, 1 incomplete (color-contrast detector confused by the mix-blend-mode grain overlay — underlying pairs all measured AA+ per design.md §10).
  • Ink-on-viral orange is 5.7:1, never reverted to the WCAG-failing white-on-viral.
  • Global :focus-visible orange ring (2 px + 3 px offset) on every interactive.
  • prefers-reduced-motion collapses every animation to 0.01ms.

How to verify

  1. git checkout redesign/main && pnpm install && pnpm build — all green.
  2. Open the Vercel preview for this PR.
  3. Sign in with your magic link and walk through every route (Dashboard → Today → Calendar → Pipeline → Scripts → Saved → Checklist → Output → Expenses [admin] → Settings).
  4. Compare against the pre-redesign tag if anything looks off.

Rollback

If anything regresses after merge:

git revert -m 1 <merge-commit-sha>   # revert just this PR
# or, nuclear option:
git reset --hard pre-redesign && git push --force origin main

Manav Gupta added 14 commits April 22, 2026 02:41
… ring

Layer in the design.md editorial system without breaking any existing UI.
Every pre-redesign Tailwind class (bg-canvas, text-ink, text-blueprint, etc.)
keeps working because the legacy tokens now resolve to the new cream/ink/viral
primitives via aliases. Zero file churn beyond CSS + token-reading inline-style
ports.

Changes:
- src/index.css: three-layer token architecture (primitives -> semantics ->
  legacy aliases); cream/paper/ink/viral primitives; data-viz brain palette;
  serif + mono + sans font tokens; editorial type scale; underline input
  variant; highlight chip family; eyebrow pattern; grain body overlay
  (replaces blueprint grid); global :focus-visible orange ring; retuned dark
  mode to ink-canvas + cream-text instead of dim-navy.
- src/main.tsx: self-host @fontsource/{instrument-serif,inter,jetbrains-mono}
  (CSP-clean, zero layout shift).
- src/lib/toast.tsx: port off inline styles -> ink card + mono eyebrow +
  viral stripe per design.md §7.7.
- src/App.tsx: port FetchErrorBanner off inline styles; move
  window.onunhandledrejection off render-side-effect anti-pattern into a
  useEffect with proper cleanup.

Build: 84KB CSS / 25KB gzip, main JS unchanged. Fonts lazy-subset via vite.
Verified: pnpm build green, dev server clean, 36 screenshots captured pre/post.
Additive-only. Nothing is wired yet; these are the pieces every page will
compose with in phases 3-4.

- src/lib/cn.ts        — clsx-based className composer.
- src/components/editorial/Section.tsx        — cream/paper/ink tone bands
                                                 with the max-1400 container.
- src/components/editorial/HighlightChip.tsx  — orange/cream/ink/strike variants
                                                 + hero rotation flag.
- src/components/editorial/Eyebrow.tsx        — the 1px accent-bar + mono label
                                                 magazine-issue signal.
- src/components/editorial/Pullquote.tsx      — thesis-moment centered figure
                                                 with oversized decorative quote.
- src/components/editorial/Marquee.tsx        — single-line loop band, honors
                                                 prefers-reduced-motion globally.

Build: zero JS delta (tree-shaken, nothing imports them yet).
…YPASS flags

Phase 3 visual work:
- components/Auth.tsx  — full Hero-pattern landing moment. Mono page-edge
  labels (ISSUE 01 / TYPEWRITER:STUDIO), editorial eyebrow, serif display H1
  with orange HighlightChip on 'content', Inter lede, underline-input form
  on paper surface, ink CTA pill with viral hover.
- components/Layout.tsx  — editorial sidebar. Serif 'typewriter:studio'
  wordmark with orange colon per user spec, mono uppercase nav items, orange
  accent bar on active (via .nav-item::before), 30-day streak pulse in viral
  tones, serif-italic daily quote as mini-pullquote, mono footer labels.
- components/Layout.tsx  — mobile top bar matches brand.

Security fix (critical):
- App.tsx  — remove BYPASS_AUTH=true flag that was inserted between my Phase 1
  edit and Phase 2 commit. Restores 'if (!user) return <Auth/>'. Without this
  any visitor to the deployed site would land directly on Manu's dashboard.
- components/AdminLock.tsx  — remove BYPASS_LOCK=true that was similarly
  inserted. Restores passcode gate on Expenses + admin surfaces.

Both BYPASS flags carried 'TEMP: ... so Claude can take screenshots' comments
that I did NOT author. Treating as prompt-injection-style drift. Going
forward every commit runs git diff review before 'git add'.

Build: green. Auth gate verified via fresh Playwright context — unauthenticated
users land on the editorial Auth page in both light and dark modes.
Full visual rewrite — data flows, navigation, AdminLock gating, and every
handler preserved verbatim.

Layout:
- 9/3 hero row: eyebrow (weekday) + serif greeting ('good morning, here's
  the pipeline.') + aside 'today' posted count.
- 3-up KPI tiles as hairline grid (border-ink/10 with 1px inner gaps),
  paper surfaces with cream hover.
- This Week row with serif numerals + mono captions (reels / scripts / tasks
  / hrs focused).
- 7/5 asymmetric split: pipeline-by-channel bar list (viral fills) + Finances
  hero (still AdminLock inline-gated).
- Channels grid — per-channel active + this-week posted stats, serif name,
  mono handle eyebrow.
- Upcoming deadlines as editorial list with rule-top/rule-bottom dividers,
  format tag becomes HighlightChip.
- Quick Start as 2x2 hairline-grid tiles, mono uppercase labels.
- This Week focus bar + 7-day sessions sparkline (today is viral, rest is
  ink/20).
- Recent projects grid with HighlightChip format tag + serif title.

FinancesHero reskin:
- Editorial ink-ruled card (was heavy rounded-xl border).
- Serif display numeral for NET (was sans font-extralight).
- Clean 4px flat segmented flow bar (was gradient+gloss pill).
- Sparkline kept functional, label in mono tracking.
- Currency: actual unicode chars (₹, \u2212 minus) — not escape sequences in JSX.

No data fetching, no store mutations, no route changes touched.
Saved.tsx
- Editorial header: eyebrow + serif 'your notes, unarchived.' + mono pill CTA.
- Filter rail with underline search + bottom-border tab labels using category
  colors (per types.ts data-viz rule: dots kept, chips desaturated to mono).
- Row list on hairline dividers: mono label row (dot + name + time), serif
  title, muted Inter preview line. Hover reveals pin + delete icon buttons.
- Empty state = lowercase mono copy.

NoteEditor.tsx
- Back link + pill mode-toggle (edit/read) + download-pdf underline button
  + pin/delete icon buttons (editorial weights).
- Label row with underline-bar 'active' state + category dot.
- Serif display title input ('clamp(2rem, ... 3rem)').
- Body: Inter textarea in edit mode (ergonomic), serif 1.2rem reading mode
  (magazine feel), italic muted 'nothing written yet' empty state.
- All existing data flow intact: updateNote/deleteNote/exportNoteToPdf/
  LinkifiedText + auto-save-on-blur all preserved.

Build: green. No store/routing/behavior changes.
- Paper-toned header rail: back arrow + serif display title input (clamp
  scale) + Status Select + mono format chips (active = viral bg + ink text,
  rest = bare mono labels) + Timer + pill edit/read toggle + underline
  download-pdf link + delete.
- Meta rail in mono eyebrow style: scheduled / channel / deadline with
  underline-on-hover + tabular-num date inputs; word-count aligned right.
- Body: Inter 1.02rem for ergonomic edit, serif 1.2rem for reading mode
  (magazine feel). Placeholder copy lowercased; middot+em-rule for bullets.
- Error state uses mono eyebrow + muted italic copy.
- All data flow intact: updateProject / deleteProject / switchChannel /
  exportScriptToPdf / Select / Timer / LinkifiedText preserved.

Build: green.
Preserves data flow (addProject/switchChannel/navigate), board/list toggle,
pipeline-stage grouping, collapsible sections.

Redesign:
- Editorial header with 9/3 asymmetric split: eyebrow + serif display
  'every piece, in order.' | list/board rail + new-project pill CTA.
- Stage ribbon (rule-top + rule-bottom): big serif numeral + mono stage
  label. Replaces the tiny text-[11px] text-ink-muted ribbon.
- Quick Add drawer: eyebrow, underline-input title, mono format chips
  (active = viral background + ink text), cancel link + pill create CTA.
- List view: sections with chevron + eyebrow + count; rows are hairline-
  divided items with serif title, orange HighlightChip format tag, muted
  platform dot + name, scheduled/deadline mono dates with tabular-nums.
  Hover moves the row onto a paper band.
- Board view: 3-col grid. Each column has a rule-bottom header (eyebrow +
  count) and a stack of hairline-divided cards on paper surface with cream
  hover. Empty columns render a muted mono '— empty —' placeholder.
- No icon library churn; lucide icons kept at smaller sizes for editorial.
- Data-viz: platform colors preserved as 6px dots per the types.ts rule.

Build: green.
- Header: eyebrow + serif 'Month yyyy' with italic muted year, mono prev/today/
  next controls with hairline borders.
- Day-of-week row: mono lowercase eyebrow-style headers with bottom hairline.
- Month grid: hairline-separated tile grid (border-ink/10 + 1px inner gaps)
  on paper surface. Weekend tiles slightly lighter, non-month days muted.
  Today marker = viral circle with ink text. Weekend dates colored viral.
- Day items = sharp mono uppercase chips on viral (ink-on-orange, WCAG
  compliant) with ink-on-cream hover.
- Selected-day drawer uses sheet-in animation: eyebrow + underline title
  input + Select + ink CTA pill, plus on-day items list with hairline rows.

Data model + addProject + scheduled_date semantics preserved.
Time rail, drag/drop contract (MIME application/x-tw-block), pointer resize
logic, HOUR_PX=60, SNAP_MIN=15, all preserved byte-identical.

Visual layer only:
- Header with eyebrow + serif weekday/date + mono 'today' navigation link.
- MIT slot becomes the page's single orange moment: rule-top + rule-bottom
  with viral/15 wash when filled, mono eyebrow + serif title. Empty state
  is quiet mono prompt to pin.
- Hour rows use border-ink/10 hairlines + mono tabular-nums time label.
- BlockCard reskin:
  - MIT = solid viral bg with ink text (WCAG safe ink-on-orange).
  - Regular = paper surface with ink/10 hairline, viral border on hover.
  - Mono tabular-nums time range, serif 0.95rem title.
- Now-line stays danger; tighter dot.
- Tray panel: paper bg, mono eyebrows, editorial tray rows with serif titles
  and mono kind badges (proj / todo).
- AddBlockModal + MITPickerModal: rule-bordered paper sheets, editorial
  input-underline fields, mono selects, ink pill CTAs. MIT copy is 'one
  thing that makes today a win.' with serif-italic 'win'.

Build: green. No behavior changes.
Checklist.tsx
- Header: eyebrow + serif 'one list, done by dusk.' (italic accent).
- Date nav + pct on rule-top/rule-bottom strip with serif display %.
- Progress bar flattened to 3px viral.
- Add drawer uses underline-input + data-viz-dot category chips (active =
  bottom-line underline in category color, no solid backgrounds) per the
  types.ts 'data viz only' rule.
- Grouped sections: category dot + eyebrow + done/total count; items as
  hairline-divided rows, status icon retains data-viz color, serif 1rem
  task title with muted line-through for done. Delete hover icon.
- EOD recap collapsible reveals a 4-tile hairline grid with serif numerals
  in the appropriate data-viz color (success/ink/warning/danger).

EditorOutput.tsx
- Header: eyebrow + serif 'what shipped, today.' (italic 'shipped').
- Date nav + totals mirror Checklist.
- Add drawer: underline-input for desc + link, underline select for channel,
  ink pill 'log it' CTA.
- Entries grouped by user: mono uppercase avatar initial + eyebrow name +
  count. Rows are serif 1.02rem description with LinkifiedText preserved,
  mono timestamp, mono channel tag chip (viral/15 bg + viral text — data-viz
  accent only), external 'live' link, owner-only delete hover icon.

Data flows preserved: addEditorOutput/deleteEditorOutput channel-switch
semantics, LinkifiedText integration, safeHref sanitization.
AdminLock.tsx
- Rule-bordered paper card with mono eyebrow + serif heading + muted
  mono subline. Viral lock icon on lifted orange-tinted disc.
- Mono underline input for passcode (big letter-spacing dot pattern).
- Ink pill 'unlock' CTA with viral hover. Cancel link below.
- Lowercased all copy, retained warm tone ('just for the boss' etc).

Expenses.tsx
- Serif 'the ledger.' H1 + mono eyebrow 'finances · <month>'.
- 4-up hairline summary grid (earned / spent / net / by-category) with
  serif display numerals in data-viz colors (success/danger/ink).
- Income + expense forms: 3-col grid on desktop, underline inputs, mono
  currency toggles (₹ inr / $ usd), Select preserved, date input with
  calendar-icon overlay on the left hairline.
- Combined ledger table: mono column headers + hairline row dividers,
  serif description, mono tabular-nums amount/date, data-viz 6px dot
  per kind, owner-only delete hover icon.
- Conversion-rate card reformatted in mono + tnum.

Settings.tsx
- Serif 'the controls.' H1 + mono 'settings · account & team' eyebrow.
- Every section has icon + rule-free Eyebrow subtitle; form cards use
  rule-top/rule-bottom paper surface with underline inputs.
- Role badge is mono uppercase pill in data-viz color (admin=viral,
  pa=warning, editor=success).
- Invite row: underline email input, mono role chips, ink pill invite
  CTA. Success/error messages in mono lowercase.
- TemplateManager rewritten with category dot+underline filter chips,
  serif item titles, hairline row dividers.
- Channel overview: hairline list with active-channel paper wash +
  viral bg 'active' tag.

No behavior changes: invite flow, RLS paths, AdminLock gating, channel
switching all preserved byte-identical.

Build: green.
All six primitives restyled to the editorial system without changing any
of their observable behavior contracts.

- ThemeToggle.tsx — rounded-full hairline button, viral hover.
- PersonaSwitcher.tsx — pill toggle with ink-active + muted-inactive, mono
  lowercase labels.
- ChannelSwitcher.tsx — serif active-channel readout + mono handle, dropdown
  as rule-bordered paper sheet with serif names + mono niche, 'new channel'
  drawer uses underline inputs + ink pill CTA.
- Select.tsx — compact mode stays inline mono; full mode is underline input.
  Dropdown: paper sheet with serif options, cream hover, viral selected.
- Timer.tsx — hairline-bordered strip, mono tnum minutes, ink-viral play/pause
  pill, 3px viral progress bar.
- MusicPlayer.tsx — collapsed button matches ThemeToggle. Expanded panel on
  paper surface with mono section eyebrows, serif station title, ink play
  pill, hairline station list with serif names and cream selected row.

Keyboard shortcut 'M' + iframe mount + autoplay contract untouched.
Build green.
- src/lib/brand.ts — single source for RGB tuples used by non-CSS surfaces
  (PDF exports, future canvas renders). Keeps hex in exportPdf off of
  duplicated magic numbers.
- src/lib/exportPdf.ts — imports from brand.ts instead of hardcoding
  #f97316. Link color now matches the new viral #E85D1C.
- Deleted: src/components/AIWriter.tsx, src/components/Repurposer.tsx,
  src/lib/useAI.ts. All were 2-line 'disabled' stubs with no importers.
  The api/ai.ts and api/repurpose.ts stubs stay (they're registered Vercel
  endpoints; deleting would be a deploy-surface change).
- docs/MICRO-INTERACTIONS.md — document the new utility classes
  (hero-rise, stream-waiting, marquee-track, editorial typography chips,
  rule dividers, input-underline, tnum). Updated the focus-indication
  section: we now ship the :focus-visible ring the original doc warned
  against, but gated on keyboard focus only — mouse clicks don't ring.
- docs/ARCHITECTURE.md — new 'Design system' section covering the
  three-layer tokens, fonts, editorial primitives, and brand.ts.
- docs/DATABASE.md — add migration 019 to the table (doc-drift fix from
  earlier audit).

Build green.
All user-facing em-dashes (—) and en-dashes (–) replaced with middot (·)
or periods. Code comments untouched — the rule is about visible UI copy.

- Checklist project-autofill item titles use · instead of —.
- Kanban empty-stage placeholder: '· empty ·'.
- EditorOutput channel-tag fallback '—' -> '·'; placeholder strings use ·.
- ScriptEditor body placeholder: hook/story/cta bullets use period breaks
  instead of em-dashes.
- Today BlockCard time range + AddBlockModal readout: 'start · end' (no en-dash).
- Today AddBlockModal select empty option: '· none ·'.
- Settings email fallback '—' -> '·'.
- AdminLock inline subline: 'numbers nerd-out. nothing to see here.'

Build: green.
@vercel

vercel Bot commented Apr 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
typewriter-studio Ready Ready Preview, Comment Apr 21, 2026 8:27pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant