Promote to main: Feed browser luxury redesign #7

Merged
calcazar merged 49 commits from develop into main 2026-10-20 10:33:01 -06:00
2 changed files with 231 additions and 0 deletions
Showing only changes of commit dfb3590ff4 - Show all commits
+1
View File
@@ -4,6 +4,7 @@ Minnect feed browser. A web app where each person signs in with their own Minnec
- CRM project: Minnect (`9aw9m1ka4`), module **Feed browser**.
- Build contract: `docs/requirements.md` (from `docs/minnect-feed-browser.spec.md` in the Minnect workspace).
- Redesign build contract: `docs/minnect-feed-redesign.spec.md` (copied from the Minnect workspace `docs/`). It covers the feed browser redesign and is the single source for the redesign tasks.
- Stack: Next.js App Router. Route handlers are the same-origin server that holds sessions.
## Rules
+230
View File
@@ -0,0 +1,230 @@
# Minnect feed browser: luxury redesign
A visual and interaction redesign of the feed browser (`frontend-helper`). The functions do not change: sign in, read the home feed, like, comment, publish text, image and video posts, delete your own post, find experts, featured experts, trending minnects. Every screen, style and motion changes.
This file is the build contract for the redesign. The approved mockup is the visual reference: https://claude.ai/artifact/GQFEUeXcNuC2f4k8XcjwuE (boards: Desktop feed, Mobile feed dark, Mobile feed light, Sign in, Color and components, Button styles). Where this file and the mockup disagree, this file wins. The original contract, `docs/minnect-feed-browser.spec.md`, still governs data, sessions, hosts and security.
Approved by Cesar on 2026-10-19.
## Direction
Minnect sells human answers from experts to people making business decisions ("Human Answers for Human Decisions"). The app must look like a luxury business product, not a social network and not a WordPress page.
- Monochrome luxury. Obsidian, graphite and ivory carry the screen. Minnect crimson is the only color.
- Crimson appears only where the person acts or where something is live: Post, like, the new-posts pill, the live dot, the selected featured expert.
- No gold or champagne anywhere. It was tried and rejected as gimmicky.
- Dark mode is the default. Light mode is required and equal in quality.
## Non-goals
- No new Minnect features. No share, no "who liked", no follow, no booking, no profile pages. The Minnect API does not support them (spike `8kr7vfa5n`).
- No general user search. Expert search only (the Finding-9 rule in the original contract).
- No UI framework or component library. Plain CSS in the existing app.
- No change to the session, token or proxy design.
## Design tokens
Define every color as a CSS custom property on the app root, with a light set and a dark set. Components use only the tokens.
| Token | Dark (default) | Light | Use |
|---|---|---|---|
| `--bg` | `#09090B` | `#EFEDE9` | Page canvas |
| `--tile` | `#121215` | `#FBFAF8` | Panels, post cards |
| `--tile-2` | `#19191D` | `#F3F1EE` | Insets, fields, comment bubbles |
| `--tile-3` | `#232328` | `#E8E5E0` | Disabled buttons, skeletons |
| `--line` | `rgba(255,255,255,.07)` | `rgba(26,28,31,.08)` | Hairlines |
| `--line-2` | `rgba(255,255,255,.15)` | `rgba(26,28,31,.16)` | Stronger outlines |
| `--ink` | `#F4F2EE` | `#1A1C1F` | Body text, names |
| `--ink-2` | `#BFBDB8` | `#46484D` | Actions, labels |
| `--ink-3` | `#95938E` | `#686A70` | Time, meta |
| `--accent` | `#C8141C` | `#C8141C` | Crimson, derived from the app's `#EC1C24` |
| `--danger` | `#FF6B70` | `#B3121A` | Delete text |
| `--glass` | `rgba(18,18,21,.72)` | `rgba(251,250,248,.74)` | Frosted surfaces, with `backdrop-filter: blur()` |
Derive the crimson shades with `color-mix()`: highlight 26% white, shadow 30% black, soft fill 88% transparent.
Text contrast: `--ink-3` on `--tile` is at least 4.5:1 in both themes. Do not use a lighter meta color.
## Typography
- Manrope (400 to 800) for everything except titles. Load with `next/font/google`.
- Cormorant Garamond (500, 600, italic 500) for titles only: the feed title, panel titles, featured expert names, sheet titles, and text-only post slides on mobile.
- The wordmark is `MINNECT`, Manrope 800, letter spacing 0.26em.
- Post body: 15px, line height 1.7. Meta: 12.5px.
- Eyebrow labels: 11px, 700, uppercase, letter spacing 0.18em, `--ink-3`.
## Shape
- Panels 18px radius. Post cards 16px. Media and controls 12px. Chips fully round.
- Avatars are hexagons, the same pointy-top shape as the logo: `clip-path: polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%)`, width to height ratio 0.866.
- Avatar sizes: 46 by 53 (posts), 38 by 44 (lists), 30 by 35 (comments). A photo fills the hexagon. Without a photo, initials sit on a dark muted gradient (oxblood, navy, forest, slate, plum, graphite).
## Buttons
Five styles, each with one job. They come from uiverse.io picks and are recolored to the tokens.
| Style | Source | Used for | Behavior |
|---|---|---|---|
| Flip reveal | gharsh11032000 / friendly-turkey-54 | Post (composer) | Face is `--ink` with `--bg` text: "POST" plus a send icon. Hover slides up a crimson panel reading "PUBLISH" plus the send icon. Disabled (nothing to post): solid `--tile-3` face, `--ink-2` text, hover shows "WRITE FIRST". While posting: shows "POSTING", no flip. Never lower its opacity. |
| Circle expand | cssbuttons-io / massive-mayfly-74 | New-posts pill | Glass pill with a crimson circle and up arrow on the left. Hover grows the circle across the pill and turns the text white. |
| Outline fill sweep | yaasiinaxmed / serious-stingray-77 | Category chips, Cancel | 1.5px outline at rest. Hover sweeps an `--ink` fill in from the bottom-right corner and turns the text `--bg`. A selected chip stays filled. |
| Soft depth, rising liquid | shah1345 / spicy-liger-32 | Mobile More sheet rows, Dark/Light switch | Neumorphic raised surface on `--bg`. Hover raises crimson liquid from below and turns the text white. Press shows an inset shadow. |
| Sparkle glow | ilkhoeri / foolish-shrimp-59 | Sign in, mobile new-post button | Crimson radial glow, ten white sparks rising. Sign in only: a folded top-right corner that unfolds on hover, and a hexagon icon that draws its outline and then fills. Mobile new-post: no fold, the plus turns 90 degrees on hover. |
Small icon actions (send comment, delete confirm, play) use the glossy crimson button: a three-stop crimson gradient, a white top highlight, and a light sweep on hover.
Rejected and not to be used: liquid waves (SmookyDev / sharp-stingray-58), generic 3D drop-shadow buttons.
Set `color` on button classes with enough specificity to beat any global `button { color: inherit }` rule. A Post button with ivory text on an ivory face was a real bug in the mockup.
## Desktop and tablet layout
The page is a bento grid that fits the viewport (`height: 100vh`). The page itself never scrolls. Only the feed column scrolls, so the rest of the screen stays in view.
Desktop, 1181px and wider: three columns, `272px | 1fr | 324px`, 14px gaps and padding.
- Left column: an account panel (logo, wordmark, theme toggle, the signed-in person's hex avatar, name and email, "Feed updates live" with a pulsing crimson dot). Below it, the Find experts panel fills the rest of the height and scrolls on its own.
- Center column: the feed panel. Header ("Home feed" in serif, a refresh button), then the composer, then the scrolling list.
- Right column: the Featured experts panel (fixed height), then the Trending minnects panel, which fills the rest and scrolls on its own.
1001 to 1180px: same layout with columns `244px | 1fr | 292px`.
761 to 1000px (tablet): two columns, `1fr | 300px`. The feed spans the full height on the left. The right column stacks the account and search panels (search capped at 250px tall) over the featured and trending panels.
760px and narrower: the mobile layout below.
Use container queries on the app root, not viewport media queries, so the layout follows the space the app actually has.
### Feed list
- Posts are cards in the scrolling list, newest first, with `scroll-snap-type: y proximity`.
- The list fades out at its top and bottom edges with a mask gradient.
- Cards rise in on load (12px, 550ms, staggered 70ms per card).
- A skeleton card with a shimmer sits at the bottom while the next page loads.
- The new-posts pill floats at the top center of the list. Clicking it shows the new posts and scrolls the list to the top smoothly.
### Post card
- Header: hex avatar, name, relative time. The person's own posts show a "YOU" outline badge and a "..." menu: Delete post, then an inline confirm ("Delete this post?", Cancel, Delete).
- Text, then media at 16:9 with a 12px radius. Video shows a frosted round play button and the duration.
- Footer: like (heart and count, crimson when liked, a beat animation on toggle) and comments (icon and count).
- Comments open inside the card: list, "No comments yet" empty state, removed-comment state, and a field with a send button.
### Composer
- Collapsed: a 50px field with the person's avatar and "Share an insight with the feed".
- Focused, or holding text or a file: it expands to about 92px and gains a shadow.
- Toolbar: photo, video, emoji, then a divider, then a bulleted-list button, then the Ctrl + Enter hint and the flip Post button.
- Emoji opens a frosted popover with a grid of 32 frequent emoji. Clicking one inserts it at the end of the text.
- An attached file shows as a row: thumbnail (with a play mark for video), file name, type and size, a crimson upload progress bar, and a remove button. One file per post, as today.
- Ctrl + Enter or Cmd + Enter publishes.
- Formatting (decided by Cesar on 2026-10-19, spike `6lbkotok9` skipped): Minnect posts are plain text, so there is no bold or italic. The bulleted-list button inserts the plain character "• " at the start of the current line (or of each selected line). Nothing else in the post text is changed.
### Featured experts carousel
A compact spotlight that moves on its own. Nobody has to click or swipe. These are celebrity hooks, meant to draw signed-in people into talking to experts.
- Data: `featuredExperts` from `/api/discover`, with photo (`pictureUrl`), display name, byline, rating and review count.
- The center expert is a large hex photo (96px wide on desktop) in a crimson hex frame, over a soft breathing crimson glow.
- Neighbors sit at 70% scale in grayscale. Outer neighbors sit at 48% scale and 45% opacity. Items further out are hidden.
- Every 2.8 seconds the next expert moves to the center with a 1.1s ease.
- Below: the name in serif, the byline, the rating and review count. The caption fades up on each change.
- Progress dots: the active one is a crimson bar. A counter ("3 / 10") sits in the panel header.
- Hover pauses the rotation. `prefers-reduced-motion` stops autoplay.
### Trending minnects
- Cards: 16:9 thumbnail with a dark fade at the bottom, a glass chip with the expert's avatar and name, a small play button, a view count, and an "AUDIO" or "VIDEO" label.
- Under each card, the question, at most two lines.
- Video and audio playback stay as they work today.
### Find experts
- Search field with a focus ring, then category chips (outline fill sweep). The results list shows hex avatars, name, byline and rating.
- Empty state, "no results" state and error state, worded as today.
## Mobile layout
Width 760px and below. One post fills the whole screen at a time, like Instagram.
### Full-screen feed
- A vertical scroller with `scroll-snap-type: y mandatory` and `scroll-snap-stop: always`. Each slide is exactly the viewport height.
- Image and video posts: media fills the slide edge to edge, with dark fades at the top and bottom. Author (hex avatar, name, time, YOU badge) and text (at most three lines) sit over the bottom fade, in white.
- Text-only posts: the text is the hero, in serif at 31px with a crimson opening quote mark, on the page background with a faint crimson glow in the top-left corner. Author sits at the bottom.
- The current slide's content rises in when it snaps into place. Media eases from 104% to 100% scale.
- Double-tapping a slide likes the post (it never unlikes) and plays a large crimson heart burst.
- The person's own posts show the "..." menu (frosted) at the top right, with the same delete confirm.
- After the second post, a featured experts slide: the eyebrow "FEATURED EXPERTS", the title "Ask the people everyone is talking about", the carousel at 156px wide, the caption, dots, and a "Keep scrolling" hint with a nudging chevron.
- The last slide is a loading skeleton while the next page loads.
- A thin crimson progress bar on the right edge shows the position in the loaded feed.
### Top bar
Frosted pills over the feed: logo and wordmark on the left, theme toggle on the right.
### Bottom dock
A frosted bar 16px above the bottom edge. The like and comment buttons act on the post currently on screen.
1. Like: heart and count for the current post. Crimson when liked.
2. Comments: count for the current post. Opens the comments sheet.
3. New post: the sparkle glow button. Opens the composer sheet.
4. More: opens the Discover sheet.
On the featured and loading slides, like and comment are disabled.
### Sheets
All sheets slide up from the bottom (450ms) over a dimmed, slightly blurred backdrop. Tapping the backdrop closes them. Each has a grab handle and a close button.
- Comments: the current post's comments and a field with a send button.
- Composer: the desktop composer as a sheet, titled "New post", with a 150px text area.
- Discover (More): three rows with the soft depth style. Featured experts (a stack of three hex photos and "Robert O'Neill, Mark Moss and 8 more"), Trending minnects, Find experts. Then the Appearance switch: Dark, Light.
- Featured experts, Trending minnects and Find experts each open their panel as an 80% height sheet. The featured carousel grows to 150px wide there.
## Theme
- Dark is the default for a first visit.
- Toggles: the account panel (desktop), the top bar (mobile), the Discover sheet switch.
- Store the choice in `localStorage` (inside try/catch) and apply it before first paint, so there is no flash of the wrong theme.
## Motion
- Standard ease `cubic-bezier(.2,.8,.2,1)`. Menus pop in over 240ms. Sheets slide over 450ms.
- `prefers-reduced-motion: reduce` turns off carousel autoplay, card rise-in, sparks, heart bursts and the light sweep. State changes still happen instantly.
## Accessibility
- Every control is a real `<button>`, `<a>` or `<input>` with a label. Icon-only buttons have `aria-label`.
- The like button uses `aria-pressed` and labels its count. Comments toggles use `aria-expanded`.
- The carousel region is `aria-live="polite"`. The non-center items are `aria-hidden`.
- Visible focus ring on every control, `--ink` colored.
- Touch targets at least 44px on mobile.
## Sign in
- Obsidian page with a faint crimson glow at the top.
- Logo and wordmark, then the eyebrow "MEMBERS", then "Human answers for *human decisions*" in serif, then a short ivory hairline.
- Uppercase labels, 52px fields with a focus ring, and the sparkle glow Sign in button.
- Error text as today.
## Acceptance
The redesign is done when all of these pass, in both themes, at 1440, 1024, 820 and 390px wide:
1. The page never scrolls. Only the feed scrolls on desktop and tablet. Mobile scrolls one post per screen and snaps.
2. Every function in the original contract still works: sign in, read, paging, like and unlike, comments, text, image and video posts, delete own post, expert search and categories, featured experts, trending playback.
3. The featured carousel rotates on its own, pauses on hover, and stops under reduced motion.
4. The mobile dock's like and comment act on the post on screen. Double-tap likes.
5. Each of the five button styles behaves as specified. The Post label is readable in every state.
6. No gold or champagne color is used anywhere.
7. Text contrast meets 4.5:1, checked with the browser's accessibility inspector or Lighthouse on each screen.
8. Typecheck, lint, vitest and `next build` pass.
## Implementation notes
- Keep the data layer (`src/lib/*`, `src/app/api/*`) unchanged. This is a presentation change.
- Replace `src/app/globals.css` with token-based styles. Split it by component if it grows past about 600 lines.
- Add a `HexAvatar` component and replace every avatar with it.
- The mockup source (`Main.dc.html` on the canvas) holds working CSS for every component. Port it, do not copy the canvas runtime.