Scroll
Case studyProduct design and design engineering

Imagine AI

Imagine AI drafts, schedules, and measures LinkedIn content for B2B teams. I redesigned the product around the agent at its core, built the design system behind it, and implemented the new front end in React.

Role
Design Engineer (contract)
Company
Imagine AI, YC F25
Timeline
Aug to Oct 2026
Imagine AI redesign: the light and dark Agent home beside Rodin's Thinker
Scope
Audit, information architecture, wireframes, visual design, design system, React front end
Tools
Figma, Next.js, TypeScript, Tailwind CSS v4, shadcn/ui, Motion
6
core surfaces redesigned
9 → 4
primary destinations
1
token file drives light and dark
236
commits, designed and built by me
01/

The starting point

Context

Imagine's agent does real work. It drafts posts in each person's voice, schedules them, drafts replies to comments, and ties engagement back to the CRM. The old interface hid all of that behind a dashboard: the agent lived in an “Ask AI” button in the corner, and the home screen opened on totals with no next step.

What the audit surfaced
  • It looked AI-generated.Saturated default blue on every button and link, generous rounded corners on every card, and cards nested inside cards. That combination is the signature of scaffolded, AI-generated UI. It read as generic SaaS, not as Imagine, and nothing on the screen led the eye.
  • Nine destinations.Customer features sat next to internal tools like Neo4j Analytics and two separate research modes.
  • Numbers without a next step.Team feedback on analytics was blunt: the UI is unclear on “what do I do with this?”
  • Unfinished edges.Destructive actions used the browser's native confirm dialog instead of designed confirmation UI.
The old Imagine AI overview: a navy dashboard of metrics
Before: the Overview. Metrics first, the agent hidden behind “Ask AI.”
The old workspace calendar
Before: Workspace calendar.
The old analytics page
Before: Analytics.
The brand outside the app

Imagine's website, useimagine.ai, speaks in a completely different voice from the old app: Rodin's Thinker, an editorial serif, warm paper tones, and a dusty rose. Signing in felt like switching companies. The redesign closes that gap so the product and the brand feel like the same company.

useimagine.ai hero: Data-Driven Content Motion, with the Thinker statue
useimagine.ai: the Thinker, an editorial serif, and warm neutrals.
useimagine.ai section on targeting the ICP with data
Data shown as editorial figures, with rose as the only accent.
useimagine.ai section: one calendar for the whole team
The site promises one calendar for the whole team.
useimagine.ai section: content filesystem and research
A content filesystem the agent writes from.
useimagine.ai closing call to action over pink clouds
Pink clouds and a serif headline close the page.
02/

Agent first

The reframe

The product is the agent, so the agent should be the home screen. Instead of reading dashboards and deciding what to do, people open Imagine, see what the agent did while they were away, and approve or redirect it in one conversation.

Calendar and analytics stop being destinations you have to interpret. The agent pulls them into the chat as evidence for what it recommends, and they expand into full pages only when you want the detail.

Navigation
Before
  1. Overview
  2. Workspace
  3. Analytics
  4. Neo4j Analytics
  5. Network
  6. Profiles
  7. Simple Research
  8. Deep Research
  9. Settings
After
  1. Agent
  2. Calendar
  3. Analytics
  4. Files

Chats live under the nav. Profiles, integrations, and API keys move into Settings.

Design goals
  • Show the work.Lead with what the agent did and what needs approval.
  • Evidence, not dashboards.Every recommendation comes with the data behind it, and that data has to be accurate and trustworthy.
  • Feel premium.Calm, editorial, and unmistakably not another blue SaaS tool.
03/

Wireframes and iteration

Process

I worked structure first, in greyscale, and saved data and visual decisions until after reviewing the flows with the team. The Agent home went through four versions before it felt like an agent and not a dashboard with a search bar.

Four wireframe versions of the Agent home screen
V1 put a prompt bar over a calendar. V2 added stat tiles and draft cards. V3 turned drafts into an approval queue. V4, the direction I built, is a “While you were away” timeline with bite-size analytics and an Up next rail.
The full wireframe set

Every page and interaction, from sign-in to settings. These fixed layout and behavior; visual polish came later.

