# Thoughts Frontend β€” Frutiger Aero Redesign **Date:** 2026-05-16 **Scope:** `thoughts-frontend` only **Approach:** Component-by-component redesign (B) β€” apply existing FA utilities purposefully, add interaction moments --- ## Summary The thoughts frontend already has the Frutiger Aero foundation (font, CSS utilities, background image, gradients) but almost no components use it. Cards are plain shadcn white. The header is text-only. The landing page is a single minimal card. This redesign applies the aesthetic throughout and adds a layer of subtle, unexpected delight moments modelled on the existing confetti+sound interaction. **Vibe:** "Calm surface, surprise inside." Tasteful Frutiger Aero β€” not maximalist, not flat. One or two playful moments per interaction, short animations (150–450ms), never in the way. --- ## Design Decisions ### 1. Header **Current:** Plain text "Thoughts" + nav links + flat buttons. **Proposed:** - Full glass/blur treatment: `backdrop-filter: blur(16px)`, white highlight border, `box-shadow` with inset top highlight - Logo: glossy rounded-square pill (border-radius: 50% 50% 50% 8px) with πŸ’­ emoji, blue gradient fill, gloss sweep pseudo-element - Logo text: "Thoughts" with white text-shadow - Nav links: subtle opacity treatment, white text-shadow - Search: pill-shaped with translucent background - Login/Register: rounded pill buttons β€” Login is ghost-glass, Register is glossy blue gradient ### 2. Landing Page **Current:** Single centered glass card, h1 "Welcome to Thoughts", two flat buttons. **Proposed:** - Full-screen Aero sky background visible (already provided by `background.avif` + body rule) - Three ambient CSS orbs (blurred radial gradients, `position: absolute`, no images) float in the background - Hero card: deeper glass (`rgba(255,255,255,0.28)` + `backdrop-filter: blur(20px)`), larger border-radius (20px), inset top border highlight, gloss sweep pseudo-element covers top 55% - Heading: larger (text-5xl is fine), stronger text-shadow - CTA buttons: glossy gradient pills β€” Login is blue, Register is green, both with top-half specular highlight pseudo-element - Fediverse badge: small pill below buttons ("Works with Mastodon, Pixelfed & more" + green dot) ### 3. Thought Cards **Current:** Standard shadcn `` β€” white, 8px radius, flat border, grey avatar circle, flat Reply ghost button. **Proposed:** - Body: `rgba(255,255,255,0.72)` + `backdrop-filter: blur(12px)`, 16px border-radius, white highlight border - Gloss sweep: `::before` pseudo covering top 52%, `rgba(255,255,255,0.5) β†’ transparent` - Avatar: gradient fill (blueβ†’teal) with initial letter fallback, `box-shadow: 0 0 0 2px white, 0 0 0 3.5px rgba(59,130,246,0.45)` glow ring - Hover: `transform: translateY(-3px)` + deeper blue-tinted shadow β€” CSS transition, no JS - Reply button: blue-tinted pill (`rgba(37,99,235,0.08)` bg, matching border) instead of flat ghost - Hashtags in content: colored `text-primary` inline - Reply inline form: slides in with `slideDown` keyframe animation (opacity + translateY + max-height), styled as translucent panel ### 4. Sidebar Widgets (PopularTags, TopFriends, UsersCount) All three get the same glass panel treatment as cards. **PopularTags:** - Widget title gets a glossy gradient icon badge (blue, 22px rounded-square) - Tag pills: `rgba(37,99,235,0.08)` bg, branded border, hover scales to 1.05 - Trending tags (top 2 by count): πŸ”₯ prefix + red tint variant **TopFriends:** - Widget title: green gradient icon badge - Avatars: gradient fill with initial letter + glow ring (same pattern as thought cards) - Handle shown beneath display name (`@username` β€” local users only, no full fediverse instance suffix needed) - "following" badge per entry: green-tinted pill **UsersCount β†’ Community widget:** - Widget title: purple gradient icon badge, renamed "Community" - Single glossy stat cell: user count with gradient number text (`background-clip: text`, blueβ†’teal) + "members" label - No new API data required β€” uses existing `getUsersCount` endpoint only ### 5. Interaction Moments **Follow button:** - On click: canvas-based particle burst (14 particles, random angles, brand colors) - Button transitions: blue gradient β†’ green gradient, label "+ Follow" β†’ "βœ“ Following" - Particles: 400ms lifetime, gravity applied **Delete thought:** - On confirm: card plays `shake` keyframe (450ms, Β±4px horizontal + slight rotation) - After shake: `fadeout` keyframe (scale 0.9 + translateY 8px + opacity 0), 300ms - Card removed from DOM after animation **Reply form:** - `slideDown` animation: opacity 0β†’1, translateY -8pxβ†’0, max-height 0β†’120px, 220ms ease-out - Form is styled as translucent panel matching card footer background **Loading skeletons:** - Shimmer gradient updated to use blue/teal palette: `rgba(96,165,250,0.15) β†’ rgba(96,165,250,0.35) β†’ rgba(96,165,250,0.15)` - Avatar skeleton: circular, same shimmer **Empty states:** - Replace plain string with a structured component: floating emoji (CSS `float` keyframe, 2.8s loop), title, subtitle, optional CTA button - Variants per context: πŸ’­ feed empty, πŸ” search no results, 🏷 no tags, πŸ‘₯ no users - CTA is a glossy blue pill button where relevant (e.g. "Discover people ✨" on empty feed) **Post thought (existing):** - Keep confetti + sound as-is β€” it already nails the vibe --- ## Responsive Behaviour - All glass effects degrade gracefully: `backdrop-filter` not supported β†’ `background-opacity` fallback already handled by the rgba values - Cards: full-width on mobile, no sidebar (existing layout already handles this with `hidden lg:block`) - Header: search pill collapses on small screens (existing behaviour kept) - Landing orbs are static (no animation) β€” no motion concern - Empty state floating emoji: `animation: none` on `prefers-reduced-motion` - Skeleton shimmer: `prefers-reduced-motion` β†’ static grey instead of animated - Card hover lift: `transition: none` on `prefers-reduced-motion` --- ## Files Affected | File | Change | |------|--------| | `app/globals.css` | Add `slideDown`, `shake`, `fadeout`, `float`, `shimmer-aero` keyframes; add `.empty-state`, `.widget-icon`, `.orb` utility classes | | `app/layout.tsx` | No change | | `app/page.tsx` | LandingPage: add orbs, deeper glass card, fediverse badge, glossy buttons | | `components/header.tsx` | Add logo bubble, glass treatment, pill buttons | | `components/thought-card.tsx` | Glass body, gradient avatar, hover lift, pill reply button, hashtag color | | `components/thought-form.tsx` | Slide-in animation wrapper when used as reply form | | `components/thought-thread.tsx` | Pass through animation class | | `components/popular-tags.tsx` | Glass widget, icon badge, branded tag pills, trending variant | | `components/top-friends.tsx` | Glass widget, icon badge, gradient avatars, handle + following badge | | `components/users-count.tsx` | Rename to Community widget, 2-col grid, gradient number text | | `components/user-avatar.tsx` | Add gradient fallback + glow ring variant | | `components/empty-state.tsx` | Full redesign: floating emoji, copy, optional CTA | | `components/loading-skeleton.tsx` | Aero shimmer palette, respects prefers-reduced-motion | | `components/follow-button.tsx` | Canvas particle burst on follow/unfollow | | `components/ui/button.tsx` | Add `glossy` variant (pill shape, gradient, gloss pseudo) | | `components/ui/card.tsx` | Add `glass` variant (frosted, gloss sweep) | | `components/ui/badge.tsx` | Add `branded` and `trending` variants | --- ## Out of Scope - Dark mode improvements (existing dark mode kept as-is, no new dark-mode-specific FA treatment) - Shared component library / cross-project unification - New features (likes, bookmarks, etc.) - Portfolio or movies-diary projects