| Issue | Current State | Impact |
|---|---|---|
| Information Overload | 14+ cards on homepage, 4 dense sections | Users don't know where to focus |
| Repetitive Layouts | Same card design repeated throughout | Visually monotonous, no hierarchy |
| Unclear Navigation | Multiple CTAs ("Register Interest", "Express Interest") | Confusing calls-to-action |
| Dense Text | Small descriptions crammed into cards | Hard to scan/read |
| Abstract Hero Visual | Overlapping circles don't communicate purpose | Missed opportunity to explain the protocol |
| Static Feel | Minimal interaction, basic hover effects | Doesn't feel modern/dynamic |
| Problem | Files Affected | Solution |
|---|---|---|
| 6 Separate Sidebar Components | DocsSidebar.jsx, GovernanceSidebar.jsx, ProtocolSidebar.jsx, LibrarySidebar.jsx, EngageSidebar.jsx, PlatformSidebar.jsx |
Single Sidebar.jsx with config prop |
| Repeated Card Markup | Throughout page.jsx and section pages |
Create Card.jsx, CardGrid.jsx components |
| Duplicated Layout Patterns | 6 different layout.jsx files with similar structure |
Single ContentLayout.jsx component |
| Hardcoded Navigation | SiteHeader.jsx with inline nav items |
Extract to navigation.config.js |
- Clarity First - Every element should have clear purpose
- Progressive Disclosure - Show less upfront, let users explore
- Visual Hierarchy - Clear primary, secondary, tertiary levels
- Responsive by Default - Mobile-first with ultrawide support
- DRY Components - Single source of truth for each pattern
app/components/
├── layout/
│ ├── ContentLayout.jsx # Replaces 6 layout patterns
│ ├── Sidebar.jsx # Unified sidebar (config-driven)
│ └── PageHeader.jsx # Consistent page headers
├── ui/
│ ├── Card.jsx # Base card component
│ ├── CardGrid.jsx # Responsive card grid
│ ├── Button.jsx # Unified button styles
│ ├── Badge.jsx # Status/label badges
│ └── Icon.jsx # Icon wrapper
├── sections/
│ ├── Hero.jsx # Homepage hero
│ ├── FeatureShowcase.jsx # Interactive feature display
│ └── QuickStart.jsx # Getting started section
├── navigation/
│ ├── SiteHeader.jsx # Refactored header
│ ├── MobileMenu.jsx # Mobile navigation drawer
│ └── Breadcrumb.jsx # Page breadcrumbs
└── StickyInterestCta.jsx # Keep (already isolated)
app/config/
├── navigation.js # All nav items, dropdowns
├── sections.js # Sidebar configs per section
└── cards.js # Card content data
Hero → 3 cards → "Navigate" 4 cards → "Components" 4 cards → "Get Involved" 3 cards
Hero (Simplified)
↓
"What is LOOP?" (Visual Explainer)
↓
"Quick Start" (3 clear paths)
↓
"See it in Action" (Interactive Demo Link)
↓
"Get Involved" (Single clear CTA)
Current:
- Long title + subtitle
- Two CTAs side by side
- Abstract circles illustration
- "Express Interest" floating button
New:
- Concise tagline: "Circular Economy Protocol for Cities"
- Single primary CTA: "Explore the Protocol"
- Animated flow diagram showing: MaterialDNA → Offer → Match → Transfer
- Remove redundant floating CTA (keep in footer/nav)
Replace the dense cards with a visual explainer:
<section className="explainer">
<div className="explainer-flow">
<Step icon="leaf" title="MaterialDNA" desc="Tag materials with identity" />
<Arrow />
<Step icon="handshake" title="Match" desc="Find circular opportunities" />
<Arrow />
<Step icon="recycle" title="Transfer" desc="Complete the loop" />
</div>
</section>Three clear user paths instead of 14 cards:
| Path | Target User | Destination |
|---|---|---|
| "I want to understand" | Curious visitors | /protocol |
| "I want to implement" | Developers | /docs |
| "I want to participate" | Organizations | /interest |
- 720px (mobile)
- 960px (tablet)
/* Mobile First */
--bp-sm: 480px; /* Small mobile */
--bp-md: 768px; /* Tablet portrait */
--bp-lg: 1024px; /* Tablet landscape / small desktop */
--bp-xl: 1280px; /* Desktop */
--bp-2xl: 1536px; /* Large desktop */
--bp-ultra: 1920px; /* Ultrawide */@media (min-width: 1920px) {
:root {
--page-max: 1400px; /* Wider content */
--gutter: 80px; /* More breathing room */
}
.hero-top {
grid-template-columns: 1fr 1fr; /* Equal split */
}
.card-grid {
grid-template-columns: repeat(4, 1fr); /* 4 columns */
}
.content-layout {
grid-template-columns: 280px 1fr; /* Wider sidebar */
}
}@media (max-width: 480px) {
.hero-title {
font-size: clamp(1.75rem, 8vw, 2.5rem);
}
.card-grid {
grid-template-columns: 1fr; /* Stack cards */
gap: 12px;
}
.cta-row {
flex-direction: column;
gap: 12px;
}
}:root {
/* Refined Color Palette */
--ink: #0f172a; /* Darker, more contrast */
--ink-soft: #475569; /* Better secondary text */
--paper: #fafaf9; /* Slightly warmer white */
--surface: #ffffff; /* Card backgrounds */
--mist: #f1f5f9; /* Subtle backgrounds */
/* Accent System */
--accent-primary: #ea580c; /* Vibrant orange */
--accent-secondary: #0d9488; /* Teal */
--accent-tertiary: #eab308; /* Yellow */
/* Spacing Scale */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-6: 24px;
--space-8: 32px;
--space-12: 48px;
--space-16: 64px;
/* Typography Scale */
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 1.875rem;
--text-4xl: 2.25rem;
/* Animation */
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--duration-fast: 150ms;
--duration-normal: 300ms;
--duration-slow: 500ms;
}/* Entrance Animations */
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes scaleIn {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
/* Interaction States */
.card {
transition: transform var(--duration-normal) var(--ease-out),
box-shadow var(--duration-normal) var(--ease-out);
}
.card:hover {
transform: translateY(-6px);
box-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.15);
}
/* Staggered Entrance */
.card-grid > * {
animation: fadeInUp var(--duration-slow) var(--ease-out) backwards;
}
.card-grid > *:nth-child(1) { animation-delay: 0ms; }
.card-grid > *:nth-child(2) { animation-delay: 100ms; }
.card-grid > *:nth-child(3) { animation-delay: 200ms; }
.card-grid > *:nth-child(4) { animation-delay: 300ms; }Each sidebar duplicates the same structure with different content.
app/components/layout/Sidebar.jsx:
export function Sidebar({ section, currentPath }) {
const config = sectionConfigs[section];
return (
<nav className="sidebar">
<h2 className="sidebar-title">{config.title}</h2>
{config.groups.map(group => (
<div key={group.label} className="sidebar-group">
<span className="sidebar-label">{group.label}</span>
<ul className="sidebar-links">
{group.links.map(link => (
<li key={link.href}>
<Link
href={link.href}
className={currentPath === link.href ? 'active' : ''}
>
{link.label}
</Link>
</li>
))}
</ul>
</div>
))}
</nav>
);
}app/config/sections.js:
export const sectionConfigs = {
docs: {
title: 'Documentation',
groups: [
{
label: 'Getting Started',
links: [
{ href: '/docs', label: 'Overview' },
{ href: '/docs/quickstart', label: 'Quick Start' },
// ...
]
},
// ...
]
},
protocol: { /* ... */ },
governance: { /* ... */ },
// ...
};app/components/ui/Card.jsx:
export function Card({
icon,
title,
description,
href,
variant = 'default',
size = 'md'
}) {
const Component = href ? Link : 'div';
return (
<Component
href={href}
className={`card card--${variant} card--${size}`}
>
{icon && (
<div className="card-icon">
<Icon name={icon} />
</div>
)}
<h3 className="card-title">{title}</h3>
{description && (
<p className="card-description">{description}</p>
)}
{href && (
<span className="card-link">Learn more →</span>
)}
</Component>
);
}app/components/ui/CardGrid.jsx:
export function CardGrid({ children, columns = 'auto' }) {
return (
<div className={`card-grid card-grid--${columns}`}>
{children}
</div>
);
}.card-grid {
display: grid;
gap: var(--space-6);
}
.card-grid--auto {
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.card-grid--2 {
grid-template-columns: repeat(2, 1fr);
}
.card-grid--3 {
grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 768px) {
.card-grid--2,
.card-grid--3 {
grid-template-columns: 1fr;
}
}Replace the current toggle menu with a slide-in drawer:
// MobileMenu.jsx
export function MobileMenu({ isOpen, onClose }) {
return (
<div className={`mobile-menu ${isOpen ? 'is-open' : ''}`}>
<div className="mobile-menu-backdrop" onClick={onClose} />
<nav className="mobile-menu-content">
<button className="mobile-menu-close" onClick={onClose}>
<Icon name="x" />
</button>
{/* Navigation items */}
</nav>
</div>
);
}.mobile-menu {
position: fixed;
inset: 0;
z-index: 100;
pointer-events: none;
}
.mobile-menu.is-open {
pointer-events: auto;
}
.mobile-menu-backdrop {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.5);
opacity: 0;
transition: opacity var(--duration-normal);
}
.mobile-menu.is-open .mobile-menu-backdrop {
opacity: 1;
}
.mobile-menu-content {
position: absolute;
top: 0;
right: 0;
width: min(320px, 85vw);
height: 100%;
background: var(--surface);
transform: translateX(100%);
transition: transform var(--duration-normal) var(--ease-out);
}
.mobile-menu.is-open .mobile-menu-content {
transform: translateX(0);
}Add breadcrumbs for deeper pages:
// Breadcrumb.jsx
export function Breadcrumb({ items }) {
return (
<nav className="breadcrumb" aria-label="Breadcrumb">
<ol>
{items.map((item, i) => (
<li key={item.href}>
{i < items.length - 1 ? (
<Link href={item.href}>{item.label}</Link>
) : (
<span aria-current="page">{item.label}</span>
)}
</li>
))}
</ol>
</nav>
);
}- Create unified component structure
- Extract navigation config
- Build
Sidebar.jsxto replace 6 sidebar components - Build
Card.jsxandCardGrid.jsx - Build
ContentLayout.jsx - Update CSS with new design tokens
Files to create:
app/components/layout/Sidebar.jsxapp/components/layout/ContentLayout.jsxapp/components/ui/Card.jsxapp/components/ui/CardGrid.jsxapp/config/navigation.jsapp/config/sections.js
Files to delete (after migration):
app/docs/components/DocsSidebar.jsxapp/governance/components/GovernanceSidebar.jsxapp/protocol/components/ProtocolSidebar.jsxapp/library/components/LibrarySidebar.jsxapp/(engage)/components/EngageSidebar.jsxapp/(platform)/components/PlatformSidebar.jsx
- Simplify hero section
- Create visual protocol explainer
- Implement "Quick Start" paths (3 cards max)
- Add interactive demo section
- Streamline CTAs
Files to modify:
app/page.jsx(major rewrite)public/assets/css/site.css(hero styles)
- Add ultrawide breakpoint
- Improve mobile navigation (drawer)
- Test/fix tablet layouts
- Add responsive typography scale
Files to modify:
public/assets/css/site.css(media queries)app/components/SiteHeader.jsxapp/components/navigation/MobileMenu.jsx(new)
- Add scroll-triggered animations
- Implement staggered card entrances
- Add micro-interactions (buttons, links)
- Optimize performance (lazy loading)
Files to modify:
public/assets/css/site.css(animations)public/assets/js/main.js(scroll observers)
| Metric | Current | Target |
|---|---|---|
| Homepage cards | 14 | 3-4 |
| Sidebar components | 6 | 1 |
| CSS file size | 1,346 lines | ~1,000 lines |
| Breakpoints | 2 | 6 |
| Time to first meaningful paint | TBD | < 1.5s |
| Lighthouse accessibility | TBD | > 95 |
| Priority | File | Action |
|---|---|---|
| 1 | app/components/layout/Sidebar.jsx |
CREATE |
| 1 | app/components/layout/ContentLayout.jsx |
CREATE |
| 1 | app/components/ui/Card.jsx |
CREATE |
| 1 | app/components/ui/CardGrid.jsx |
CREATE |
| 1 | app/config/sections.js |
CREATE |
| 1 | app/config/navigation.js |
CREATE |
| 2 | app/page.jsx |
REWRITE |
| 2 | public/assets/css/site.css |
MAJOR EDIT |
| 2 | app/components/SiteHeader.jsx |
REFACTOR |
| 3 | app/docs/layout.jsx |
SIMPLIFY (use ContentLayout) |
| 3 | app/protocol/layout.jsx |
SIMPLIFY |
| 3 | app/governance/layout.jsx |
SIMPLIFY |
| 3 | app/library/layout.jsx |
SIMPLIFY |
| 3 | app/(platform)/layout.jsx |
SIMPLIFY |
| 3 | app/(engage)/layout.jsx |
SIMPLIFY |
| 4 | app/docs/components/DocsSidebar.jsx |
DELETE |
| 4 | app/protocol/components/ProtocolSidebar.jsx |
DELETE |
| 4 | app/governance/components/GovernanceSidebar.jsx |
DELETE |
| 4 | app/library/components/LibrarySidebar.jsx |
DELETE |
| 4 | app/(platform)/components/PlatformSidebar.jsx |
DELETE |
| 4 | app/(engage)/components/EngageSidebar.jsx |
DELETE |