Wireframe: sign in
Sign in
Wireframe: onboarding, set up your organization
Onboarding 1: organization
Wireframe: onboarding, invite your team
Onboarding 2: invite the team
Wireframe: onboarding, connect LinkedIn
Onboarding 3: connect LinkedIn
Wireframe: agent landing page
Agent home: while you were away
Wireframe: agent chat
Agent chat
Wireframe: calendar preview inside the chat
Calendar preview in the chat bar
Wireframe: analytics preview inside the chat
Analytics preview in the chat bar
Wireframe: full calendar page with the chat in a sidebar
Calendar page, chat moved to the sidebar
Wireframe: analytics page
Analytics page
Wireframe: file system in a right sidebar
File system in the right sidebar
Wireframe: editing a file in a tab
Editing a file in a tab
Wireframe: settings, profiles
Settings: profiles
Wireframe: settings, integrations
Settings: integrations and CRM
Agent conversation
Wireframe: a full agent conversation with charts, a drafted post, and a scheduled confirmation
A full conversation, top to bottom: the agent answers with a chart, drafts a post that renders like LinkedIn, and confirms the schedule with a calendar graphic.
Analytics wireframes annotated with feedback
Analytics wireframes with the team's feedback pinned beside them: what is performing, what to post next, ICP engagement, and a team leaderboard.
04/

A new surface: Files

Why it exists

The original app had no file system. Everything the agent knew about a company, its positioning, brand voice, campaigns, and each person's persona, was invisible and impossible to edit. You could only see the output, never what it was written from.

Feedback on the first round of wireframes asked for a place for that knowledge, so I designed Files from scratch. If the agent writes from memory, people should be able to read and correct that memory.

How it works
  • Org first, then people.Company files sit at the top: brand voice, posting rules, product notes, campaigns. Each teammate gets their own folder below with a persona and post ideas.
  • Markdown, not forms.Memory is plain markdown files the agent reads and people can edit, so nothing about the agent's context is hidden.
  • Next to the conversation.Files open in a right sidebar beside the chat. Editing one opens a tab next to the conversation, and assets can be dragged straight into a message.
  • Skills alongside files.A Skills tab holds reusable instructions: built-in skills are read-only, and each org can add its own.
Wireframe: file system in a right sidebar next to the chat
Wireframe: files beside the chat, org on top and people below.
Final design: files sidebar next to the agent chat
Final: the same structure with asset thumbnails and drag into chat.
Final design: full Files page
The full Files page with Files and Skills tabs.
Final design: brand voice file open in a tab beside the chat
Editing brand-voice.md in a tab without leaving the conversation.
In production

I then built it into Imagine's production app as Memory, on the workspace filesystem SDK the agent already uses, with a folder tree, list and grid views kept in the URL, upload, new folder, delete with a confirmation, and previews for images, video, and text.

05/

Color

Starting from the brand

Imagine's brand guidelines describe a company that should feel “analytical without becoming mechanical, and human without becoming soft,” built on four values: authority, sharpness, warmth, and precision. Its palette is two families: warm Porcelain, Blush, Dust Rose, and Cloud Grey, and a neutral run from Pietra to Obsidian. None of it is blue.

The old app ignored all of that. LinkedIn is blue, the old app was blue, and almost every tool in the category is blue, so drafts looked like LinkedIn's own chrome and the product looked like a different company from its website. The product palette is the brand palette, tuned to work as an interface.

Imagine brand guidelines: vision page with the Thinker
Brand guidelines: vision.
Imagine brand guidelines: authority, sharpness, warmth, precision
Brand guidelines: values.
Brand palette: Porcelain, Blush, Dust Rose, Cloud Grey
Warm palette: Porcelain #F6F2F2, Blush #F3D7D5, Dust Rose #DDB5BA, Cloud Grey #D8D2DA.
Brand palette: Pietra, Shadow, Cobble, Obsidian
Neutral palette: Pietra #E6E6E6, Shadow #B4B4B4, Cobble #383838, Obsidian #0A0A0A.
Brand to product
BrandProduct tokenWhy it changed
Porcelain #F6F2F2→Background #F4F2F0Shifted from pink-tinted to neutral warm paper, so the rose accent is the only pink on screen.
Dust Rose #DDB5BA→Accent #D4707CDust Rose is 1.66:1 on Porcelain, too faint for a selected state or a chart bar. Deepened to 3.28:1 on white surfaces, past WCAG's 3:1 for UI graphics.
Blush #F3D7D5→Rose washes, 8 to 18%Kept as tint: selection gradients, the scheduled-post chip, the onboarding panel.
Cobble #383838→Primary #3D3A38Warmed slightly to sit with Porcelain. Carries every primary action.
Obsidian #0A0A0A→Foreground #161516Softened from pure black for long reading, still 16.3:1.
Wireframe with the rose accent applied
First step after the wireframes: the same layout with rose applied sparingly. It set the ceiling for how much pink any screen gets.
Exploring within it

