Files
resolutionflow/REBRAND-IMPLEMENTATION-GUIDE.md
Michael Chihlas 653ac50e55 chore: Add rebrand assets, implementation guide, and gitignore local settings
Adds brand-assets/ (SVGs, brand guide) and REBRAND-IMPLEMENTATION-GUIDE.md
as reference docs. Removes .claude/settings.local.json from tracking
(contains local permissions and tokens).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 00:52:03 -05:00

786 lines
24 KiB
Markdown

# 🎨 ResolutionFlow Brand Rebuild - Implementation Guide
## 📋 Pre-Implementation Checklist
**Before starting, complete these safety steps:**
```powershell
cd C:\Dev\Projects\patherly
git add .
git commit -m "Pre-rebrand checkpoint - Patherly working state"
git checkout -b rebrand-to-resolutionflow
```
**Copy brand assets:**
- Place all 8 SVG files in: `C:\Dev\Projects\patherly\brand-assets\`
---
## 🎯 Project Context
**Current State:**
- React + TypeScript + Tailwind CSS project
- Location: `C:\Dev\Projects\patherly\frontend\`
- Using shadcn/ui components
- "Patherly" hardcoded in AppLayout.tsx and LoginPage.tsx
- Default shadcn color scheme (not branded)
- No custom logo/favicon
**Target State:**
- Complete ResolutionFlow branding
- Purple gradient theme (#818cf8#a78bfa)
- Dark mode optimized
- Custom fonts (Plus Jakarta Sans, Inter, Outfit)
- Professional logo in header and favicon
---
## 📦 PHASE 1: Asset Deployment
### 1.1 Create Asset Directories
```bash
mkdir -p frontend/public/icons
mkdir -p frontend/src/assets/brand
```
### 1.2 Copy Brand Assets
Copy files from `C:\Dev\Projects\patherly\brand-assets\` to:
| Source File | Destination |
|------------|-------------|
| `favicon.svg` | `frontend/public/icons/favicon.svg` |
| `icon.svg` | `frontend/public/icons/icon.svg` |
| `app-icon-gradient.svg` | `frontend/public/icons/app-icon-gradient.svg` |
| `logo-horizontal.svg` | `frontend/src/assets/brand/logo-horizontal.svg` |
| `logo-with-tagline.svg` | `frontend/src/assets/brand/logo-with-tagline.svg` |
| `icon.svg` | `frontend/src/assets/brand/icon.svg` |
### 1.3 Update index.html
**File:** `frontend/index.html`
Replace the entire `<head>` section with:
```html
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/icons/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ResolutionFlow - Decision Tree Platform</title>
<meta name="description" content="Transform troubleshooting into guided workflows with automatic documentation" />
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=Inter:wght@400;500;600&family=Outfit:wght@400;500;600;700&display=swap" rel="stylesheet">
<!-- PWA Icons -->
<link rel="apple-touch-icon" href="/icons/app-icon-gradient.svg" />
<meta name="theme-color" content="#09090b" />
<script>
// Prevent flash of wrong theme on initial load
(function() {
try {
const stored = JSON.parse(localStorage.getItem('theme-storage') || '{}');
const theme = stored.state?.theme || 'system';
const isDark = theme === 'dark' ||
(theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches);
if (isDark) document.documentElement.classList.add('dark');
} catch (e) {}
})();
</script>
</head>
```
---
## 🎨 PHASE 2: Tailwind Theme Configuration
### 2.1 Update Tailwind Config
**File:** `frontend/tailwind.config.js`
Replace the entire file with:
```javascript
/** @type {import('tailwindcss').Config} */
export default {
darkMode: ["class"],
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {
colors: {
// ResolutionFlow Brand Colors
brand: {
gradient: {
from: '#818cf8',
to: '#a78bfa',
},
dark: {
DEFAULT: '#09090b',
card: '#18181b',
surface: '#12121c',
},
text: {
primary: '#ffffff',
secondary: '#a1a1aa',
muted: '#52525b',
},
border: '#27272a',
},
// shadcn/ui color system
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
fontFamily: {
sans: ['Inter', 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'sans-serif'],
heading: ['Plus Jakarta Sans', 'system-ui', 'sans-serif'],
label: ['Outfit', 'system-ui', 'sans-serif'],
},
backgroundImage: {
'gradient-brand': 'linear-gradient(90deg, #818cf8 0%, #a78bfa 100%)',
'gradient-brand-hover': 'linear-gradient(90deg, #6366f1 0%, #9333ea 100%)',
},
},
},
plugins: [],
}
```
---
## 🎨 PHASE 3: Global Styles
### 3.1 Update Global CSS
**File:** `frontend/src/index.css`
Replace the entire file with:
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
/* Light mode (fallback) */
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--primary: 243 75% 59%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 243 75% 59%;
--radius: 0.75rem;
}
.dark {
/* ResolutionFlow Dark Theme */
--background: 240 10% 3.9%;
--foreground: 0 0% 100%;
--card: 240 10% 9.4%;
--card-foreground: 0 0% 100%;
--popover: 240 10% 9.4%;
--popover-foreground: 0 0% 100%;
--primary: 243 75% 59%;
--primary-foreground: 0 0% 100%;
--secondary: 240 5.9% 15%;
--secondary-foreground: 0 0% 100%;
--muted: 240 5.9% 15%;
--muted-foreground: 240 5% 64.9%;
--accent: 240 5.9% 15%;
--accent-foreground: 0 0% 100%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 100%;
--border: 240 5.9% 15%;
--input: 240 5.9% 15%;
--ring: 243 75% 59%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
h1, h2, h3, h4, h5, h6 {
font-family: 'Plus Jakarta Sans', system-ui, sans-serif;
font-weight: 700;
letter-spacing: -0.02em;
}
}
@layer utilities {
.text-gradient-brand {
@apply bg-gradient-brand bg-clip-text text-transparent;
}
}
```
---
## 🔧 PHASE 4: Component Updates
### 4.1 Update AppLayout Component
**File:** `frontend/src/components/layout/AppLayout.tsx`
Replace the entire file with:
```typescript
import { Link, useLocation, useNavigate, Outlet } from 'react-router-dom'
import { useAuthStore } from '@/store/authStore'
import { ThemeToggle } from '@/components/common/ThemeToggle'
import { cn } from '@/lib/utils'
export function AppLayout() {
const location = useLocation()
const navigate = useNavigate()
const { user, logout } = useAuthStore()
const handleLogout = async () => {
await logout()
navigate('/login')
}
const navItems = [
{ path: '/trees', label: 'Trees' },
{ path: '/sessions', label: 'Sessions' },
{ path: '/settings', label: 'Settings' },
]
return (
<div className="min-h-screen bg-background">
{/* Header */}
<header className="sticky top-0 z-50 border-b border-border bg-card backdrop-blur-sm">
<div className="container mx-auto flex h-16 items-center justify-between px-4">
<div className="flex items-center gap-8">
<Link to="/trees" className="flex items-center gap-2">
{/* Logo */}
<svg viewBox="0 0 40 40" fill="none" className="h-8 w-8">
<defs>
<linearGradient id="logo-grad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#818cf8"/>
<stop offset="100%" stopColor="#a78bfa"/>
</linearGradient>
</defs>
<circle cx="5" cy="7" r="2.5" fill="url(#logo-grad)" opacity="0.35"/>
<circle cx="5" cy="15" r="2.75" fill="url(#logo-grad)" opacity="0.5"/>
<circle cx="5" cy="25" r="2.75" fill="url(#logo-grad)" opacity="0.5"/>
<circle cx="5" cy="33" r="2.5" fill="url(#logo-grad)" opacity="0.35"/>
<path d="M7.5 7L14 17" stroke="url(#logo-grad)" strokeWidth="1" strokeLinecap="round" strokeDasharray="1 1.5" opacity="0.45"/>
<path d="M7.75 15L14 19" stroke="url(#logo-grad)" strokeWidth="1" strokeLinecap="round" opacity="0.6"/>
<path d="M7.75 25L14 21" stroke="url(#logo-grad)" strokeWidth="1" strokeLinecap="round" opacity="0.6"/>
<path d="M7.5 33L14 23" stroke="url(#logo-grad)" strokeWidth="1" strokeLinecap="round" strokeDasharray="1 1.5" opacity="0.45"/>
<circle cx="18" cy="20" r="5" fill="url(#logo-grad)" opacity="0.15"/>
<circle cx="18" cy="20" r="3.5" fill="url(#logo-grad)"/>
<path d="M21.5 20H35M35 20L30 15M35 20L30 25" stroke="url(#logo-grad)" strokeWidth="1.25" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
{/* Wordmark */}
<span className="font-heading text-xl font-bold">
<span className="text-foreground">Resolution</span>
<span className="text-gradient-brand">Flow</span>
</span>
</Link>
<nav className="hidden items-center gap-1 sm:flex">
{navItems.map((item) => (
<Link
key={item.path}
to={item.path}
className={cn(
'rounded-md px-3 py-2 text-sm font-medium transition-colors',
location.pathname.startsWith(item.path)
? 'bg-accent text-accent-foreground'
: 'text-muted-foreground hover:bg-accent hover:text-accent-foreground'
)}
>
{item.label}
</Link>
))}
</nav>
</div>
<div className="flex items-center gap-4">
<span className="hidden text-sm text-muted-foreground sm:block">
{user?.name || user?.email}
</span>
<ThemeToggle />
<button
onClick={handleLogout}
className={cn(
'rounded-md px-3 py-1.5 text-sm font-medium',
'text-muted-foreground hover:bg-accent hover:text-accent-foreground'
)}
>
Logout
</button>
</div>
</div>
</header>
{/* Main Content */}
<main>
<Outlet />
</main>
</div>
)
}
export default AppLayout
```
### 4.2 Update LoginPage Component
**File:** `frontend/src/pages/LoginPage.tsx`
Replace the entire file with:
```typescript
import { useState } from 'react'
import { Link, useNavigate, useLocation } from 'react-router-dom'
import { useAuthStore } from '@/store/authStore'
import { cn } from '@/lib/utils'
export function LoginPage() {
const navigate = useNavigate()
const location = useLocation()
const { login, isLoading, error, clearError } = useAuthStore()
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [localError, setLocalError] = useState('')
const from = (location.state as { from?: { pathname: string } })?.from?.pathname || '/trees'
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setLocalError('')
clearError()
if (!email || !password) {
setLocalError('Please enter both email and password')
return
}
try {
await login({ email, password })
navigate(from, { replace: true })
} catch {
// Error is set in the store
}
}
return (
<div className="flex min-h-screen items-center justify-center bg-background px-4">
<div className="w-full max-w-md space-y-8">
{/* Header with Logo */}
<div className="text-center">
<div className="mb-6 flex justify-center">
<svg viewBox="0 0 80 80" fill="none" className="h-20 w-20">
<defs>
<linearGradient id="login-logo-grad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#818cf8"/>
<stop offset="100%" stopColor="#a78bfa"/>
</linearGradient>
</defs>
<circle cx="10" cy="14" r="5" fill="url(#login-logo-grad)" opacity="0.35"/>
<circle cx="10" cy="30" r="5.5" fill="url(#login-logo-grad)" opacity="0.5"/>
<circle cx="10" cy="50" r="5.5" fill="url(#login-logo-grad)" opacity="0.5"/>
<circle cx="10" cy="66" r="5" fill="url(#login-logo-grad)" opacity="0.35"/>
<path d="M15 14L28 34" stroke="url(#login-logo-grad)" strokeWidth="2" strokeLinecap="round" strokeDasharray="2 3" opacity="0.45"/>
<path d="M15.5 30L28 38" stroke="url(#login-logo-grad)" strokeWidth="2" strokeLinecap="round" opacity="0.6"/>
<path d="M15.5 50L28 42" stroke="url(#login-logo-grad)" strokeWidth="2" strokeLinecap="round" opacity="0.6"/>
<path d="M15 66L28 46" stroke="url(#login-logo-grad)" strokeWidth="2" strokeLinecap="round" strokeDasharray="2 3" opacity="0.45"/>
<circle cx="36" cy="40" r="10" fill="url(#login-logo-grad)" opacity="0.15"/>
<circle cx="36" cy="40" r="7" fill="url(#login-logo-grad)"/>
<path d="M43 40H70M70 40L60 30M70 40L60 50" stroke="url(#login-logo-grad)" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</div>
<h1 className="font-heading text-3xl font-bold tracking-tight">
<span className="text-foreground">Resolution</span>
<span className="text-gradient-brand">Flow</span>
</h1>
<p className="mt-3 text-lg text-gradient-brand font-medium">
Decision Tree Platform
</p>
<p className="mt-2 text-sm text-muted-foreground">
Sign in to your account
</p>
</div>
<form onSubmit={handleSubmit} className="mt-8 space-y-6">
<div className="space-y-4 rounded-lg border border-border bg-card p-6 shadow-lg">
{(error || localError) && (
<div className="rounded-md bg-destructive/10 p-3 text-sm text-destructive border border-destructive/20">
{localError || error}
</div>
)}
<div>
<label htmlFor="email" className="block text-sm font-medium text-foreground mb-1">
Email address
</label>
<input
id="email"
name="email"
type="email"
autoComplete="email"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
className={cn(
'block w-full rounded-md border border-input bg-background px-3 py-2',
'text-foreground placeholder:text-muted-foreground',
'focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20',
'transition-colors'
)}
placeholder="you@example.com"
/>
</div>
<div>
<label htmlFor="password" className="block text-sm font-medium text-foreground mb-1">
Password
</label>
<input
id="password"
name="password"
type="password"
autoComplete="current-password"
required
value={password}
onChange={(e) => setPassword(e.target.value)}
className={cn(
'block w-full rounded-md border border-input bg-background px-3 py-2',
'text-foreground placeholder:text-muted-foreground',
'focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20',
'transition-colors'
)}
placeholder="••••••••••"
/>
</div>
<button
type="submit"
disabled={isLoading}
className={cn(
'w-full rounded-md px-4 py-2.5 text-sm font-semibold text-white',
'bg-gradient-brand hover:bg-gradient-brand-hover',
'focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2',
'disabled:cursor-not-allowed disabled:opacity-50',
'transition-all shadow-lg shadow-primary/20'
)}
>
{isLoading ? 'Signing in...' : 'Sign in'}
</button>
</div>
<p className="text-center text-sm text-muted-foreground">
Don't have an account?{' '}
<Link
to="/register"
className="font-medium text-gradient-brand hover:underline"
>
Register
</Link>
</p>
</form>
</div>
</div>
)
}
export default LoginPage
```
### 4.3 Update RegisterPage Component
**File:** `frontend/src/pages/RegisterPage.tsx`
**Changes needed:**
1. Add the logo SVG before the title (same as LoginPage)
2. Update title to match ResolutionFlow branding
3. Update submit button to use gradient styling
**Find this section:**
```typescript
<div className="text-center">
<h1 className="text-3xl font-bold tracking-tight text-foreground">Patherly</h1>
<p className="mt-2 text-muted-foreground">Create your account</p>
</div>
```
**Replace with:**
```typescript
<div className="text-center">
<div className="mb-6 flex justify-center">
<svg viewBox="0 0 80 80" fill="none" className="h-20 w-20">
<defs>
<linearGradient id="register-logo-grad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#818cf8"/>
<stop offset="100%" stopColor="#a78bfa"/>
</linearGradient>
</defs>
<circle cx="10" cy="14" r="5" fill="url(#register-logo-grad)" opacity="0.35"/>
<circle cx="10" cy="30" r="5.5" fill="url(#register-logo-grad)" opacity="0.5"/>
<circle cx="10" cy="50" r="5.5" fill="url(#register-logo-grad)" opacity="0.5"/>
<circle cx="10" cy="66" r="5" fill="url(#register-logo-grad)" opacity="0.35"/>
<path d="M15 14L28 34" stroke="url(#register-logo-grad)" strokeWidth="2" strokeLinecap="round" strokeDasharray="2 3" opacity="0.45"/>
<path d="M15.5 30L28 38" stroke="url(#register-logo-grad)" strokeWidth="2" strokeLinecap="round" opacity="0.6"/>
<path d="M15.5 50L28 42" stroke="url(#register-logo-grad)" strokeWidth="2" strokeLinecap="round" opacity="0.6"/>
<path d="M15 66L28 46" stroke="url(#register-logo-grad)" strokeWidth="2" strokeLinecap="round" strokeDasharray="2 3" opacity="0.45"/>
<circle cx="36" cy="40" r="10" fill="url(#register-logo-grad)" opacity="0.15"/>
<circle cx="36" cy="40" r="7" fill="url(#register-logo-grad)"/>
<path d="M43 40H70M70 40L60 30M70 40L60 50" stroke="url(#register-logo-grad)" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</div>
<h1 className="font-heading text-3xl font-bold tracking-tight">
<span className="text-foreground">Resolution</span>
<span className="text-gradient-brand">Flow</span>
</h1>
<p className="mt-3 text-lg text-gradient-brand font-medium">
Decision Tree Platform
</p>
<p className="mt-2 text-sm text-muted-foreground">
Create your account
</p>
</div>
```
**Find the submit button:**
```typescript
<button
type="submit"
disabled={isLoading}
className={cn(
'w-full rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground',
// ... rest of classes
)}
>
```
**Replace with:**
```typescript
<button
type="submit"
disabled={isLoading}
className={cn(
'w-full rounded-md px-4 py-2.5 text-sm font-semibold text-white',
'bg-gradient-brand hover:bg-gradient-brand-hover',
'focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2',
'disabled:cursor-not-allowed disabled:opacity-50',
'transition-all shadow-lg shadow-primary/20'
)}
>
```
---
## 🔍 PHASE 5: Search and Replace
Search for any remaining "Patherly" references in the codebase:
**Command to find references:**
```powershell
cd frontend/src
Select-String -Path . -Pattern "Patherly" -Recurse
```
**Replace all instances with "ResolutionFlow"**
Common places to check:
- Page titles
- Comments
- Error messages
- API descriptions
- Console logs
---
## ✅ PHASE 6: Verification Checklist
### 6.1 Start Development Server
```bash
cd frontend
npm run dev
```
### 6.2 Visual Checks
- [ ] **Login Page**
- Logo displays correctly
- ResolutionFlow branding visible
- Purple gradient on submit button
- Fonts loaded (Plus Jakarta Sans for title)
- [ ] **Register Page**
- Matches login page styling
- Logo and branding consistent
- [ ] **App Header**
- Logo in navbar
- "ResolutionFlow" wordmark (Resolution + Flow gradient)
- Navigation items styled correctly
- [ ] **Browser Tab**
- New favicon visible
- Title shows "ResolutionFlow"
- [ ] **Theme Toggle**
- Dark mode works
- Colors look correct in both modes
- Purple gradients visible
- [ ] **Console**
- No errors in browser console
- Fonts loading successfully
### 6.3 Functionality Checks
- [ ] Login works
- [ ] Registration works
- [ ] Navigation works
- [ ] Theme toggle works
- [ ] All existing features preserved
---
## 🎉 Success Criteria
✅ New ResolutionFlow logo in header
✅ Purple gradient theme throughout
✅ Custom fonts loaded (Plus Jakarta Sans, Inter, Outfit)
✅ No "Patherly" references remaining
✅ Favicon updated in browser tab
✅ Login/Register pages fully branded
✅ Dark mode optimized
✅ All existing functionality preserved
---
## 📝 Post-Implementation
### Commit Changes
```powershell
git add .
git commit -m "Complete rebrand to ResolutionFlow - new logo, colors, fonts, and branding"
git push origin rebrand-to-resolutionflow
```
### Create Pull Request
Review the changes and merge into main when ready.
---
## 🆘 Rollback Plan
If something goes wrong:
```powershell
git checkout main
git branch -D rebrand-to-resolutionflow
```
This will discard all changes and return to your pre-rebrand state.
---
## 📋 Known Issues & Solutions
### Issue: Fonts Not Loading
**Solution:** Clear browser cache and hard refresh (Ctrl+Shift+R)
### Issue: Logo Not Showing
**Solution:** Check that SVG files were copied to correct directories
### Issue: Gradient Not Visible
**Solution:** Verify Tailwind config was updated and dev server was restarted
### Issue: Dark Mode Colors Wrong
**Solution:** Check that index.css was fully replaced with new CSS variables
---
## 🔗 Reference Files
- Brand Guide: `brand-assets/brand-guide.html`
- App Mockups: `brand-assets/app-mockups.html`
- Original Assets: `brand-assets/*.svg`
---
**Last Updated:** February 2026
**Version:** 1.0
**Status:** Ready for Implementation