new ux start
This commit is contained in:
160
components/ui/hero-section-2.tsx
Normal file
160
components/ui/hero-section-2.tsx
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
|
// Icon component for contact details
|
||||||
|
const InfoIcon = ({ type }: { type: 'website' | 'phone' | 'address' }) => {
|
||||||
|
const icons = {
|
||||||
|
website: (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="h-5 w-5 text-primary">
|
||||||
|
<circle cx="12" cy="12" r="10"></circle>
|
||||||
|
<line x1="2" x2="22" y1="12" y2="12"></line>
|
||||||
|
<path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path>
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
phone: (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="h-5 w-5 text-primary">
|
||||||
|
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
address: (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="h-5 w-5 text-primary">
|
||||||
|
<path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z"></path>
|
||||||
|
<circle cx="12" cy="10" r="3"></circle>
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
return <div className="mr-2 flex-shrink-0">{icons[type]}</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Prop types for the HeroSection component
|
||||||
|
interface HeroSectionProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||||
|
logo?: {
|
||||||
|
url: string;
|
||||||
|
alt: string;
|
||||||
|
text?: string;
|
||||||
|
};
|
||||||
|
slogan?: string;
|
||||||
|
title: React.ReactNode;
|
||||||
|
subtitle: string;
|
||||||
|
callToAction: {
|
||||||
|
text: string;
|
||||||
|
href: string;
|
||||||
|
};
|
||||||
|
backgroundImage: string;
|
||||||
|
contactInfo: {
|
||||||
|
website: string;
|
||||||
|
phone: string;
|
||||||
|
address: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const HeroSection = React.forwardRef<HTMLDivElement, HeroSectionProps>(
|
||||||
|
({ className, logo, slogan, title, subtitle, callToAction, backgroundImage, contactInfo, ...props }, ref) => {
|
||||||
|
|
||||||
|
// Animation variants for the container to orchestrate children animations
|
||||||
|
const containerVariants = {
|
||||||
|
hidden: { opacity: 0 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
transition: {
|
||||||
|
staggerChildren: 0.15,
|
||||||
|
delayChildren: 0.2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Animation variants for individual text/UI elements
|
||||||
|
const itemVariants = {
|
||||||
|
hidden: { y: 20, opacity: 0 },
|
||||||
|
visible: {
|
||||||
|
y: 0,
|
||||||
|
opacity: 1,
|
||||||
|
transition: {
|
||||||
|
duration: 0.5,
|
||||||
|
ease: "easeOut",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<motion.section
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"relative flex w-full flex-col overflow-hidden bg-background text-foreground md:flex-row",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
initial="hidden"
|
||||||
|
animate="visible"
|
||||||
|
variants={containerVariants}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{/* Left Side: Content */}
|
||||||
|
<div className="flex w-full flex-col justify-between p-8 md:w-1/2 md:p-12 lg:w-3/5 lg:p-16">
|
||||||
|
{/* Top Section: Logo & Main Content */}
|
||||||
|
<div>
|
||||||
|
<motion.header className="mb-12" variants={itemVariants}>
|
||||||
|
{logo && (
|
||||||
|
<div className="flex items-center">
|
||||||
|
<img src={logo.url} alt={logo.alt} className="mr-3 h-8" />
|
||||||
|
<div>
|
||||||
|
{logo.text && <p className="text-lg font-bold text-foreground">{logo.text}</p>}
|
||||||
|
{slogan && <p className="text-xs tracking-wider text-muted-foreground">{slogan}</p>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</motion.header>
|
||||||
|
|
||||||
|
<motion.main variants={containerVariants}>
|
||||||
|
<motion.h1 className="text-4xl font-bold leading-tight text-foreground md:text-5xl" variants={itemVariants}>
|
||||||
|
{title}
|
||||||
|
</motion.h1>
|
||||||
|
<motion.div className="my-6 h-1 w-20 bg-primary" variants={itemVariants}></motion.div>
|
||||||
|
<motion.p className="mb-8 max-w-md text-base text-muted-foreground" variants={itemVariants}>
|
||||||
|
{subtitle}
|
||||||
|
</motion.p>
|
||||||
|
<motion.a href={callToAction.href} className="text-lg font-bold tracking-widest text-primary transition-colors hover:text-primary/80" variants={itemVariants}>
|
||||||
|
{callToAction.text}
|
||||||
|
</motion.a>
|
||||||
|
</motion.main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bottom Section: Footer Info */}
|
||||||
|
<motion.footer className="mt-12 w-full" variants={itemVariants}>
|
||||||
|
<div className="grid grid-cols-1 gap-6 text-xs text-muted-foreground sm:grid-cols-3">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<InfoIcon type="website" />
|
||||||
|
<span>{contactInfo.website}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<InfoIcon type="phone" />
|
||||||
|
<span>{contactInfo.phone}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<InfoIcon type="address" />
|
||||||
|
<span>{contactInfo.address}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right Side: Image with Clip Path Animation */}
|
||||||
|
<motion.div
|
||||||
|
className="w-full min-h-[300px] bg-cover bg-center md:w-1/2 md:min-h-full lg:w-2/5"
|
||||||
|
style={{
|
||||||
|
backgroundImage: `url(${backgroundImage})`,
|
||||||
|
}}
|
||||||
|
initial={{ clipPath: 'polygon(100% 0, 100% 0, 100% 100%, 100% 100%)' }}
|
||||||
|
animate={{ clipPath: 'polygon(25% 0, 100% 0, 100% 100%, 0% 100%)' }}
|
||||||
|
transition={{ duration: 1.2, ease: "circOut" }}
|
||||||
|
>
|
||||||
|
</motion.div>
|
||||||
|
</motion.section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
HeroSection.displayName = "HeroSection";
|
||||||
|
|
||||||
|
export { HeroSection };
|
||||||
300
components/ui/modern-side-bar.tsx
Normal file
300
components/ui/modern-side-bar.tsx
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
"use client";
|
||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import {
|
||||||
|
Home,
|
||||||
|
User,
|
||||||
|
Settings,
|
||||||
|
LogOut,
|
||||||
|
Menu,
|
||||||
|
X,
|
||||||
|
ChevronLeft,
|
||||||
|
ChevronRight,
|
||||||
|
BarChart3,
|
||||||
|
FileText,
|
||||||
|
Bell,
|
||||||
|
Search,
|
||||||
|
HelpCircle
|
||||||
|
} from 'lucide-react';
|
||||||
|
|
||||||
|
interface NavigationItem {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
icon: React.ComponentType<{ className?: string }>;
|
||||||
|
href: string;
|
||||||
|
badge?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SidebarProps {
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updated navigation items - remove logout from here
|
||||||
|
const navigationItems: NavigationItem[] = [
|
||||||
|
{ id: "dashboard", name: "Dashboard", icon: Home, href: "/dashboard" },
|
||||||
|
{ id: "analytics", name: "Analytics", icon: BarChart3, href: "/analytics" },
|
||||||
|
{ id: "documents", name: "Documents", icon: FileText, href: "/documents", badge: "3" },
|
||||||
|
{ id: "notifications", name: "Notifications", icon: Bell, href: "/notifications", badge: "12" },
|
||||||
|
{ id: "profile", name: "Profile", icon: User, href: "/profile" },
|
||||||
|
{ id: "settings", name: "Settings", icon: Settings, href: "/settings" },
|
||||||
|
{ id: "help", name: "Help & Support", icon: HelpCircle, href: "/help" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export function Sidebar({ className = "" }: SidebarProps) {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const [isCollapsed, setIsCollapsed] = useState(false);
|
||||||
|
const [activeItem, setActiveItem] = useState("dashboard");
|
||||||
|
|
||||||
|
// Auto-open sidebar on desktop
|
||||||
|
useEffect(() => {
|
||||||
|
const handleResize = () => {
|
||||||
|
if (window.innerWidth >= 768) {
|
||||||
|
setIsOpen(true);
|
||||||
|
} else {
|
||||||
|
setIsOpen(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handleResize();
|
||||||
|
window.addEventListener('resize', handleResize);
|
||||||
|
return () => window.removeEventListener('resize', handleResize);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const toggleSidebar = () => setIsOpen(!isOpen);
|
||||||
|
const toggleCollapse = () => setIsCollapsed(!isCollapsed);
|
||||||
|
|
||||||
|
const handleItemClick = (itemId: string) => {
|
||||||
|
setActiveItem(itemId);
|
||||||
|
if (window.innerWidth < 768) {
|
||||||
|
setIsOpen(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Mobile hamburger button */}
|
||||||
|
<button
|
||||||
|
onClick={toggleSidebar}
|
||||||
|
className="fixed top-6 left-6 z-50 p-3 rounded-lg bg-white shadow-md border border-slate-100 md:hidden hover:bg-slate-50 transition-all duration-200"
|
||||||
|
aria-label="Toggle sidebar"
|
||||||
|
>
|
||||||
|
{isOpen ?
|
||||||
|
<X className="h-5 w-5 text-slate-600" /> :
|
||||||
|
<Menu className="h-5 w-5 text-slate-600" />
|
||||||
|
}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* Mobile overlay */}
|
||||||
|
{isOpen && (
|
||||||
|
<div
|
||||||
|
className="fixed inset-0 bg-black/40 backdrop-blur-sm z-30 md:hidden transition-opacity duration-300"
|
||||||
|
onClick={toggleSidebar}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Sidebar */}
|
||||||
|
<div
|
||||||
|
className={`
|
||||||
|
fixed top-0 left-0 h-full bg-white border-r border-slate-200 z-40 transition-all duration-300 ease-in-out flex flex-col
|
||||||
|
${isOpen ? "translate-x-0" : "-translate-x-full"}
|
||||||
|
${isCollapsed ? "w-28" : "w-78"}
|
||||||
|
md:translate-x-0 md:static md:z-auto
|
||||||
|
${className}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{/* Header with logo and collapse button */}
|
||||||
|
<div className="flex items-center justify-between p-5 border-b border-slate-200 bg-slate-50/60">
|
||||||
|
{!isCollapsed && (
|
||||||
|
<div className="flex items-center space-x-2.5">
|
||||||
|
<div className="w-9 h-9 bg-blue-600 rounded-lg flex items-center justify-center shadow-sm">
|
||||||
|
<span className="text-white font-bold text-base">A</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<span className="font-semibold text-slate-800 text-base">Acme Corp</span>
|
||||||
|
<span className="text-xs text-slate-500">Enterprise Dashboard</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{isCollapsed && (
|
||||||
|
<div className="w-9 h-9 bg-blue-600 rounded-lg flex items-center justify-center mx-auto shadow-sm">
|
||||||
|
<span className="text-white font-bold text-base">A</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Desktop collapse button */}
|
||||||
|
<button
|
||||||
|
onClick={toggleCollapse}
|
||||||
|
className="hidden md:flex p-1.5 rounded-md hover:bg-slate-100 transition-all duration-200"
|
||||||
|
aria-label={isCollapsed ? "Expand sidebar" : "Collapse sidebar"}
|
||||||
|
>
|
||||||
|
{isCollapsed ? (
|
||||||
|
<ChevronRight className="h-4 w-4 text-slate-500" />
|
||||||
|
) : (
|
||||||
|
<ChevronLeft className="h-4 w-4 text-slate-500" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Search Bar */}
|
||||||
|
{!isCollapsed && (
|
||||||
|
<div className="px-4 py-3">
|
||||||
|
<div className="relative">
|
||||||
|
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-3.5 w-3.5 text-slate-400" />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Search..."
|
||||||
|
className="w-full pl-9 pr-4 py-2 bg-slate-50 border border-slate-200 rounded-md text-sm placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Navigation */}
|
||||||
|
<nav className="flex-1 px-3 py-2 overflow-y-auto">
|
||||||
|
<ul className="space-y-0.5">
|
||||||
|
{navigationItems.map((item) => {
|
||||||
|
const Icon = item.icon;
|
||||||
|
const isActive = activeItem === item.id;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li key={item.id}>
|
||||||
|
<button
|
||||||
|
onClick={() => handleItemClick(item.id)}
|
||||||
|
className={`
|
||||||
|
w-full flex items-center space-x-2.5 px-3 py-2.5 rounded-md text-left transition-all duration-200 group
|
||||||
|
${isActive
|
||||||
|
? "bg-blue-50 text-blue-700"
|
||||||
|
: "text-slate-600 hover:bg-slate-50 hover:text-slate-900"
|
||||||
|
}
|
||||||
|
${isCollapsed ? "justify-center px-2" : ""}
|
||||||
|
`}
|
||||||
|
title={isCollapsed ? item.name : undefined}
|
||||||
|
>
|
||||||
|
<div className="flex items-center justify-center min-w-[24px]">
|
||||||
|
<Icon
|
||||||
|
className={`
|
||||||
|
h-4.5 w-4.5 flex-shrink-0
|
||||||
|
${isActive
|
||||||
|
? "text-blue-600"
|
||||||
|
: "text-slate-500 group-hover:text-slate-700"
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{!isCollapsed && (
|
||||||
|
<div className="flex items-center justify-between w-full">
|
||||||
|
<span className={`text-sm ${isActive ? "font-medium" : "font-normal"}`}>{item.name}</span>
|
||||||
|
{item.badge && (
|
||||||
|
<span className={`
|
||||||
|
px-1.5 py-0.5 text-xs font-medium rounded-full
|
||||||
|
${isActive
|
||||||
|
? "bg-blue-100 text-blue-700"
|
||||||
|
: "bg-slate-100 text-slate-600"
|
||||||
|
}
|
||||||
|
`}>
|
||||||
|
{item.badge}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Badge for collapsed state */}
|
||||||
|
{isCollapsed && item.badge && (
|
||||||
|
<div className="absolute top-1 right-1 w-4 h-4 flex items-center justify-center rounded-full bg-blue-100 border border-white">
|
||||||
|
<span className="text-[10px] font-medium text-blue-700">
|
||||||
|
{parseInt(item.badge) > 9 ? '9+' : item.badge}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Tooltip for collapsed state */}
|
||||||
|
{isCollapsed && (
|
||||||
|
<div className="absolute left-full ml-2 px-2 py-1 bg-slate-800 text-white text-xs rounded opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 whitespace-nowrap z-50">
|
||||||
|
{item.name}
|
||||||
|
{item.badge && (
|
||||||
|
<span className="ml-1.5 px-1 py-0.5 bg-slate-700 rounded-full text-[10px]">
|
||||||
|
{item.badge}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
<div className="absolute left-0 top-1/2 transform -translate-y-1/2 -translate-x-1 w-1.5 h-1.5 bg-slate-800 rotate-45" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{/* Bottom section with profile and logout */}
|
||||||
|
<div className="mt-auto border-t border-slate-200">
|
||||||
|
{/* Profile Section */}
|
||||||
|
<div className={`border-b border-slate-200 bg-slate-50/30 ${isCollapsed ? 'py-3 px-2' : 'p-3'}`}>
|
||||||
|
{!isCollapsed ? (
|
||||||
|
<div className="flex items-center px-3 py-2 rounded-md bg-white hover:bg-slate-50 transition-colors duration-200">
|
||||||
|
<div className="w-8 h-8 bg-slate-200 rounded-full flex items-center justify-center">
|
||||||
|
<span className="text-slate-700 font-medium text-sm">JD</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 min-w-0 ml-2.5">
|
||||||
|
<p className="text-sm font-medium text-slate-800 truncate">John Doe</p>
|
||||||
|
<p className="text-xs text-slate-500 truncate">Senior Administrator</p>
|
||||||
|
</div>
|
||||||
|
<div className="w-2 h-2 bg-green-500 rounded-full ml-2" title="Online" />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-center">
|
||||||
|
<div className="relative">
|
||||||
|
<div className="w-9 h-9 bg-slate-200 rounded-full flex items-center justify-center">
|
||||||
|
<span className="text-slate-700 font-medium text-sm">JD</span>
|
||||||
|
</div>
|
||||||
|
<div className="absolute -bottom-1 -right-1 w-3 h-3 bg-green-500 rounded-full border-2 border-white" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Logout Button */}
|
||||||
|
<div className="p-3">
|
||||||
|
<button
|
||||||
|
onClick={() => handleItemClick("logout")}
|
||||||
|
className={`
|
||||||
|
w-full flex items-center rounded-md text-left transition-all duration-200 group
|
||||||
|
text-red-600 hover:bg-red-50 hover:text-red-700
|
||||||
|
${isCollapsed ? "justify-center p-2.5" : "space-x-2.5 px-3 py-2.5"}
|
||||||
|
`}
|
||||||
|
title={isCollapsed ? "Logout" : undefined}
|
||||||
|
>
|
||||||
|
<div className="flex items-center justify-center min-w-[24px]">
|
||||||
|
<LogOut className="h-4.5 w-4.5 flex-shrink-0 text-red-500 group-hover:text-red-600" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{!isCollapsed && (
|
||||||
|
<span className="text-sm">Logout</span>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Tooltip for collapsed state */}
|
||||||
|
{isCollapsed && (
|
||||||
|
<div className="absolute left-full ml-2 px-2 py-1 bg-slate-800 text-white text-xs rounded opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 whitespace-nowrap z-50">
|
||||||
|
Logout
|
||||||
|
<div className="absolute left-0 top-1/2 transform -translate-y-1/2 -translate-x-1 w-1.5 h-1.5 bg-slate-800 rotate-45" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Main Content Area */}
|
||||||
|
<div
|
||||||
|
className={`
|
||||||
|
transition-all duration-300 ease-in-out w-full
|
||||||
|
${isCollapsed ? "md:ml-20" : "md:ml-72"}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{/* Your content remains the same */}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
90
components/ui/timeline.tsx
Normal file
90
components/ui/timeline.tsx
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
"use client";
|
||||||
|
import {
|
||||||
|
useMotionValueEvent,
|
||||||
|
useScroll,
|
||||||
|
useTransform,
|
||||||
|
motion,
|
||||||
|
} from "framer-motion";
|
||||||
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
|
interface TimelineEntry {
|
||||||
|
title: string;
|
||||||
|
content: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Timeline = ({ data }: { data: TimelineEntry[] }) => {
|
||||||
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
const [height, setHeight] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (ref.current) {
|
||||||
|
const rect = ref.current.getBoundingClientRect();
|
||||||
|
setHeight(rect.height);
|
||||||
|
}
|
||||||
|
}, [ref]);
|
||||||
|
|
||||||
|
const { scrollYProgress } = useScroll({
|
||||||
|
target: containerRef,
|
||||||
|
offset: ["start 10%", "end 50%"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const heightTransform = useTransform(scrollYProgress, [0, 1], [0, height]);
|
||||||
|
const opacityTransform = useTransform(scrollYProgress, [0, 0.1], [0, 1]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="w-full bg-white dark:bg-neutral-950 font-sans md:px-10"
|
||||||
|
ref={containerRef}
|
||||||
|
>
|
||||||
|
<div className="max-w-7xl mx-auto py-20 px-4 md:px-8 lg:px-10">
|
||||||
|
<h2 className="text-lg md:text-4xl mb-4 text-black dark:text-white max-w-4xl">
|
||||||
|
Changelog from my journey
|
||||||
|
</h2>
|
||||||
|
<p className="text-neutral-700 dark:text-neutral-300 text-sm md:text-base max-w-sm">
|
||||||
|
I've been working on Aceternity for the past 2 years. Here's
|
||||||
|
a timeline of my journey.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ref={ref} className="relative max-w-7xl mx-auto pb-20">
|
||||||
|
{data.map((item, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className="flex justify-start pt-10 md:pt-40 md:gap-10"
|
||||||
|
>
|
||||||
|
<div className="sticky flex flex-col md:flex-row z-40 items-center top-40 self-start max-w-xs lg:max-w-sm md:w-full">
|
||||||
|
<div className="h-10 absolute left-3 md:left-3 w-10 rounded-full bg-white dark:bg-black flex items-center justify-center">
|
||||||
|
<div className="h-4 w-4 rounded-full bg-neutral-200 dark:bg-neutral-800 border border-neutral-300 dark:border-neutral-700 p-2" />
|
||||||
|
</div>
|
||||||
|
<h3 className="hidden md:block text-xl md:pl-20 md:text-5xl font-bold text-neutral-500 dark:text-neutral-500 ">
|
||||||
|
{item.title}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="relative pl-20 pr-4 md:pl-4 w-full">
|
||||||
|
<h3 className="md:hidden block text-2xl mb-4 text-left font-bold text-neutral-500 dark:text-neutral-500">
|
||||||
|
{item.title}
|
||||||
|
</h3>
|
||||||
|
{item.content}{" "}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: height + "px",
|
||||||
|
}}
|
||||||
|
className="absolute md:left-8 left-8 top-0 overflow-hidden w-[2px] bg-[linear-gradient(to_bottom,var(--tw-gradient-stops))] from-transparent from-[0%] via-neutral-200 dark:via-neutral-700 to-transparent to-[99%] [mask-image:linear-gradient(to_bottom,transparent_0%,black_10%,black_90%,transparent_100%)] "
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
style={{
|
||||||
|
height: heightTransform,
|
||||||
|
opacity: opacityTransform,
|
||||||
|
}}
|
||||||
|
className="absolute inset-x-0 top-0 w-[2px] bg-gradient-to-t from-purple-500 via-blue-500 to-transparent from-[0%] via-[10%] rounded-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
158
docs/design/timeline-comp.tsx
Normal file
158
docs/design/timeline-comp.tsx
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
|
||||||
|
import Image from "next/image";
|
||||||
|
import React from "react";
|
||||||
|
import { Timeline } from "@/components/ui/timeline";
|
||||||
|
|
||||||
|
export function TimelineDemo() {
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
title: "2024",
|
||||||
|
content: (
|
||||||
|
<div>
|
||||||
|
<p className="text-neutral-800 dark:text-neutral-200 text-xs md:text-sm font-normal mb-8">
|
||||||
|
Built and launched Aceternity UI and Aceternity UI Pro from scratch
|
||||||
|
</p>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<Image
|
||||||
|
src="https://assets.aceternity.com/templates/startup-1.webp"
|
||||||
|
alt="startup template"
|
||||||
|
width={500}
|
||||||
|
height={500}
|
||||||
|
className="rounded-lg object-cover h-20 md:h-44 lg:h-60 w-full shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset]"
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src="https://assets.aceternity.com/templates/startup-2.webp"
|
||||||
|
alt="startup template"
|
||||||
|
width={500}
|
||||||
|
height={500}
|
||||||
|
className="rounded-lg object-cover h-20 md:h-44 lg:h-60 w-full shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset]"
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src="https://assets.aceternity.com/templates/startup-3.webp"
|
||||||
|
alt="startup template"
|
||||||
|
width={500}
|
||||||
|
height={500}
|
||||||
|
className="rounded-lg object-cover h-20 md:h-44 lg:h-60 w-full shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset]"
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src="https://assets.aceternity.com/templates/startup-4.webp"
|
||||||
|
alt="startup template"
|
||||||
|
width={500}
|
||||||
|
height={500}
|
||||||
|
className="rounded-lg object-cover h-20 md:h-44 lg:h-60 w-full shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Early 2023",
|
||||||
|
content: (
|
||||||
|
<div>
|
||||||
|
<p className="text-neutral-800 dark:text-neutral-200 text-xs md:text-sm font-normal mb-8">
|
||||||
|
I usually run out of copy, but when I see content this big, I try to
|
||||||
|
integrate lorem ipsum.
|
||||||
|
</p>
|
||||||
|
<p className="text-neutral-800 dark:text-neutral-200 text-xs md:text-sm font-normal mb-8">
|
||||||
|
Lorem ipsum is for people who are too lazy to write copy. But we are
|
||||||
|
not. Here are some more example of beautiful designs I built.
|
||||||
|
</p>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<Image
|
||||||
|
src="https://assets.aceternity.com/pro/hero-sections.png"
|
||||||
|
alt="hero template"
|
||||||
|
width={500}
|
||||||
|
height={500}
|
||||||
|
className="rounded-lg object-cover h-20 md:h-44 lg:h-60 w-full shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset]"
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src="https://assets.aceternity.com/features-section.png"
|
||||||
|
alt="feature template"
|
||||||
|
width={500}
|
||||||
|
height={500}
|
||||||
|
className="rounded-lg object-cover h-20 md:h-44 lg:h-60 w-full shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset]"
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src="https://assets.aceternity.com/pro/bento-grids.png"
|
||||||
|
alt="bento template"
|
||||||
|
width={500}
|
||||||
|
height={500}
|
||||||
|
className="rounded-lg object-cover h-20 md:h-44 lg:h-60 w-full shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset]"
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src="https://assets.aceternity.com/cards.png"
|
||||||
|
alt="cards template"
|
||||||
|
width={500}
|
||||||
|
height={500}
|
||||||
|
className="rounded-lg object-cover h-20 md:h-44 lg:h-60 w-full shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Changelog",
|
||||||
|
content: (
|
||||||
|
<div>
|
||||||
|
<p className="text-neutral-800 dark:text-neutral-200 text-xs md:text-sm font-normal mb-4">
|
||||||
|
Deployed 5 new components on Aceternity today
|
||||||
|
</p>
|
||||||
|
<div className="mb-8">
|
||||||
|
<div className="flex gap-2 items-center text-neutral-700 dark:text-neutral-300 text-xs md:text-sm">
|
||||||
|
✅ Card grid component
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2 items-center text-neutral-700 dark:text-neutral-300 text-xs md:text-sm">
|
||||||
|
✅ Startup template Aceternity
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2 items-center text-neutral-700 dark:text-neutral-300 text-xs md:text-sm">
|
||||||
|
✅ Random file upload lol
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2 items-center text-neutral-700 dark:text-neutral-300 text-xs md:text-sm">
|
||||||
|
✅ Himesh Reshammiya Music CD
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2 items-center text-neutral-700 dark:text-neutral-300 text-xs md:text-sm">
|
||||||
|
✅ Salman Bhai Fan Club registrations open
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<Image
|
||||||
|
src="https://assets.aceternity.com/pro/hero-sections.png"
|
||||||
|
alt="hero template"
|
||||||
|
width={500}
|
||||||
|
height={500}
|
||||||
|
className="rounded-lg object-cover h-20 md:h-44 lg:h-60 w-full shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset]"
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src="https://assets.aceternity.com/features-section.png"
|
||||||
|
alt="feature template"
|
||||||
|
width={500}
|
||||||
|
height={500}
|
||||||
|
className="rounded-lg object-cover h-20 md:h-44 lg:h-60 w-full shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset]"
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src="https://assets.aceternity.com/pro/bento-grids.png"
|
||||||
|
alt="bento template"
|
||||||
|
width={500}
|
||||||
|
height={500}
|
||||||
|
className="rounded-lg object-cover h-20 md:h-44 lg:h-60 w-full shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset]"
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src="https://assets.aceternity.com/cards.png"
|
||||||
|
alt="cards template"
|
||||||
|
width={500}
|
||||||
|
height={500}
|
||||||
|
className="rounded-lg object-cover h-20 md:h-44 lg:h-60 w-full shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen w-full">
|
||||||
|
<div className="absolute top-0 left-0 w-full">
|
||||||
|
<Timeline data={data} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
495
docs/specs/bouwplan-ai-speedrun-marketing-first-v2.1.md
Normal file
495
docs/specs/bouwplan-ai-speedrun-marketing-first-v2.1.md
Normal file
@@ -0,0 +1,495 @@
|
|||||||
|
# 🚀 Mission Control – Bouwplan AI Speedrun EPD v2.1
|
||||||
|
|
||||||
|
**Projectnaam:** AI Speedrun - Mini-EPD Prototype
|
||||||
|
**Versie:** v2.1 (Vereenvoudigde User Journey + Teal Design System)
|
||||||
|
**Datum:** 17-11-2024
|
||||||
|
**Auteur:** Colin Lit
|
||||||
|
**Laatste Update:** 17-11-2024
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Doel en context
|
||||||
|
|
||||||
|
🎯 **Doel:** Een werkend EPD-prototype bouwen in 4 weken dat demonstreert hoe "Software on Demand" traditionele ontwikkeling disrupts: van €100.000+ en 12-24 maanden naar €200 build cost en 4 weken doorlooptijd.
|
||||||
|
|
||||||
|
📘 **Toelichting:** Dit project dient een drievoudig doel:
|
||||||
|
1. **Demo voor GGZ-sector:** Tonen van AI-waarde in EPD-workflows (intake → profiel → plan) tijdens inspiratiesessies
|
||||||
|
2. **LinkedIn Build in Public:** Wekelijkse transparante updates die viral marketing genereren voor AI consultancy
|
||||||
|
3. **Software on Demand Proof:** Bewijs dat enterprise-kwaliteit software nu in weken ipv jaren gebouwd kan worden
|
||||||
|
|
||||||
|
**Nieuwe Strategie (v2.1):**
|
||||||
|
- **Vereenvoudigde user journey:** Geen separate EPD demo pagina meer
|
||||||
|
- **Features in timeline:** Build-in-public transparantie met features showcase per week
|
||||||
|
- **Login met features:** Directe showcase van EPD capabilities op login pagina
|
||||||
|
- **Teal-first design:** Modern, innovatief brand identity (#0D9488)
|
||||||
|
|
||||||
|
Het systeem toont praktische AI-integratie: intake samenvattingen in seconden ipv uren, automatische DSM-classificatie, en behandelplannen die direct bruikbaar zijn. Alles met fictieve demo-data, privacy-first design.
|
||||||
|
|
||||||
|
**Referenties:**
|
||||||
|
- **FO v2.1:** `docs/specs/fo-marketing-app-flow-v2.md` - Vereenvoudigde user journey
|
||||||
|
- **UX Plan v2.0:** `docs/specs/ux-implementation-plan-v2.md` - Teal-first design system
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Uitgangspunten
|
||||||
|
|
||||||
|
### 2.1 Technische Stack
|
||||||
|
|
||||||
|
🎯 **Doel:** Modern, bewezen technologie stack voor snelle development en lage run costs.
|
||||||
|
|
||||||
|
**Frontend:**
|
||||||
|
- **Framework:** Next.js 15 (App Router) - Single repo voor marketing + EPD
|
||||||
|
- **Styling:** Tailwind CSS v3.4 met teal-first design system
|
||||||
|
- **UI Components:** shadcn/ui + custom components (Timeline, AIButton)
|
||||||
|
- **Rich Text:** TipTap editor (ProseMirror basis) - Week 3
|
||||||
|
- **Icons:** Lucide React
|
||||||
|
- **Animations:** Framer Motion (voor timeline scroll effects)
|
||||||
|
- **State:** Zustand + React Context (simpel maar effectief)
|
||||||
|
|
||||||
|
**Backend:**
|
||||||
|
- **API:** Next.js Route Handlers (server-side)
|
||||||
|
- **Database:** Supabase (PostgreSQL + Auth + Storage) - EU region
|
||||||
|
- **AI:** Claude 3.5 Sonnet (Anthropic) - Superieur voor Nederlands
|
||||||
|
- **Hosting:** Vercel (EU region Amsterdam)
|
||||||
|
|
||||||
|
**Development & Tools:**
|
||||||
|
- **Version Control:** GitHub (public repo voor transparantie)
|
||||||
|
- **Type Safety:** TypeScript overal
|
||||||
|
- **Package Manager:** pnpm (sneller dan npm)
|
||||||
|
- **AI Pair Programming:** Cursor IDE
|
||||||
|
- **Testing:** Vitest + Playwright (basis coverage)
|
||||||
|
|
||||||
|
### 2.2 Projectkaders
|
||||||
|
|
||||||
|
🎯 **Doel:** Realistische constraints voor 4-weken sprint.
|
||||||
|
|
||||||
|
- **Tijd:** 4 weken part-time (80-120 uur totaal)
|
||||||
|
- **Budget:** €200 totaal (€50/maand runtime target)
|
||||||
|
- **Team:** 1 developer (Colin) + AI tools als co-pilot
|
||||||
|
- **Data:** 100% fictieve demo data
|
||||||
|
- **Scope:** MVP voor 10-min demo + marketing site
|
||||||
|
- **Launch:** LinkedIn viral series + demo sessies
|
||||||
|
|
||||||
|
### 2.3 Programmeer Uitgangspunten
|
||||||
|
|
||||||
|
🎯 **Doel:** Code quality zonder over-engineering voor MVP.
|
||||||
|
|
||||||
|
**Core Principles:**
|
||||||
|
- **DRY:** Herbruikbare componenten, centrale configs
|
||||||
|
- **KISS:** Simpele oplossingen boven complexiteit
|
||||||
|
- **SOC:** UI/logic/data layers gescheiden
|
||||||
|
- **YAGNI:** Alleen bouwen wat nu nodig is
|
||||||
|
|
||||||
|
**Development Practices:**
|
||||||
|
- **Iteratief:** Ship daily, perfect later
|
||||||
|
- **AI-First:** Laat Claude/Cursor heavy lifting doen
|
||||||
|
- **Copy-Paste OK:** Voor MVP snelheid > perfectie
|
||||||
|
- **Error Handling:** User-friendly messages overal
|
||||||
|
- **Security:** API keys server-side, RLS in Supabase
|
||||||
|
|
||||||
|
**Design System:**
|
||||||
|
- **Primary Color:** Teal (#0D9488 / teal-600) - Innovation signal
|
||||||
|
- **AI Color:** Amber (#F59E0B / amber-500) - AI actions
|
||||||
|
- **Neutral:** Slate scale voor professional foundation
|
||||||
|
- **Typography:** Crimson Text (serif) + Inter (sans) + JetBrains Mono
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Epics & Stories Overzicht
|
||||||
|
|
||||||
|
🎯 **Doel:** 8 duidelijke epics voor 4-weken development sprint - **Marketing First Strategy met vereenvoudigde user journey**.
|
||||||
|
|
||||||
|
| Epic ID | Titel | Doel | Status | Story Count | Week |
|
||||||
|
|---------|-------|------|--------|-------------|------|
|
||||||
|
| **WEEK 1 - FOUNDATION & MARKETING REFACTOR** |||||
|
||||||
|
| E0 | Project Setup | Next.js + Supabase + Vercel running | ✅ Compleet | 5 | 1 |
|
||||||
|
| E1 | Marketing Website Refactor | Homepage met timeline + login met features | 🔄 In Progress | 7 | 1 |
|
||||||
|
| E2 | Design System Migration | Teal-first colors + component updates | ⏳ To Do | 5 | 1 |
|
||||||
|
| **WEEK 2 - EPD CORE** |||||
|
||||||
|
| E3 | Database & Auth | Schema + RLS + demo users | ✅ Compleet | 4 | 2 |
|
||||||
|
| E4 | Core UI & Client Module | Layout + Client CRUD + Navigation | ⏳ To Do | 5 | 2 |
|
||||||
|
| **WEEK 3 - AI MAGIC** |||||
|
||||||
|
| E5 | Intake & AI Integration | TipTap + Claude API + Prompts | ⏳ To Do | 6 | 3 |
|
||||||
|
| E6 | Profile & Plan | DSM + behandelplan flows | ⏳ To Do | 4 | 3 |
|
||||||
|
| **WEEK 4 - POLISH & LAUNCH** |||||
|
||||||
|
| E7 | Onboarding System | Walkthrough + tooltips + help | ⏳ To Do | 4 | 4 |
|
||||||
|
| E8 | Performance & Launch | Optimization + demo prep | ⏳ To Do | 4 | 4 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Epics & Stories (Uitwerking)
|
||||||
|
|
||||||
|
### Epic 0 — Project Setup
|
||||||
|
|
||||||
|
**Epic Doel:** Werkende development omgeving met alle benodigde tools en dependencies.
|
||||||
|
|
||||||
|
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|
||||||
|
|----------|--------------|---------------------|--------|------------------|--------------|
|
||||||
|
| E0.S1 | Repository aanmaken | GitHub repo + lokale clone, `.gitignore` config | ✅ | — | 1 |
|
||||||
|
| E0.S2 | Next.js project initialisatie | Next.js 15 App Router draait, dev server start | ✅ | E0.S1 | 2 |
|
||||||
|
| E0.S3 | Supabase setup | Project aangemaakt, database connected, Auth enabled | ✅ | E0.S2 | 3 |
|
||||||
|
| E0.S4 | Dependencies installeren | Tailwind, shadcn/ui, Framer Motion, Lucide geïnstalleerd | ✅ | E0.S2 | 2 |
|
||||||
|
| E0.S5 | Environment variables | `.env.local` + Vercel vars geconfigureerd | ✅ | E0.S3 | 1 |
|
||||||
|
|
||||||
|
**Technical Notes:**
|
||||||
|
- Gebruik `pnpm` voor snellere installs
|
||||||
|
- `.env.example` committen voor team onboarding
|
||||||
|
- Supabase project in EU region (Amsterdam)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Epic 1 — Marketing Website Refactor
|
||||||
|
|
||||||
|
**Epic Doel:** Vereenvoudigde marketing homepage met timeline (features showcase) en login pagina met features.
|
||||||
|
|
||||||
|
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|
||||||
|
|----------|--------------|---------------------|--------|------------------|--------------|
|
||||||
|
| E1.S1 | Verwijder EPD demo pagina | `/epd` route verwijderd, navigation updated | ⏳ | E0.S5 | 1 |
|
||||||
|
| E1.S2 | Homepage vereenvoudigen | Manifesto content verwijderd, statement section toegevoegd | ⏳ | E1.S1 | 3 |
|
||||||
|
| E1.S3 | Timeline component integreren | Aceternity timeline met features per week | ⏳ | E1.S2 | 5 |
|
||||||
|
| E1.S4 | Timeline content structuur | `content/nl/timeline.json` met features array | ⏳ | E1.S3 | 2 |
|
||||||
|
| E1.S5 | Login pagina refactor | Split-screen layout: features links, login rechts | ⏳ | E1.S1 | 4 |
|
||||||
|
| E1.S6 | Features showcase component | Herbruikbare feature cards voor timeline + login | ⏳ | E1.S3, E1.S5 | 3 |
|
||||||
|
| E1.S7 | CTA updates | Homepage CTA naar `/login`, navigation cleanup | ⏳ | E1.S2, E1.S5 | 1 |
|
||||||
|
|
||||||
|
**Technical Notes:**
|
||||||
|
- Timeline component: `components/ui/timeline.tsx` (Aceternity UI pattern)
|
||||||
|
- Features data: `content/nl/timeline.json` (met features array per week)
|
||||||
|
- Login layout: Inspiratie van `components/ui/sign-in.tsx`
|
||||||
|
- Mobile: Stack layout voor login pagina (features boven, form onder)
|
||||||
|
|
||||||
|
**Content Structure:**
|
||||||
|
```json
|
||||||
|
// content/nl/timeline.json
|
||||||
|
{
|
||||||
|
"weeks": [
|
||||||
|
{
|
||||||
|
"weekNumber": 1,
|
||||||
|
"title": "Week 1 • Nov 11-17",
|
||||||
|
"status": "completed",
|
||||||
|
"description": "...",
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"title": "AI-Gestuurde Intake",
|
||||||
|
"description": "...",
|
||||||
|
"time": "< 5 seconden",
|
||||||
|
"traditional": "15-20 minuten handmatig",
|
||||||
|
"icon": "Brain"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metrics": { ... },
|
||||||
|
"achievements": [ ... ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Epic 2 — Design System Migration
|
||||||
|
|
||||||
|
**Epic Doel:** Teal-first design system implementeren (migratie van blue naar teal).
|
||||||
|
|
||||||
|
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|
||||||
|
|----------|--------------|---------------------|--------|------------------|--------------|
|
||||||
|
| E2.S1 | Tailwind config update | Teal brand colors, amber AI colors | ⏳ | E0.S4 | 2 |
|
||||||
|
| E2.S2 | Global CSS variables | `--primary`, `--info` naar teal | ⏳ | E2.S1 | 1 |
|
||||||
|
| E2.S3 | Component color updates | Buttons, links, navigation naar teal | ⏳ | E2.S2 | 3 |
|
||||||
|
| E2.S4 | AIButton component | Amber gradient button voor AI actions | ⏳ | E2.S1 | 2 |
|
||||||
|
| E2.S5 | Contrast testing | WCAG AA compliance voor teal colors | ⏳ | E2.S3 | 1 |
|
||||||
|
|
||||||
|
**Technical Notes:**
|
||||||
|
- Primary: `teal-600` (#0D9488)
|
||||||
|
- AI actions: `amber-500` (#F59E0B)
|
||||||
|
- Test contrast: WebAIM Contrast Checker
|
||||||
|
- Rollback plan: Git revert indien nodig
|
||||||
|
|
||||||
|
**Color Palette:**
|
||||||
|
```typescript
|
||||||
|
// tailwind.config.ts
|
||||||
|
colors: {
|
||||||
|
brand: {
|
||||||
|
600: '#0D9488', // PRIMARY
|
||||||
|
700: '#0F766E', // Hover
|
||||||
|
// ... full scale
|
||||||
|
},
|
||||||
|
ai: colors.amber, // AI features
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Epic 3 — Database & Auth
|
||||||
|
|
||||||
|
**Epic Doel:** Werkend datamodel met seed data, auth flow en RLS policies.
|
||||||
|
|
||||||
|
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|
||||||
|
|----------|--------------|---------------------|--------|------------------|--------------|
|
||||||
|
| E3.S1 | Database schema | 5 core tables: clients, intake_notes, problem_profiles, treatment_plans, ai_events | ✅ | E0.S3 | 5 |
|
||||||
|
| E3.S2 | RLS policies | Row-level security per table (user isolation) | ✅ | E3.S1 | 3 |
|
||||||
|
| E3.S3 | Demo users seed | demo@mini-ecd.demo account aangemaakt | ✅ | E3.S2 | 1 |
|
||||||
|
| E3.S4 | Auth flow | Magic link + password login werkend | ✅ | E3.S3 | 2 |
|
||||||
|
|
||||||
|
**Technical Notes:**
|
||||||
|
- Schema: PostgreSQL via Supabase
|
||||||
|
- RLS: `auth.uid() = created_by` pattern
|
||||||
|
- Demo users: Shared dataset voor demo purposes
|
||||||
|
- Auth: Supabase Auth (magic link + password)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Epic 4 — Core UI & Client Module
|
||||||
|
|
||||||
|
**Epic Doel:** EPD app foundation: layout, client CRUD, navigation.
|
||||||
|
|
||||||
|
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|
||||||
|
|----------|--------------|---------------------|--------|------------------|--------------|
|
||||||
|
| E4.S1 | Coming Soon dashboard | `/epd/clients` placeholder met roadmap | ⏳ | E3.S4 | 2 |
|
||||||
|
| E4.S2 | App layout | Header + sidebar + main content area | ⏳ | E4.S1 | 3 |
|
||||||
|
| E4.S3 | Client list page | CRUD operations, table view, filters | ⏳ | E4.S2 | 5 |
|
||||||
|
| E4.S4 | Client detail page | Tabs: Intake, Profile, Plan (placeholders) | ⏳ | E4.S3 | 3 |
|
||||||
|
| E4.S5 | Navigation & routing | App routes, breadcrumbs, logout flow | ⏳ | E4.S2 | 2 |
|
||||||
|
|
||||||
|
**Technical Notes:**
|
||||||
|
- Layout: Separate van marketing (app header vs MinimalNav)
|
||||||
|
- Client CRUD: Forms met validation (Zod)
|
||||||
|
- Routing: `/epd/clients` namespace
|
||||||
|
- Mobile: Responsive table → card layout
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Epic 5 — Intake & AI Integration
|
||||||
|
|
||||||
|
**Epic Doel:** TipTap editor + Claude API voor intake samenvatting en B1 readability.
|
||||||
|
|
||||||
|
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|
||||||
|
|----------|--------------|---------------------|--------|------------------|--------------|
|
||||||
|
| E5.S1 | TipTap editor setup | Rich text editor in client detail | ⏳ | E4.S4 | 4 |
|
||||||
|
| E5.S2 | Claude API endpoints | `/api/ai/summarize`, `/api/ai/simplify` | ⏳ | E0.S5 | 5 |
|
||||||
|
| E5.S3 | AI-rail component | Right panel voor AI suggestions | ⏳ | E5.S2 | 4 |
|
||||||
|
| E5.S4 | Prompt engineering | Nederlands prompts voor samenvatting | ⏳ | E5.S2 | 3 |
|
||||||
|
| E5.S5 | AI event logging | Log alle AI calls naar `ai_events` table | ⏳ | E5.S2 | 2 |
|
||||||
|
| E5.S6 | Error handling | Retry logic, user-friendly errors | ⏳ | E5.S2 | 2 |
|
||||||
|
|
||||||
|
**Technical Notes:**
|
||||||
|
- TipTap: ProseMirror-based editor
|
||||||
|
- Claude: 3.5 Sonnet voor Nederlands
|
||||||
|
- Prompts: Templates in `/lib/prompts/`
|
||||||
|
- Cost tracking: Log tokens + estimated costs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Epic 6 — Profile & Plan
|
||||||
|
|
||||||
|
**Epic Doel:** DSM-light classificatie + SMART behandelplan generatie.
|
||||||
|
|
||||||
|
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|
||||||
|
|----------|--------------|---------------------|--------|------------------|--------------|
|
||||||
|
| E6.S1 | Profile tab UI | DSM categories + severity selector | ⏳ | E4.S4 | 3 |
|
||||||
|
| E6.S2 | AI categorize endpoint | `/api/ai/categorize` met DSM-light output | ⏳ | E5.S2 | 4 |
|
||||||
|
| E6.S3 | Plan tab UI | SMART doelen form + interventies | ⏳ | E4.S4 | 3 |
|
||||||
|
| E6.S4 | AI plan generator | `/api/ai/plan` met 4 secties output | ⏳ | E6.S2 | 5 |
|
||||||
|
|
||||||
|
**Technical Notes:**
|
||||||
|
- DSM-light: 6 categorieën (stemming, angst, gedrag, etc.)
|
||||||
|
- Plan structuur: JSONB in database (flexibel)
|
||||||
|
- AI output: Structured JSON voor consistentie
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Epic 7 — Onboarding System
|
||||||
|
|
||||||
|
**Epic Doel:** User guidance voor eerste gebruik (tooltips, walkthrough).
|
||||||
|
|
||||||
|
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|
||||||
|
|----------|--------------|---------------------|--------|------------------|--------------|
|
||||||
|
| E7.S1 | First-time user detection | Check `user_metadata.onboarded` flag | ⏳ | E4.S2 | 1 |
|
||||||
|
| E7.S2 | Tooltip system | React Joyride of custom tooltips | ⏳ | E7.S1 | 3 |
|
||||||
|
| E7.S3 | Help documentation | In-app help modal met shortcuts | ⏳ | E7.S2 | 2 |
|
||||||
|
| E7.S4 | Skip onboarding | Option om walkthrough te skippen | ⏳ | E7.S2 | 1 |
|
||||||
|
|
||||||
|
**Technical Notes:**
|
||||||
|
- Tooltips: Highlight key features (AI buttons, etc.)
|
||||||
|
- Help: Keyboard shortcuts, feature overview
|
||||||
|
- Optional: Skip voor returning users
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Epic 8 — Performance & Launch
|
||||||
|
|
||||||
|
**Epic Doel:** Optimization, testing, demo preparation.
|
||||||
|
|
||||||
|
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|
||||||
|
|----------|--------------|---------------------|--------|------------------|--------------|
|
||||||
|
| E8.S1 | Performance optimization | Lighthouse > 90, LCP < 2.5s | ⏳ | E7.S4 | 3 |
|
||||||
|
| E8.S2 | Accessibility audit | WCAG AA compliance, keyboard nav | ⏳ | E8.S1 | 2 |
|
||||||
|
| E8.S3 | Demo dry-run | 10-min demo scenario werkt | ⏳ | E8.S2 | 2 |
|
||||||
|
| E8.S4 | Production deployment | Live op Vercel, monitoring setup | ⏳ | E8.S3 | 2 |
|
||||||
|
|
||||||
|
**Technical Notes:**
|
||||||
|
- Performance: Image optimization, code splitting
|
||||||
|
- Accessibility: Focus states, ARIA labels
|
||||||
|
- Demo: Pre-seeded data, backup plan
|
||||||
|
- Monitoring: Vercel Analytics + error tracking
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Kwaliteit & Testplan
|
||||||
|
|
||||||
|
🎯 **Doel:** Vastleggen hoe de kwaliteit van het project wordt geborgd.
|
||||||
|
|
||||||
|
### Test Types
|
||||||
|
|
||||||
|
| Test Type | Scope | Tools | Verantwoordelijke |
|
||||||
|
|-----------|-------|-------|-------------------|
|
||||||
|
| Unit Tests | Business logic, utilities | Vitest | Developer |
|
||||||
|
| Integration Tests | API endpoints, database | Playwright | Developer |
|
||||||
|
| Smoke Tests | Kritieke user flows | Manual checklist | Developer |
|
||||||
|
| Performance Tests | Load times, API response | Lighthouse | Developer |
|
||||||
|
| Accessibility Tests | WCAG AA compliance | axe DevTools | Developer |
|
||||||
|
|
||||||
|
### Test Coverage Targets
|
||||||
|
|
||||||
|
- **Unit tests:** 80%+ coverage op `/lib` folder
|
||||||
|
- **Integration tests:** Alle API endpoints
|
||||||
|
- **Smoke tests:** 5 happy flows + 3 error scenarios
|
||||||
|
|
||||||
|
### Manual Test Checklist (voor demo)
|
||||||
|
|
||||||
|
**Marketing Site:**
|
||||||
|
- [ ] Homepage laadt met hero + statement + timeline
|
||||||
|
- [ ] Timeline scrollt en toont features per week
|
||||||
|
- [ ] Login pagina toont features showcase + form
|
||||||
|
- [ ] Navigation werkt (Home, Contact, Login)
|
||||||
|
- [ ] Mobile responsive (timeline, login layout)
|
||||||
|
|
||||||
|
**EPD App:**
|
||||||
|
- [ ] User kan inloggen (magic link + demo credentials)
|
||||||
|
- [ ] Coming Soon dashboard toont roadmap
|
||||||
|
- [ ] Client CRUD werkt (Week 2)
|
||||||
|
- [ ] Intake editor werkt met TipTap (Week 3)
|
||||||
|
- [ ] AI samenvatting genereert binnen 5 sec (Week 3)
|
||||||
|
- [ ] Profile + Plan tabs werken (Week 3)
|
||||||
|
- [ ] Navigatie werkt zonder errors
|
||||||
|
- [ ] Mobile view is responsive
|
||||||
|
- [ ] Error states tonen user-friendly messages
|
||||||
|
|
||||||
|
**Design System:**
|
||||||
|
- [ ] Teal colors consistent overal
|
||||||
|
- [ ] Amber AI buttons duidelijk
|
||||||
|
- [ ] Contrast ratios WCAG AA compliant
|
||||||
|
- [ ] Focus states zichtbaar
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Demo & Presentatieplan
|
||||||
|
|
||||||
|
🎯 **Doel:** Beschrijven hoe de demo wordt gepresenteerd.
|
||||||
|
|
||||||
|
### Demo Scenario
|
||||||
|
|
||||||
|
**Duur:** 10 minuten
|
||||||
|
**Doelgroep:** GGZ innovatiemanagers + bestuurders
|
||||||
|
**Locatie:** Live op Vercel (backup: localhost)
|
||||||
|
|
||||||
|
**Flow:**
|
||||||
|
1. **Intro** (1 min): Homepage - Statement + Timeline overview
|
||||||
|
2. **Features showcase** (2 min): Timeline scrollen, features per week zien
|
||||||
|
3. **Login** (1 min): Login pagina met features showcase
|
||||||
|
4. **EPD demo** (4 min):
|
||||||
|
- Client lijst
|
||||||
|
- Nieuwe intake maken
|
||||||
|
- AI samenvatting genereren
|
||||||
|
- Profile + Plan tabs
|
||||||
|
5. **Afsluiting** (2 min): Vragen + LinkedIn build-in-public link
|
||||||
|
|
||||||
|
**Backup Plan:**
|
||||||
|
- Lokale versie klaar bij internet issues
|
||||||
|
- Pre-seeded data als AI API niet reageert
|
||||||
|
- Screenshots als complete fallback
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Risico's & Mitigatie
|
||||||
|
|
||||||
|
🎯 **Doel:** Risico's vroeg signaleren en voorzien van oplossingen.
|
||||||
|
|
||||||
|
| Risico | Kans | Impact | Mitigatie | Owner |
|
||||||
|
|--------|------|--------|-----------|-------|
|
||||||
|
| Teal design niet goed ontvangen | Laag | Middel | Rollback plan (1 uur), hybrid approach mogelijk | Developer |
|
||||||
|
| Timeline component complex | Middel | Middel | Aceternity UI pattern gebruiken, simplify indien nodig | Developer |
|
||||||
|
| Features data structuur te complex | Middel | Laag | Start simpel, iteratief uitbreiden | Developer |
|
||||||
|
| AI-output inconsistent | Hoog | Hoog | Snapshot tests, prompt versioning, fallback responses | Developer |
|
||||||
|
| API rate limits tijdens demo | Middel | Hoog | Caching, pre-warmed responses, backup data | Developer |
|
||||||
|
| Tijdsdruk deadline | Hoog | Middel | Prioriteer MVP features, cut scope indien nodig | Developer |
|
||||||
|
| Login pagina layout niet responsive | Laag | Middel | Test op mobile early, stack layout fallback | Developer |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Evaluatie & Lessons Learned
|
||||||
|
|
||||||
|
🎯 **Doel:** Reflecteren op het proces en verbeteringen vastleggen.
|
||||||
|
|
||||||
|
**Te documenteren na project:**
|
||||||
|
- Wat ging goed? Wat niet?
|
||||||
|
- Was teal-first design de juiste keuze?
|
||||||
|
- Werkt vereenvoudigde user journey beter?
|
||||||
|
- Welke AI-tools waren het meest effectief?
|
||||||
|
- Welke prompts werkten het beste?
|
||||||
|
- Waar liepen we vertraging op?
|
||||||
|
- Wat doen we volgende keer anders?
|
||||||
|
- Herbruikbare componenten voor volgende projecten
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Referenties
|
||||||
|
|
||||||
|
🎯 **Doel:** Koppelen aan de overige Mission Control-documenten.
|
||||||
|
|
||||||
|
**Mission Control Documents:**
|
||||||
|
- **PRD v1.2** — `docs/specs/prd-mini-ecd-v2.md` - Product Requirements & Business Case
|
||||||
|
- **FO v2.1** — `docs/specs/fo-marketing-app-flow-v2.md` - Functioneel Ontwerp (vereenvoudigde user journey)
|
||||||
|
- **UX Plan v2.0** — `docs/specs/ux-implementation-plan-v2.md` - Teal-first design system
|
||||||
|
- **TO v1.2** — `docs/specs/to-mini-ecd-v1_2.md` - Technische Architectuur & Database Schema
|
||||||
|
- **API Specs** — `docs/specs/api-acces-mini-ecd.md` - Endpoint Documentation
|
||||||
|
|
||||||
|
**External Resources:**
|
||||||
|
- Repository: GitHub (public voor transparantie)
|
||||||
|
- Deployment: Vercel (EU region Amsterdam)
|
||||||
|
- Design: Tailwind CSS + shadcn/ui
|
||||||
|
- Documentation: `/docs` folder in repo
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Glossary & Abbreviations
|
||||||
|
|
||||||
|
| Term | Betekenis |
|
||||||
|
|------|-----------|
|
||||||
|
| Epic | Grote feature of fase in development (bevat meerdere stories) |
|
||||||
|
| Story | Kleine, uitvoerbare taak binnen een epic |
|
||||||
|
| Story Points | Schatting van complexiteit (Fibonacci: 1, 2, 3, 5, 8, 13) |
|
||||||
|
| MVP | Minimum Viable Product |
|
||||||
|
| DRY | Don't Repeat Yourself |
|
||||||
|
| KISS | Keep It Simple, Stupid |
|
||||||
|
| SOC | Separation of Concerns |
|
||||||
|
| YAGNI | You Aren't Gonna Need It |
|
||||||
|
| RLS | Row Level Security (Supabase) |
|
||||||
|
| WCAG | Web Content Accessibility Guidelines |
|
||||||
|
| LCP | Largest Contentful Paint (performance metric) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Versiehistorie
|
||||||
|
|
||||||
|
| Versie | Datum | Auteur | Wijziging |
|
||||||
|
|--------|-------|--------|-----------|
|
||||||
|
| v2.1 | 17-11-2024 | Colin | Nieuw bouwplan op basis van FO v2.1 (vereenvoudigde user journey) en UX Plan v2.0 (teal-first design). Verwijderd: EPD demo pagina. Nieuw: Timeline met features, login met features showcase. |
|
||||||
|
| v1.6 | 15-11-2024 | Colin | Eerdere versie met separate EPD demo pagina |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Status:** Ready for Week 1 Implementation
|
||||||
|
**Next Action:** Begin Epic 1 (Marketing Website Refactor)
|
||||||
|
**Owner:** Colin Lit
|
||||||
|
**Timeline:** Week 1-4 (4 weken sprint)
|
||||||
|
|
||||||
699
docs/specs/fo-marketing-app-flow-v2.md
Normal file
699
docs/specs/fo-marketing-app-flow-v2.md
Normal file
@@ -0,0 +1,699 @@
|
|||||||
|
# 🧩 Functioneel Ontwerp (FO) – Marketing & App Flow v2.1
|
||||||
|
|
||||||
|
**Projectnaam:** AI Speedrun - Mini-EPD Prototype
|
||||||
|
**Versie:** v2.1 (Vereenvoudigde User Journey)
|
||||||
|
**Datum:** 17-11-2024
|
||||||
|
**Auteur:** Colin Lit
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Doel en relatie met het PRD
|
||||||
|
|
||||||
|
🎯 **Doel van dit document:**
|
||||||
|
Dit Functioneel Ontwerp beschrijft de **vereenvoudigde user journey** voor de AI Speedrun marketing website en EPD applicatie. Het lost de huidige UX problemen op (broken links, onduidelijke navigatie) en introduceert een heldere scheiding tussen marketing en applicatie.
|
||||||
|
|
||||||
|
📘 **Toelichting aan de lezer:**
|
||||||
|
Versie 2.0 is een refactor van de huidige implementatie (v1.2). De belangrijkste wijzigingen:
|
||||||
|
- **Marketing vereenvoudigd**: Van lange manifesto naar compacte statement + timeline met features
|
||||||
|
- **Geen separate EPD demo pagina**: Features worden getoond in timeline op homepage en op login pagina
|
||||||
|
- **Duidelijke app routing**: `/epd/*` namespace voor alle EPD functionaliteit
|
||||||
|
- **Werkende flows**: Alle CTA's en login links gaan naar bestaande pagina's
|
||||||
|
- **Coming Soon strategie**: Eerlijke communicatie tijdens Week 2 development
|
||||||
|
|
||||||
|
Dit document is niet-technisch en beschrijft wat gebruikers zien en kunnen doen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Overzicht van de belangrijkste onderdelen
|
||||||
|
|
||||||
|
🎯 **Doel:** De 4 kernmodules van de applicatie
|
||||||
|
|
||||||
|
**Marketing Modules (Publiek):**
|
||||||
|
1. **Marketing Homepage** (`/`) - Vereenvoudigde landing met hero, statement en timeline (met features)
|
||||||
|
2. **Contact & Leads** (`/contact`) - Lead capture formulier
|
||||||
|
|
||||||
|
**Auth & App Modules (Protected/Semi-Protected):**
|
||||||
|
3. **Login & Authentication** (`/login`) - Magic link + demo credentials + features showcase
|
||||||
|
4. **EPD App Dashboard** (`/epd/clients`) - Coming Soon placeholder (Week 2+)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. User Stories
|
||||||
|
|
||||||
|
🎯 **Doel:** Wat gebruikers kunnen en willen doen
|
||||||
|
|
||||||
|
### Prioriteit: Hoog (MVP Critical)
|
||||||
|
|
||||||
|
| ID | Rol | Doel / Actie | Verwachte waarde | Status |
|
||||||
|
|----|-----|--------------|------------------|--------|
|
||||||
|
| US-01 | Marketing bezoeker | Homepage bekijken met project statement en voortgang | Begrijpen wat AI Speedrun doet en volgen van build progress + features zien | ✅ Te implementeren |
|
||||||
|
| US-02 | Marketing bezoeker | EPD features bekijken in timeline | Zien wat het prototype kan (features getoond in timeline op homepage) | ✅ Te implementeren |
|
||||||
|
| US-03 | Marketing bezoeker | Contact opnemen voor lead | Interesse tonen in Software on Demand services | ✅ Bestaand |
|
||||||
|
| US-04 | Demo gebruiker | Inloggen met demo credentials | Toegang tot EPD app prototype | ✅ Bestaand (fix redirect) |
|
||||||
|
| US-05 | Demo gebruiker | Coming Soon dashboard zien | Weten dat app in Week 2 komt + verwachtingen managen | ✅ Te implementeren |
|
||||||
|
| US-06 | Terugkerende gebruiker | Direct naar login navigeren | Snel inloggen zonder homepage te moeten bezoeken | ✅ Te implementeren (nav link) |
|
||||||
|
|
||||||
|
### Prioriteit: Middel (Nice to Have)
|
||||||
|
|
||||||
|
| ID | Rol | Doel / Actie | Verwachte waarde | Status |
|
||||||
|
|----|-----|--------------|------------------|--------|
|
||||||
|
| US-07 | Ingelogde gebruiker | Uitloggen | Sessie beëindigen en terug naar marketing | 🔄 Toekomstig |
|
||||||
|
| US-08 | Marketing bezoeker | Wekelijkse updates volgen via timeline | Build in public transparantie ervaren | ✅ Te implementeren |
|
||||||
|
| US-09 | Stakeholder | ROI vergelijking zien | Business case begrijpen (traditioneel vs AI) | ⏸️ On hold |
|
||||||
|
|
||||||
|
### Prioriteit: Laag (Future Enhancement)
|
||||||
|
|
||||||
|
| ID | Rol | Doel / Actie | Verwachte waarde | Status |
|
||||||
|
|----|-----|--------------|------------------|--------|
|
||||||
|
| US-10 | Developer | Interactieve ROI calculator gebruiken | Eigen business case berekenen | ⏸️ On hold |
|
||||||
|
| US-11 | LinkedIn volger | Build metrics dashboard zien | Real-time tracking van uren en kosten | ⏸️ On hold |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Functionele werking per onderdel
|
||||||
|
|
||||||
|
🎯 **Doel:** Per module beschrijven wat gebruikers kunnen doen
|
||||||
|
|
||||||
|
### 4.1 Marketing Homepage (`/`)
|
||||||
|
|
||||||
|
**Doel:** Compacte, krachtige introductie van Software on Demand concept met build-in-public transparantie.
|
||||||
|
|
||||||
|
**Secties (van boven naar beneden):**
|
||||||
|
|
||||||
|
1. **Hero Section** (behouden zoals nu)
|
||||||
|
- Full-viewport quote van Jensen Huang: "Software is eating the world"
|
||||||
|
- Dot-shader achtergrond (subtiel, opacity 0.02)
|
||||||
|
- Scroll indicator
|
||||||
|
|
||||||
|
2. **Statement Section** (NIEUW - vervangt lange manifesto)
|
||||||
|
- **Heading**: "Software on Demand: Van €100k naar €200"
|
||||||
|
- **3-4 Paragrafen** in problem → solution → proof format:
|
||||||
|
- *Problem*: Enterprise software kost €100.000+ en duurt 12-24 maanden
|
||||||
|
- *Solution*: AI-powered development verkort dit naar 4 weken en €200
|
||||||
|
- *Proof*: Dit EPD is het bewijs - gebouwd in 4 weken, build in public
|
||||||
|
- *CTA*: Volg de voortgang hieronder
|
||||||
|
- **Visueel**: Clean, serif typography (Crimson Text), breathing room
|
||||||
|
|
||||||
|
3. **Timeline Section** (NIEUW - build in public met features showcase)
|
||||||
|
- **Component**: Aceternity UI Timeline (21st.dev)
|
||||||
|
- **Content structure** per week:
|
||||||
|
- Week nummer + datum range (bijv. "Week 1 • Nov 11-17")
|
||||||
|
- Status badge: Completed / In Progress / Planned
|
||||||
|
- Korte beschrijving (3-4 zinnen): wat is er gebouwd
|
||||||
|
- **Features showcase** (NIEUW):
|
||||||
|
- Per week worden relevante EPD features getoond
|
||||||
|
- Feature cards met: Titel, beschrijving, tijdswinst (bijv. "30 min → 5 sec")
|
||||||
|
- Icons per feature type (Brain voor AI, Zap voor snelheid, etc.)
|
||||||
|
- Visuele highlight van wat er die week gebouwd is
|
||||||
|
- Metrics cards: Development hours, Infrastructure cost
|
||||||
|
- Achievements lijst: Bullets met voltooide features
|
||||||
|
- Optioneel: Screenshot of visual van die week
|
||||||
|
- **Interactie**: Scroll-based animation (timeline ontvouwt)
|
||||||
|
- **Data source**: `content/nl/timeline.json` (met features array per week)
|
||||||
|
|
||||||
|
4. **CTA Section** (vereenvoudigd)
|
||||||
|
- **Primary CTA**: "Probeer het prototype" → `/login` (direct naar login met features)
|
||||||
|
- **Secondary CTA**: "Volg voortgang" → Scroll to timeline (anchor link `#timeline`)
|
||||||
|
- **Tertiary**: "Contact" → `/contact`
|
||||||
|
- **Visueel**: Button hierarchy duidelijk (primary = green, secondary = outline)
|
||||||
|
|
||||||
|
**Verwijderd uit v1.2:**
|
||||||
|
- Lange manifesto content (8000+ woorden)
|
||||||
|
- Separate EPD demo pagina (`/epd`) - features nu in timeline
|
||||||
|
- Comparison table (verwijderd - niet meer nodig)
|
||||||
|
- Multiple insight boxes
|
||||||
|
- Statement sections met dark backgrounds
|
||||||
|
|
||||||
|
**States:**
|
||||||
|
- **Normal**: Alle content zichtbaar
|
||||||
|
- **Loading**: Skeleton voor timeline items
|
||||||
|
- **Empty state**: (niet van toepassing - statische content)
|
||||||
|
|
||||||
|
**Navigatie:**
|
||||||
|
- Top: MinimalNav (Home, Contact, Login) - EPD Prototype link verwijderd
|
||||||
|
- Footer: Copyright + link naar ikbenlit.nl
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.2 ~~EPD Demo Info Pagina (`/epd`)~~ VERWIJDERD
|
||||||
|
|
||||||
|
**Status:** Deze pagina is verwijderd in v2.1. Features worden nu getoond in:
|
||||||
|
- Timeline op homepage (`/`)
|
||||||
|
- Features showcase op login pagina (`/login`)
|
||||||
|
|
||||||
|
**Reden:** Vereenvoudiging van user journey - gebruikers zien features direct in context van build progress en kunnen direct naar login gaan.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.3 Contact & Lead Capture (`/contact`)
|
||||||
|
|
||||||
|
**Doel:** Lead acquisition voor Software on Demand consultancy.
|
||||||
|
|
||||||
|
**Functionaliteit:** (behouden zoals nu - werkt al)
|
||||||
|
- Form fields: Naam, Email, Bericht
|
||||||
|
- Client-side validation (Zod)
|
||||||
|
- Submit → API `/api/leads` → Supabase `leads` table
|
||||||
|
- Success state: "Bedankt! We nemen contact op"
|
||||||
|
- Error state: "Er ging iets mis. Probeer opnieuw"
|
||||||
|
|
||||||
|
**Navigatie:**
|
||||||
|
- Terug naar homepage via nav
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.4 Login & Authentication (`/login`)
|
||||||
|
|
||||||
|
**Doel:** Flexibele auth met magic link (productie) en demo credentials (MVP), inclusief features showcase.
|
||||||
|
|
||||||
|
**Layout:** Split-screen design (zoals `sign-in.tsx` component)
|
||||||
|
- **Links (60%)**: Features showcase met visuals
|
||||||
|
- **Rechts (40%)**: Login formulier
|
||||||
|
|
||||||
|
**Features Showcase Sectie (Links):**
|
||||||
|
- **Grid layout** met feature cards:
|
||||||
|
- AI-Gestuurde Intake (30 min → 5 sec)
|
||||||
|
- Automatische DSM Classificatie (15 min → 3 sec)
|
||||||
|
- Behandelplan Generatie (45 min → 10 sec)
|
||||||
|
- B1 Readability (30 min → 3 sec)
|
||||||
|
- **Visuals**: Icons, stat cards, of screenshots per feature
|
||||||
|
- **Metrics**: Tijdswinst per feature prominent getoond
|
||||||
|
- **Design**: Inspiratie van `components/ui/sign-in.tsx` collage layout
|
||||||
|
|
||||||
|
**Login Form Sectie (Rechts):**
|
||||||
|
|
||||||
|
**Twee tabs/modes:**
|
||||||
|
|
||||||
|
1. **Magic Link Login** (voor productie users)
|
||||||
|
- Email input
|
||||||
|
- "Stuur Magic Link" button
|
||||||
|
- Success: "Check je email voor login link"
|
||||||
|
- Nieuwe users: Account wordt automatisch aangemaakt
|
||||||
|
- Callback: `/auth/callback` → redirect naar `/epd/clients`
|
||||||
|
|
||||||
|
2. **Demo Credentials Login** (voor demo)
|
||||||
|
- Email + Password inputs
|
||||||
|
- Toggle show/hide password
|
||||||
|
- "Login" button
|
||||||
|
- Quick demo button: Auto-fill + submit
|
||||||
|
- Success: Redirect naar `/epd/clients`
|
||||||
|
- Error: "Ongeldige credentials"
|
||||||
|
|
||||||
|
**Demo credentials info box:**
|
||||||
|
- Gele achtergrond
|
||||||
|
- Credentials in monospace font
|
||||||
|
- Copy-paste friendly
|
||||||
|
|
||||||
|
**States:**
|
||||||
|
- Loading: "Inloggen..." spinner
|
||||||
|
- Error: Red error message
|
||||||
|
- Success: Green message + redirect
|
||||||
|
- Mobile: Features sectie wordt boven login form getoond (stack layout)
|
||||||
|
|
||||||
|
**Navigatie:**
|
||||||
|
- Link in MinimalNav: "Login"
|
||||||
|
- Logo → terug naar `/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.5 EPD App - Coming Soon Dashboard (`/epd/clients`)
|
||||||
|
|
||||||
|
**Doel:** Eerlijke communicatie dat app in Week 2 gebouwd wordt, manage expectations.
|
||||||
|
|
||||||
|
**Functionaliteit:** (NIEUW - te bouwen)
|
||||||
|
|
||||||
|
**Layout:**
|
||||||
|
```
|
||||||
|
┌────────────────────────────────────────────┐
|
||||||
|
│ Header: Logo | "EPD Dashboard" | Logout │
|
||||||
|
├────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ [Icon] Coming Soon │
|
||||||
|
│ │
|
||||||
|
│ EPD Dashboard - In Ontwikkeling │
|
||||||
|
│ │
|
||||||
|
│ Week 2 (Nov 18-24): Client management │
|
||||||
|
│ Week 3 (Nov 25-Dec 1): AI integrations │
|
||||||
|
│ │
|
||||||
|
│ [Mockup screenshot placeholder] │
|
||||||
|
│ │
|
||||||
|
│ [Button: Terug naar Info] [Logout] │
|
||||||
|
│ │
|
||||||
|
└────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Content:**
|
||||||
|
- **Heading**: "EPD Dashboard - Coming Week 2"
|
||||||
|
- **Beschrijving**:
|
||||||
|
- "De EPD applicatie wordt momenteel gebouwd."
|
||||||
|
- "Bekijk de voortgang op de homepage (timeline sectie)"
|
||||||
|
- **Timeline preview**:
|
||||||
|
- Week 2: Client management & CRUD
|
||||||
|
- Week 3: AI integrations (intake, profiel, plan)
|
||||||
|
- Week 4: Polish & onboarding
|
||||||
|
- **Mockup/Screenshot**: Wireframe of visual preview van wat komt
|
||||||
|
- **Actions**:
|
||||||
|
- Button: "Terug naar Prototype Info" → `/epd`
|
||||||
|
- Button: "Logout" → `/auth/logout` → redirect `/`
|
||||||
|
|
||||||
|
**States:**
|
||||||
|
- **Authenticated**: Normale weergave
|
||||||
|
- **Not authenticated**: Redirect naar `/login` (middleware)
|
||||||
|
|
||||||
|
**Navigatie:**
|
||||||
|
- Logo → `/epd/clients` (blijf in app context)
|
||||||
|
- "Terug naar Info" → `/epd` (exit app)
|
||||||
|
- Logout → `/` (marketing)
|
||||||
|
|
||||||
|
**Future states (Week 2+):**
|
||||||
|
- Replace Coming Soon met werkende client lijst
|
||||||
|
- Zelfde layout, andere content
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. UI-overzicht (visuele structuur)
|
||||||
|
|
||||||
|
🎯 **Doel:** Globale schermopbouw voor developers en designers
|
||||||
|
|
||||||
|
### 5.1 Marketing Layout (alle publieke paginas)
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────┐
|
||||||
|
│ MinimalNav (fixed top) │
|
||||||
|
│ [Logo] Home | Contact | Login │
|
||||||
|
├─────────────────────────────────────────────────────┤
|
||||||
|
│ ReadingProgress (scroll-based bar) │
|
||||||
|
├─────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ Page Content │
|
||||||
|
│ (hero, statement, timeline, │
|
||||||
|
│ features, forms, etc.) │
|
||||||
|
│ │
|
||||||
|
├─────────────────────────────────────────────────────┤
|
||||||
|
│ Footer: © AI Speedrun | ikbenlit.nl │
|
||||||
|
└─────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Minimal navigation: scroll-based color change
|
||||||
|
- Reading progress bar (client component)
|
||||||
|
- No sidebar
|
||||||
|
- Full-width content
|
||||||
|
- Mobile: Hamburger menu
|
||||||
|
|
||||||
|
### 5.2 EPD App Layout (protected paginas)
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────┐
|
||||||
|
│ App Header │
|
||||||
|
│ [Logo: EPD] EPD Dashboard [User] [Logout] │
|
||||||
|
├─────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ Main Content │
|
||||||
|
│ (coming soon state │
|
||||||
|
│ of client list future) │
|
||||||
|
│ │
|
||||||
|
├─────────────────────────────────────────────────────┤
|
||||||
|
│ Footer: Terug naar Info | ikbenlit.nl │
|
||||||
|
└─────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Separate header (geen MinimalNav)
|
||||||
|
- User state visible
|
||||||
|
- Logout prominent
|
||||||
|
- Exit to marketing link
|
||||||
|
- Future: Sidebar toevoegen voor app nav
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Navigatie Flows & User Journeys
|
||||||
|
|
||||||
|
🎯 **Doel:** Visualiseren hoe gebruikers door de applicatie bewegen
|
||||||
|
|
||||||
|
### Flow 1: Marketing Bezoeker → Lead
|
||||||
|
|
||||||
|
```
|
||||||
|
Landing (/)
|
||||||
|
↓
|
||||||
|
Lees Statement + Timeline (met features)
|
||||||
|
↓
|
||||||
|
Decision Point:
|
||||||
|
├─→ "Probeer het prototype" → /login
|
||||||
|
│ ↓
|
||||||
|
│ Zie features showcase + login form
|
||||||
|
│ ↓
|
||||||
|
│ Login met demo credentials
|
||||||
|
│ ↓
|
||||||
|
│ /epd/clients (Coming Soon)
|
||||||
|
│
|
||||||
|
└─→ "Contact" → /contact
|
||||||
|
↓
|
||||||
|
Vul formulier in
|
||||||
|
↓
|
||||||
|
Lead opgeslagen ✓
|
||||||
|
```
|
||||||
|
|
||||||
|
### Flow 2: Demo Gebruiker → EPD App
|
||||||
|
|
||||||
|
```
|
||||||
|
Direct naar /login (nav link)
|
||||||
|
↓
|
||||||
|
Kies: Magic Link OF Demo Credentials
|
||||||
|
↓
|
||||||
|
[Demo pad]
|
||||||
|
Fill demo@mini-ecd.demo + Demo2024!
|
||||||
|
↓
|
||||||
|
Submit
|
||||||
|
↓
|
||||||
|
Auth success → Middleware redirect
|
||||||
|
↓
|
||||||
|
/epd/clients (Coming Soon)
|
||||||
|
↓
|
||||||
|
Options:
|
||||||
|
├─→ "Terug naar Info" → /epd
|
||||||
|
└─→ "Logout" → /
|
||||||
|
```
|
||||||
|
|
||||||
|
### Flow 3: Terugkerende Gebruiker (Week 2+)
|
||||||
|
|
||||||
|
```
|
||||||
|
Homepage / or direct /login
|
||||||
|
↓
|
||||||
|
Login (magic link of credentials)
|
||||||
|
↓
|
||||||
|
/epd/clients (werkende app)
|
||||||
|
↓
|
||||||
|
Client lijst → Client detail
|
||||||
|
↓
|
||||||
|
Intake → AI → Profiel → Plan
|
||||||
|
↓
|
||||||
|
Logout → terug naar marketing
|
||||||
|
```
|
||||||
|
|
||||||
|
### Flow 4: Build-in-Public Volger
|
||||||
|
|
||||||
|
```
|
||||||
|
LinkedIn post → Homepage
|
||||||
|
↓
|
||||||
|
Scroll naar Timeline (met features per week)
|
||||||
|
↓
|
||||||
|
Lees weekly updates + zie features
|
||||||
|
↓
|
||||||
|
Decision:
|
||||||
|
├─→ "Probeer demo" → /login (met features showcase)
|
||||||
|
├─→ "Contact" → /contact
|
||||||
|
└─→ Exit (volg op LinkedIn)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Interacties met AI (functionele beschrijving)
|
||||||
|
|
||||||
|
🎯 **Doel:** Waar AI voorkomt in toekomstige EPD app (Week 3+)
|
||||||
|
|
||||||
|
📘 **Toelichting:** Deze sectie beschrijft toekomstige AI features die nog niet in Coming Soon state zitten.
|
||||||
|
|
||||||
|
| Locatie | AI-actie | Trigger | Input | Output | Timing |
|
||||||
|
|---------|----------|---------|-------|--------|--------|
|
||||||
|
| Intake Editor | Samenvatten | Button "AI Samenvatten" | TipTap editor content (max 20k chars) | 5-8 bullets in rechterpaneel | ~3-5 sec |
|
||||||
|
| Intake Editor | B1 Leesbaarheid | Button "Vereenvoudig taal" | Selected text of hele intake | Herschreven versie in B1 Nederlands | ~5 sec |
|
||||||
|
| Profiel Tab | Extract Problemen | Button "AI Analyse" | Intake content | DSM-light categorie + severity + rationale | ~5-8 sec |
|
||||||
|
| Plan Tab | Genereer Plan | Button "Genereer Behandelplan" | Profiel + intake data | 4 secties: Doelen, Interventies, Freq/Duur, Meetmomenten | ~10-15 sec |
|
||||||
|
|
||||||
|
**AI-rail (rechterpaneel) gedrag:**
|
||||||
|
- Slides in vanaf rechts bij AI actie
|
||||||
|
- Loading state: Spinner + "AI analyseert..."
|
||||||
|
- Result state: Content + bronverwijzingen
|
||||||
|
- Actions: "Invoegen", "Regenereer", "Annuleer"
|
||||||
|
- Preview mode: Highlight waar content ingevoegd wordt
|
||||||
|
|
||||||
|
**Cost tracking** (toekomstig):
|
||||||
|
- Alle AI calls worden gelogd in `ai_events` table
|
||||||
|
- Dashboard toont: Aantal calls, tokens gebruikt, geschatte kosten
|
||||||
|
- Target: <€5/maand voor MVP demo use
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Routes & Toegangsrechten
|
||||||
|
|
||||||
|
🎯 **Doel:** Duidelijk overzicht welke routes publiek of protected zijn
|
||||||
|
|
||||||
|
### Publieke Routes (geen auth vereist)
|
||||||
|
|
||||||
|
| Route | Naam | Functie | Status |
|
||||||
|
|-------|------|---------|--------|
|
||||||
|
| `/` | Marketing Homepage | Statement + Timeline (met features) | ✅ Refactor |
|
||||||
|
| `/contact` | Contact Form | Lead capture | ✅ Bestaand |
|
||||||
|
| `/login` | Login Pagina | Auth flow + features showcase | ✅ Refactor |
|
||||||
|
| `/auth/callback` | OAuth Callback | Magic link handler | ✅ Bestaand |
|
||||||
|
|
||||||
|
**Verwijderd:**
|
||||||
|
- `/epd` - EPD Demo Info pagina (features nu in timeline en login)
|
||||||
|
|
||||||
|
### Protected Routes (auth vereist)
|
||||||
|
|
||||||
|
| Route | Naam | Functie | Status |
|
||||||
|
|-------|------|---------|--------|
|
||||||
|
| `/epd/clients` | EPD Dashboard | Coming Soon (Week 2: Client lijst) | ⏳ Te bouwen |
|
||||||
|
| `/epd/clients/[id]` | Client Detail | Client dossier (Week 2) | 🔄 Toekomstig |
|
||||||
|
| `/epd/clients/[id]/intake` | Intake Editor | TipTap + AI (Week 3) | 🔄 Toekomstig |
|
||||||
|
| `/epd/clients/[id]/profile` | Probleem Profiel | DSM-light + AI (Week 3) | 🔄 Toekomstig |
|
||||||
|
| `/epd/clients/[id]/plan` | Behandelplan | SMART doelen + AI (Week 3) | 🔄 Toekomstig |
|
||||||
|
|
||||||
|
### API Routes
|
||||||
|
|
||||||
|
| Route | Naam | Functie | Auth | Status |
|
||||||
|
|-------|------|---------|------|--------|
|
||||||
|
| `/api/leads` | Lead Submission | POST contact form data | No | ✅ Bestaand |
|
||||||
|
| `/api/ai/summarize` | AI Summarize | POST intake → bullets | Yes | 🔄 Week 3 |
|
||||||
|
| `/api/ai/categorize` | AI Categorize | POST intake → DSM profile | Yes | 🔄 Week 3 |
|
||||||
|
| `/api/ai/plan` | AI Plan Generator | POST profile → treatment plan | Yes | 🔄 Week 3 |
|
||||||
|
| `/auth/logout` | Logout | Supabase signOut | Yes | ✅ Bestaand |
|
||||||
|
|
||||||
|
### Middleware Logic (simplified)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Public routes (no redirect)
|
||||||
|
const publicRoutes = [
|
||||||
|
'/', '/contact', '/login',
|
||||||
|
'/auth/callback', '/auth/logout'
|
||||||
|
]
|
||||||
|
|
||||||
|
// Logic
|
||||||
|
if (!user && !isPublicRoute) {
|
||||||
|
redirect('/login?redirect=' + pathname)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user && pathname === '/login') {
|
||||||
|
redirect('/epd/clients')
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Content Management Strategie
|
||||||
|
|
||||||
|
🎯 **Doel:** Hoe content beheerd en bijgewerkt wordt
|
||||||
|
|
||||||
|
### Timeline Content (Build-in-Public updates)
|
||||||
|
|
||||||
|
**Locatie**: `content/timeline/` of `content/nl/timeline.json`
|
||||||
|
|
||||||
|
**Structuur per week**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"weekNumber": 1,
|
||||||
|
"title": "Week 1 • Nov 11-17",
|
||||||
|
"status": "completed", // completed | in_progress | planned
|
||||||
|
"description": "Marketing site foundation. Hero, statement setup, database schema aangemaakt.",
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"title": "AI-Gestuurde Intake",
|
||||||
|
"description": "Schrijf een intakeverslag en krijg binnen seconden een gestructureerde samenvatting",
|
||||||
|
"time": "< 5 seconden",
|
||||||
|
"traditional": "15-20 minuten handmatig",
|
||||||
|
"icon": "Brain"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Automatische DSM Classificatie",
|
||||||
|
"description": "Het systeem analyseert de intake en stelt DSM-categorieën voor",
|
||||||
|
"time": "< 3 seconden",
|
||||||
|
"traditional": "10-15 minuten analyse",
|
||||||
|
"icon": "Zap"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metrics": {
|
||||||
|
"developmentHours": 30,
|
||||||
|
"infrastructureCost": 50,
|
||||||
|
"totalCost": 50
|
||||||
|
},
|
||||||
|
"achievements": [
|
||||||
|
"Landing page met hero + statement",
|
||||||
|
"Timeline component met features",
|
||||||
|
"Contact form + lead capture API",
|
||||||
|
"Database schema (5 core tables)",
|
||||||
|
"Supabase Auth + RLS policies"
|
||||||
|
],
|
||||||
|
"visual": "/timeline/week-1-screenshot.png" // optional
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Update frequency**: Einde van elke week (zaterdag/zondag)
|
||||||
|
|
||||||
|
**Ownership**: Handmatig door Colin via JSON edit
|
||||||
|
|
||||||
|
**Alternative**: MDX files met frontmatter voor meer flexibiliteit
|
||||||
|
|
||||||
|
### Static Content (niet-timeline)
|
||||||
|
|
||||||
|
| Content Type | Locatie | Format | Update Freq |
|
||||||
|
|--------------|---------|--------|-------------|
|
||||||
|
| Navigation | `content/nl/navigation.json` | JSON | Ad-hoc |
|
||||||
|
| Timeline (met features) | `content/nl/timeline.json` | JSON | Weekly |
|
||||||
|
| EPD Features (voor login) | `content/nl/epd.json` | JSON | Rarely |
|
||||||
|
| Metadata (SEO) | `content/nl/metadata.json` | JSON | Once |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Gebruikersrollen en rechten
|
||||||
|
|
||||||
|
🎯 **Doel:** Wie kan wat binnen de applicatie
|
||||||
|
|
||||||
|
| Rol | Toegang tot | Beperkingen | Auth Method |
|
||||||
|
|-----|-------------|-------------|-------------|
|
||||||
|
| **Anonymous Visitor** | Marketing pages (/, /contact, /login) | Geen EPD app toegang | - |
|
||||||
|
| **Demo User** | Alles (marketing + EPD app) | Fictieve data only, geen wijzigingen persistent | Email/password (demo credentials) |
|
||||||
|
| **Magic Link User** | Marketing + EPD app (toekomstig) | Eigen dossiers (RLS) | Magic link email |
|
||||||
|
| **Admin** (toekomstig) | Alle dossiers + metrics | - | Special credentials |
|
||||||
|
|
||||||
|
**RLS (Row Level Security) in Supabase:**
|
||||||
|
- Elke gebruiker ziet alleen eigen clients/notes/profiles/plans
|
||||||
|
- Policy: `auth.uid() = created_by`
|
||||||
|
- Demo users delen fictieve dataset
|
||||||
|
- Real users: isolated per user_id
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. States & Edge Cases
|
||||||
|
|
||||||
|
🎯 **Doel:** Hoe systeem omgaat met uitzonderlijke situaties
|
||||||
|
|
||||||
|
### Marketing Website
|
||||||
|
|
||||||
|
| Scenario | Gedrag |
|
||||||
|
|----------|--------|
|
||||||
|
| Timeline data niet beschikbaar | Toon skeleton loading + "Updates coming soon" |
|
||||||
|
| Image load failure | Fallback naar placeholder met initials |
|
||||||
|
| Form submission error | Retry optie + error message + support email |
|
||||||
|
| Slow network | Progressive loading, defer non-critical content |
|
||||||
|
|
||||||
|
### Login Flow
|
||||||
|
|
||||||
|
| Scenario | Gedrag |
|
||||||
|
|----------|--------|
|
||||||
|
| Ongeldige demo credentials | Error: "Credentials incorrect. Gebruik demo@mini-ecd.demo" |
|
||||||
|
| Magic link expired | Error + "Request new link" button |
|
||||||
|
| Already logged in | Direct redirect naar `/epd/clients` |
|
||||||
|
| Network error tijdens auth | Error message + retry button |
|
||||||
|
|
||||||
|
### EPD App (Coming Soon)
|
||||||
|
|
||||||
|
| Scenario | Gedrag |
|
||||||
|
|----------|--------|
|
||||||
|
| User bezoekt direct `/epd/clients` | Middleware check → redirect `/login` als niet ingelogd |
|
||||||
|
| Logout tijdens session | Redirect naar `/` + success toast |
|
||||||
|
| Session expired | Redirect naar `/login` + "Session verlopen, log opnieuw in" |
|
||||||
|
|
||||||
|
### Week 2+ (Toekomstig - Client CRUD)
|
||||||
|
|
||||||
|
| Scenario | Gedrag |
|
||||||
|
|----------|--------|
|
||||||
|
| Lege state (geen clients) | "Voeg je eerste cliënt toe" + CTA button |
|
||||||
|
| Delete confirmation | Modal: "Weet je zeker? Alle dossiers worden verwijderd" |
|
||||||
|
| Concurrent edit conflict | Toast: "Data is veranderd, herlaad pagina" |
|
||||||
|
| AI API failure | Retry 3x, dan error + support contact |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Bijlagen & Referenties
|
||||||
|
|
||||||
|
🎯 **Doel:** Linken naar gerelateerde documenten
|
||||||
|
|
||||||
|
**Mission Control Documents:**
|
||||||
|
- **PRD v1.2** (`docs/specs/prd-mini-ecd-v2.md`) - Product Requirements & Business Case
|
||||||
|
- **TO v1.2** (`docs/specs/to-mini-ecd-v1_2.md`) - Technische Architectuur & Database Schema
|
||||||
|
- **Bouwplan v1.6** (`docs/specs/bouwplan-ai-speedrun-marketing-first-v1.1.md`) - Epic & Story Planning
|
||||||
|
- **UX Stylesheet** (`docs/specs/ux-stylesheet.md`) - Design System & Tailwind Config
|
||||||
|
- **API Specs** (`docs/specs/api-acces-mini-ecd.md`) - Endpoint Documentation
|
||||||
|
|
||||||
|
**External Resources:**
|
||||||
|
- [Aceternity UI Timeline](https://21st.dev/r/timeline) - Timeline component inspiratie
|
||||||
|
- [Supabase Auth Docs](https://supabase.com/docs/guides/auth) - Authentication flows
|
||||||
|
- [Next.js 15 Routing](https://nextjs.org/docs/app/building-your-application/routing) - App Router patterns
|
||||||
|
|
||||||
|
**Design References:**
|
||||||
|
- `docs/design/timeline-comp.tsx` - Timeline component voorbeeld
|
||||||
|
- Bestaande marketing components in `app/(marketing)/components/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. Implementatie Prioriteiten (voor Developers)
|
||||||
|
|
||||||
|
🎯 **Doel:** Volgorde van bouwen voor maximale impact
|
||||||
|
|
||||||
|
### 🔴 Critical (Week 1 fixes - nu)
|
||||||
|
|
||||||
|
1. **Verwijder EPD demo pagina** (15 min)
|
||||||
|
- Delete `/app/(marketing)/epd/page.tsx`
|
||||||
|
- Update navigation (verwijder "EPD Prototype" link)
|
||||||
|
- Update middleware (verwijder `/epd` uit public routes)
|
||||||
|
|
||||||
|
2. **Coming Soon page** (30 min)
|
||||||
|
- Create `/epd/clients/page.tsx`
|
||||||
|
- Simple layout + logout
|
||||||
|
- Middleware redirect update
|
||||||
|
|
||||||
|
### 🟡 High Priority (Week 1-2 refactor)
|
||||||
|
|
||||||
|
3. **Timeline component met features** (3-4 uur)
|
||||||
|
- Install/copy Aceternity timeline
|
||||||
|
- Create timeline content JSON met features array
|
||||||
|
- Add features showcase per week item
|
||||||
|
- Add to homepage
|
||||||
|
|
||||||
|
4. **Homepage vereenvoudiging** (2-3 uur)
|
||||||
|
- Remove manifesto long-form
|
||||||
|
- Add statement section
|
||||||
|
- Integrate timeline (met features)
|
||||||
|
- Update CTA: "Probeer het prototype" → `/login`
|
||||||
|
|
||||||
|
5. **Login pagina met features showcase** (2-3 uur)
|
||||||
|
- Split-screen layout (features links, login rechts)
|
||||||
|
- Features grid component (hergebruik van EPD features)
|
||||||
|
- Mobile responsive (stack layout)
|
||||||
|
- Integreer bestaande login functionaliteit
|
||||||
|
|
||||||
|
### 🟢 Medium Priority (Week 2 app build)
|
||||||
|
|
||||||
|
5. **EPD App foundation** (Week 2)
|
||||||
|
- Client CRUD
|
||||||
|
- App layout met sidebar
|
||||||
|
- Navigation tussen contexts
|
||||||
|
|
||||||
|
6. **AI integrations** (Week 3)
|
||||||
|
- API endpoints
|
||||||
|
- TipTap editor
|
||||||
|
- AI-rail components
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
| Versie | Datum | Auteur | Wijzigingen |
|
||||||
|
|--------|-------|--------|-------------|
|
||||||
|
| v2.0 | 17-11-2024 | Colin | Initiële versie - Refactor van v1.2 implementatie. Nieuwe timeline approach, vereenvoudigde marketing, /epd/* routing, coming soon strategie |
|
||||||
|
| v2.1 | 17-11-2024 | Colin | Verwijderd: Separate EPD demo pagina (/epd). Features nu in timeline op homepage en features showcase op login pagina. Vereenvoudigde user journey. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Einde Functioneel Ontwerp v2.1**
|
||||||
1538
docs/specs/ux-implementation-plan-v2.md
Normal file
1538
docs/specs/ux-implementation-plan-v2.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@
|
|||||||
"@supabase/supabase-js": "^2.81.1",
|
"@supabase/supabase-js": "^2.81.1",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"framer-motion": "^12.23.24",
|
||||||
"lucide-react": "^0.553.0",
|
"lucide-react": "^0.553.0",
|
||||||
"next": "16.0.1",
|
"next": "16.0.1",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
|
|||||||
38
pnpm-lock.yaml
generated
38
pnpm-lock.yaml
generated
@@ -26,6 +26,9 @@ importers:
|
|||||||
clsx:
|
clsx:
|
||||||
specifier: ^2.1.1
|
specifier: ^2.1.1
|
||||||
version: 2.1.1
|
version: 2.1.1
|
||||||
|
framer-motion:
|
||||||
|
specifier: ^12.23.24
|
||||||
|
version: 12.23.24(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||||
lucide-react:
|
lucide-react:
|
||||||
specifier: ^0.553.0
|
specifier: ^0.553.0
|
||||||
version: 0.553.0(react@19.2.0)
|
version: 0.553.0(react@19.2.0)
|
||||||
@@ -1553,6 +1556,20 @@ packages:
|
|||||||
fraction.js@5.3.4:
|
fraction.js@5.3.4:
|
||||||
resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
|
resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
|
||||||
|
|
||||||
|
framer-motion@12.23.24:
|
||||||
|
resolution: {integrity: sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==}
|
||||||
|
peerDependencies:
|
||||||
|
'@emotion/is-prop-valid': '*'
|
||||||
|
react: ^18.0.0 || ^19.0.0
|
||||||
|
react-dom: ^18.0.0 || ^19.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@emotion/is-prop-valid':
|
||||||
|
optional: true
|
||||||
|
react:
|
||||||
|
optional: true
|
||||||
|
react-dom:
|
||||||
|
optional: true
|
||||||
|
|
||||||
fsevents@2.3.3:
|
fsevents@2.3.3:
|
||||||
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
||||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||||
@@ -2023,6 +2040,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
|
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
|
||||||
engines: {node: '>=16 || 14 >=14.17'}
|
engines: {node: '>=16 || 14 >=14.17'}
|
||||||
|
|
||||||
|
motion-dom@12.23.23:
|
||||||
|
resolution: {integrity: sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==}
|
||||||
|
|
||||||
|
motion-utils@12.23.6:
|
||||||
|
resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==}
|
||||||
|
|
||||||
ms@2.1.3:
|
ms@2.1.3:
|
||||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||||
|
|
||||||
@@ -4292,6 +4315,15 @@ snapshots:
|
|||||||
|
|
||||||
fraction.js@5.3.4: {}
|
fraction.js@5.3.4: {}
|
||||||
|
|
||||||
|
framer-motion@12.23.24(react-dom@19.2.0(react@19.2.0))(react@19.2.0):
|
||||||
|
dependencies:
|
||||||
|
motion-dom: 12.23.23
|
||||||
|
motion-utils: 12.23.6
|
||||||
|
tslib: 2.8.1
|
||||||
|
optionalDependencies:
|
||||||
|
react: 19.2.0
|
||||||
|
react-dom: 19.2.0(react@19.2.0)
|
||||||
|
|
||||||
fsevents@2.3.3:
|
fsevents@2.3.3:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -4730,6 +4762,12 @@ snapshots:
|
|||||||
|
|
||||||
minipass@7.1.2: {}
|
minipass@7.1.2: {}
|
||||||
|
|
||||||
|
motion-dom@12.23.23:
|
||||||
|
dependencies:
|
||||||
|
motion-utils: 12.23.6
|
||||||
|
|
||||||
|
motion-utils@12.23.6: {}
|
||||||
|
|
||||||
ms@2.1.3: {}
|
ms@2.1.3: {}
|
||||||
|
|
||||||
mz@2.7.0:
|
mz@2.7.0:
|
||||||
|
|||||||
@@ -57,12 +57,39 @@ const config: Config = {
|
|||||||
// Borders
|
// Borders
|
||||||
border: '#E2E8F0',
|
border: '#E2E8F0',
|
||||||
|
|
||||||
// Brand & Primary
|
// Brand & Primary (Teal-first design system)
|
||||||
brand: {
|
brand: {
|
||||||
DEFAULT: '#3B82F6',
|
50: '#F0FDFA',
|
||||||
hover: '#2563EB',
|
100: '#CCFBF1',
|
||||||
active: '#1D4ED8',
|
200: '#99F6E4',
|
||||||
subtle: '#EFF6FF',
|
300: '#5EEAD4',
|
||||||
|
400: '#2DD4BF',
|
||||||
|
500: '#14B8A6',
|
||||||
|
600: '#0D9488', // PRIMARY
|
||||||
|
700: '#0F766E',
|
||||||
|
800: '#115E59',
|
||||||
|
900: '#134E4A',
|
||||||
|
DEFAULT: '#0D9488',
|
||||||
|
hover: '#0F766E',
|
||||||
|
active: '#115E59',
|
||||||
|
subtle: '#F0FDFA',
|
||||||
|
},
|
||||||
|
|
||||||
|
// AI Features (Amber)
|
||||||
|
ai: {
|
||||||
|
50: '#FFFBEB',
|
||||||
|
100: '#FEF3C7',
|
||||||
|
200: '#FDE68A',
|
||||||
|
300: '#FCD34D',
|
||||||
|
400: '#FBBF24',
|
||||||
|
500: '#F59E0B', // PRIMARY AI
|
||||||
|
600: '#D97706',
|
||||||
|
700: '#B45309',
|
||||||
|
800: '#92400E',
|
||||||
|
900: '#78350F',
|
||||||
|
DEFAULT: '#F59E0B',
|
||||||
|
hover: '#D97706',
|
||||||
|
subtle: '#FFFBEB',
|
||||||
},
|
},
|
||||||
|
|
||||||
// Neutral CTA
|
// Neutral CTA
|
||||||
@@ -104,8 +131,8 @@ const config: Config = {
|
|||||||
subtle: '#FEF2F2',
|
subtle: '#FEF2F2',
|
||||||
},
|
},
|
||||||
info: {
|
info: {
|
||||||
DEFAULT: '#3B82F6',
|
DEFAULT: '#0D9488', // Uses brand teal
|
||||||
subtle: '#EFF6FF',
|
subtle: '#CCFBF1', // teal-100
|
||||||
},
|
},
|
||||||
|
|
||||||
// Severity badges (DSM-light)
|
// Severity badges (DSM-light)
|
||||||
@@ -131,7 +158,7 @@ const config: Config = {
|
|||||||
placeholder: '#94A3B8',
|
placeholder: '#94A3B8',
|
||||||
border: '#CBD5E1',
|
border: '#CBD5E1',
|
||||||
'border-hover': '#94A3B8',
|
'border-hover': '#94A3B8',
|
||||||
focus: '#3B82F6',
|
focus: '#0D9488', // Teal focus states
|
||||||
disabled: {
|
disabled: {
|
||||||
bg: '#F1F5F9',
|
bg: '#F1F5F9',
|
||||||
text: '#94A3B8',
|
text: '#94A3B8',
|
||||||
@@ -145,7 +172,7 @@ const config: Config = {
|
|||||||
'lg': '0 8px 20px rgba(15,23,42,0.10)',
|
'lg': '0 8px 20px rgba(15,23,42,0.10)',
|
||||||
},
|
},
|
||||||
ringColor: {
|
ringColor: {
|
||||||
DEFAULT: '#3B82F6',
|
DEFAULT: '#0D9488', // Teal ring for focus states
|
||||||
},
|
},
|
||||||
ringWidth: {
|
ringWidth: {
|
||||||
DEFAULT: '2px',
|
DEFAULT: '2px',
|
||||||
|
|||||||
Reference in New Issue
Block a user