Frontend Architecture¶
The frontend is built with Next.js 16, React 19, and Tailwind CSS 4.
Project Structure¶
frontend/
├── app/ # Next.js App Router
│ ├── layout.tsx # Root layout with providers
│ ├── page.tsx # Homepage
│ ├── account/ # User account settings
│ ├── admin/ # Admin dashboard (React)
│ ├── auth/ # Authentication pages
│ ├── cart/ # Shopping cart
│ ├── catalog/ # Product catalog listing
│ ├── checkout/ # Checkout flow
│ ├── contact/ # Contact form
│ ├── designer/ # Product designer (Fabric.js)
│ ├── designs/ # Saved designs
│ ├── login/ # Login page
│ ├── orders/ # Order history
│ ├── products/ # Product detail pages
│ ├── team-order/ # Team/bulk ordering
│ ├── faq/ # FAQ page
│ ├── over-ons/ # About page
│ ├── privacy/ # Privacy policy
│ ├── retouren/ # Return policy
│ └── voorwaarden/ # Terms & conditions
├── components/
│ ├── header/ # Header components
│ ├── homepage/ # Homepage sections
│ ├── products/ # Product listing
│ ├── product-detail/ # Product detail page
│ ├── ProductDesigner/ # Canvas designer
│ └── providers/ # Context providers
├── contexts/ # React contexts
│ ├── AuthContext.tsx
│ ├── CartContext.tsx
│ ├── TeamOrderContext.tsx
│ └── ThemeContext.tsx
├── hooks/ # Custom hooks
│ ├── api/ # API query hooks
│ └── admin/ # Admin hooks
├── lib/ # Utilities
│ ├── api/client.ts # API client (Axios)
│ ├── posthog.ts # PostHog analytics init
│ └── queryClient.ts # TanStack Query
├── types/ # TypeScript types
└── public/ # Static assets
Component Architecture¶
Component Organization¶
Components are organized by feature:
components/
├── [feature]/
│ ├── FeatureComponent.tsx
│ ├── FeatureComponent.stories.tsx # Storybook
│ └── FeatureComponent.test.tsx # Jest tests
Component Patterns¶
Presentational Components
interface ButtonProps {
variant: 'primary' | 'secondary';
children: React.ReactNode;
}
export function Button({ variant, children }: ButtonProps) {
return <button className={styles[variant]}>{children}</button>;
}
Container Components
export function ProductList() {
const { data: products } = useQuery({
queryKey: ['products'],
queryFn: fetchProducts,
});
return <ProductGrid products={products} />;
}
State Management¶
Server State (TanStack Query)¶
const { data, isLoading, error } = useQuery({
queryKey: ['products', categoryId],
queryFn: () => api.products.list({ category: categoryId }),
});
Client State (React Context)¶
The primary client state is managed via React Context:
AuthContext- Authentication state and user sessionCartContext- Shopping cart items and operationsTeamOrderContext- Team order builder stateThemeContext- Light/dark theme preferences
Persistent State (Zustand)¶
Zustand is used for localStorage-persisted state that must survive SSR:
// Admin onboarding checklist progress
const useOnboardingProgress = create(
persist((set) => ({
completedSteps: [],
markComplete: (step) => set((state) => ({
completedSteps: [...state.completedSteps, step],
})),
}), { name: 'admin-onboarding' })
);
Styling¶
Tailwind CSS 4 with custom design tokens in app/globals.css:
:root {
--primary: #31a8b6;
--primary-dark: #2a919d;
}
@theme inline {
--color-primary: var(--primary);
}
Visual Identity System¶
The "Freeze" brand visual language uses frost/ice effects:
Color Tokens:
- --frost-N - Frost blue shades (100-900)
- --ice-N - Ice accent colors
- --coral-N - Warm accent for CTAs
Utility Classes:
- glass-frost - Glassmorphism with backdrop-blur
- frost-overlay - Decorative ice pattern overlay
- link-underline - Animated underline on hover/focus
Animation Patterns (Motion):
// Entrance animations with stagger
<motion.div variants={containerVariants} initial="hidden" animate="visible">
<motion.div variants={itemVariants}>...</motion.div>
</motion.div>
// Tactile feedback
<motion.button whileTap={{ scale: 0.95 }} transition={{ duration: 0.1 }}>
// Frost glow hover
className="hover:shadow-[0_0_15px_rgba(125,211,252,0.25)]"
Product Designer¶
The Fabric.js canvas editor supports:
- Text with custom fonts
- Image uploads
- Shape tools
- Multi-view support (front/back/left/right)
- Undo/redo
- Print area boundaries