Inside the brand's range there were still real choices: how much rose, how warm the greys, what dark mode should be. I explored thirteen palettes, then tested the strongest ones on the same real screen before choosing.

Palette: rose and ink
Palette: sand and ink
Palette: sand and graphite
Palette: rose and deep rose
Palette: plum dark
Palette: warm neutral dark
Palette explorations: rose and ink, sand and ink, sand and graphite, deep rose, plum dark, warm neutral dark.
Relationship screen in a sand palette
Relationship screen in a light palette with charcoal actions
Relationship screen with rose actions
Relationship screen in warm dark
Relationship screen in plum dark
Relationship screen in a cool light palette

Same screen, six palettes. A real layout shows what a swatch card can't: how much accent a dense screen can actually hold.

Chosen palette direction, light
The chosen direction, light.
Chosen palette direction, dark
The chosen direction, dark.
Final palette: light
Background
#F4F2F0
Warm paper. The page and the sidebar it rounds into.
Surface
#FFFFFF
Border
#EAE5E3
Foreground
#161516
16.3:1 on background.
Muted
#6B6661
Primary
#3D3A38
Charcoal for primary actions.
Accent
#D4707C
Dusty rose for selection, status, and data.
Final palette: dark
Chrome
#231F1E
Warmer, lighter charcoal for the sidebar.
Page
#151515
Raised
#36312F
Foreground
#FFFFFF
Muted
#908D8C
Primary
#5C5754
Accent
#E0838D
Lifted rose, 6.8:1 on the page.
Post status
Scheduled
#D4707C
Published
#AFD173
In review
#20A3CD
Draft
#F0BD2E
Calendar event
#825E8A
Why these choices
  • Rose instead of blue.It comes straight from the brand's Dust Rose. It stands apart in a category of blues and reads warm and human, which is the point of a product about real people's voices. Keeping it desaturated keeps it premium rather than playful.
  • Sharper corners, too.The old UI rounded everything heavily, which added to the generated look. The new system uses three small radii, 6px for controls, 12px for panels, and 20px for the outer surface, so shapes feel precise, matching the brand's sharpness without turning cold.
  • Pink is a signal, not a surface.White on rose measures 3.28:1, below WCAG AA for text, so primary buttons are charcoal at 10.1:1. Rose is reserved for selection, the scheduled day, status, and charts, so when it appears, it means something.
  • Warm neutrals, not cool greys.Imagine is a writing tool. Paper tones make the workspace feel like a page rather than a console, and they sit naturally next to the rose.
  • Dark mode is its own palette.The sidebar is a warmer, lighter charcoal and the page sits darker, so the chrome recedes and body text can be pure white. Rose lifts to #E0838D to hold up on dark, and elevation comes from an inset highlight because drop shadows disappear on black.
  • Status colors tuned in context.Calendar chips use a 16% wash of each status color with a solid rail. Gold replaced a paler yellow because at 16% the yellow read as cream next to rose and blue.
06/

Typography

From the brand

The brand pairs Cardinal Fruit, an editorial serif, for titles with Helvetica Neue for descriptions. That works on a billboard but not in a dense product UI. I tested twelve pairings on real product copy, and my notes became a rule: wide geometric display faces lose legibility below 32px, so keep display type out of the product.

Brand typography: Cardinal Fruit for titles
Brand guide: Cardinal Fruit for titles, Helvetica Neue for descriptions.
Pairing study: Helvetica and Outfit
One of twelve pairings tested, annotated with its tradeoff.
Product UI
Aa
DM Sans

Headings and body, every weight from one family.

One line, sign-in only
Turn what you know into your next post, set in Cardinal Fruit
Cardinal Fruit

A display serif for the first impression, never inside the app.

Display 32/40How can I help with your LinkedIn content today?
Heading 18/26Next two weeks
Body 16/24Six months of running product reviews without a deck.
Caption 12/16Thought leadership
Why these choices
  • Serif at the door, workhorse inside.Cardinal Fruit is beautiful at 97px and unreadable in a 12px calendar chip. It sets one line on the sign-in screen, next to Rodin's Thinker, and never appears in the working UI. Helvetica Neue needs separate web licensing and runs tight at small sizes.
  • One family that holds up small.DM Sans is a low-contrast geometric sans designed for smaller text sizes, with an optical size axis. One family keeps hierarchy in size and weight, and stays crisp from a calendar chip to a 300-word draft.
  • Seven steps, all tokens.The scale lives in the token file and Tailwind's text sizes are folded onto it, so even vendored components follow it.
07/

Design system

One source of truth

Every color, spacing step, radius, control height, and type size lives in one file. It emits CSS variables, and Tailwind's own scales are folded onto them, so p-4, text-sm, and rounded-lg all resolve to tokens. Changing a number there retunes the whole product in both themes. Editing a color anywhere else is a bug.

tokens.ts
// src/styles/tokens.ts: the only place a color is allowed to live
export const colors = {
  light: {
    background: "#f4f2f0",   // warm paper
    surface: "#ffffff",
    border: "#eae5e3",
    foreground: "#161516",
    primary: "#3d3a38",      // charcoal: primary actions
    secondary: "#d4707c",    // rose: selection, status, data
  },
  dark: {
    background: "#231f1e",   // warmer chrome
    surface: "#151515",      // darker page, so text can go full white
    primary: "#5c5754",
    secondary: "#d4707c",
    "secondary-strong": "#e0838d",
  },
};

export const radius = { control: 6, panel: 12, surface: 20 };
export const typeScale = {
  display: { size: 32, lineHeight: 40 },
  title:   { size: 24, lineHeight: 32 },
  heading: { size: 18, lineHeight: 26 },
  body:    { size: 16, lineHeight: 24 },
  small:   { size: 14, lineHeight: 20 },
  caption: { size: 12, lineHeight: 16 },
  micro:   { size: 12, lineHeight: 16, letterSpacing: 0.04 },
};
Rules I designed by
  1. No card inside a card. One level of surface, then content.
  2. Controls 6px, panels 12px, surfaces 20px. Nothing sharp-cornered.
  3. No divider lines walling off sections. The sidebar rounds into the page.
  4. No eyebrow labels or filler copy. If a label isn't doing a job, it doesn't ship.
  5. shadcn/ui is the starting point, customized until it no longer reads as shadcn.
  6. Motion is a requirement: shared-element transitions, staggered entrances, tactile press states, and a distinct thinking state for the agent.
The component kit page showing chart components in dark mode
The dev kit: every component in every state, in both themes, before any page is allowed to use it.
08/

The redesign

Before and after

The calendar, old and new, in both themes. Drag the handle to compare. The old version is a blue-accented grid with a chat panel bolted on the side; the new one keeps the agent conversation beside the calendar, colors posts by status, and previews each post the way it will look on LinkedIn.

Old calendar, light modeNew calendar with the agent chat, light modeBeforeAfter
Light mode.
Old calendar, dark modeNew calendar with a post preview and the agent chat, dark modeBeforeAfter
Dark mode.
Onboarding, before and after

The old app had one setup screen: name an organization or paste an invite code. After that it dropped you on a dashboard of zeros, and everything that actually made the product work, inviting teammates and connecting LinkedIn, was left for you to find in Settings and Profiles on your own.

The new onboarding is a guided six-step flow. Each step does one thing, and a live preview of the workspace builds itself on the right as you go, so by the time you land on the agent it already knows your org, your team, and who it posts for.

Before: 1 screen, then find the rest
Old setup screen: create or join an organization
1. The only setup screen: create or join an organization. Recreated from the v1 source.
Old overview dashboard after setup
2. Straight to a metrics dashboard, with no profiles connected yet.
Old settings page with members and invite link
3. To add teammates, dig into Settings for an invite link. Names redacted.
Old profiles page with connect buttons
4. To connect LinkedIn, go to Profiles and add each one by hand. Names redacted.
After: a guided flow
New sign-in
1. Sign in with Google, X, or email.
New onboarding: organization
2. Name the organization and add a logo. The preview fills in as you type.
New onboarding: invite the team
3. Invite teammates by email with a role, or share a link.
New onboarding: connect LinkedIn
4. Connect LinkedIn accounts for yourself, the company page, and anyone you post for.
New onboarding: connected accounts
5. Confirm the connected accounts the agent will draft for.
New onboarding: book a strategy meeting
6. Book a strategy session to tune the agent before the first posts go out.
Landing on the agent home after onboarding
And you land on the agent, already set up for your team.
The new Agent home: While you were away, analytics rail, and the next two weeks
The Agent home. What the agent did while you were away, with approve and edit inline, bite-size analytics, and the next two weeks.
A drafted post rendered as a LinkedIn post inside the chat
Drafts render as real LinkedIn posts in the chat, editable in place, then scheduled with one message.
The agent answering with a bar chart
The agent answers with evidence: charts drawn from the account's own posts.
Calendar preview opened from the chat bar
The calendar previews from the chat bar without leaving the conversation.
A brand voice file open as a tab next to the chat
Brand voice and persona files open as a tab beside the chat.
The new calendar with color-coded post status
Calendar. Status as a pastel wash with a solid rail, the way a calendar app colors events.
The new analytics page
Analytics, with the agent one message away from “what should I post next?”
The files page with org and per-person memory
Files: the org's and each person's memory that the agent writes from.
Onboarding with a live workspace preview
Onboarding builds a live preview of the workspace as you fill it in.
Settings: connected LinkedIn profiles
Settings: profiles, integrations, and API keys moved out of the main navigation.
Dark mode

Both themes resolve from the same tokens through a single switch, so dark mode shipped with every screen rather than as a follow-up.

Sign-in in dark mode
Agent chat in dark mode
Calendar in dark mode
Onboarding in dark mode
09/

I built it, too

Prototype

I implemented the redesign myself in Next.js, TypeScript, Tailwind CSS v4, shadcn/ui, and Motion, on one mock data file shaped exactly like the production Postgres schema. Then I ported it into Imagine's production app through a series of pull requests, and fixed the structure underneath the old UI as I went.

236
commits building the redesign, Sep 5 to 15
100+
commits merged into the production app
14 → 0
pages and layouts shipped as client components
35
shared UI primitives
What was wrong underneath
  • Pages were client components.14 of the old app's 30 pages and layouts started with “use client”. The whole screen shipped to the browser, mounted empty, and then fetched its own data, so every page loaded in two steps.
  • Where you are lived in query parameters.The current organization and the selected LinkedIn profiles were read from ?orgId= and &clientIds= on the client, mirrored into localStorage, and resolved through a 345-line organizations context. Next.js only passes query parameters to pages, never to layouts, so the app shell could not know which org it was in on the server, and every link had to carry both IDs forward by hand.
Where you are, before and after
Before
/overview?orgId=95028e5e-…&clientIds=2d526628-…
/tasks?orgId=95028e5e-…&clientIds=2d526628-…
/analytics?orgId=95028e5e-…&clientIds=2d526628-…
After
/v2/[orgId]/agent
/v2/[orgId]/calendar?view=month&date=2026-09-01
/v2/[orgId]/calendar/post/[postId]
/v2/[orgId]/memory/[[...path]]
What I changed
  • The org moved into the path./v2/[orgId] replaced ?orgId=. The workspace layout is now an async Server Component that reads the org from params, checks membership once per request, redirects non-members, and passes the org and user down as props. Switching orgs is a link.
  • Server first, client islands only.Every v2 page and layout is a Server Component. Client code is limited to leaf islands that need the browser: collapse, sheets, forms, motion, and the chat runtime. None of them fetch on mount.
  • State the server can read.The calendar range lives in ?view=&date= so the server fetches exactly that window, and each post opens at its own route with tabs kept in the calendar layout. Links replace setState calls that rewrote query strings.
  • I held my own prototype to the same bar.The redesign was built fast, so I didn't copy it as-is. Its 690-line sidebar, driven by eleven props, became compound parts that read the route and collapse state from context, and its rows became real links that prefetch and open in a new tab. Mock providers that only let a screen pretend to save were replaced by entity server actions, and animation code that could never run under the app's motion setup was deleted.
  • A port, not a rewrite.I upgraded the platform first (Tailwind CSS v4, React 19), moved the old UI under its own route group so it kept serving production, and landed v2 beside it screen by screen: the workspace shell, settings, a real-time calendar editor on Liveblocks, the agent chat on the existing assistant-ui runtime, and Memory on the workspace filesystem SDK.
Suzanne 3D project preview
Suzanne
Bear Escape project preview
Big Red Hacks 2025 - Bear Escape