Task Overview
Implement a complete GDPR/ePrivacy-compliant cookie consent system for a Next.js application. The system must prevent third-party tracking services from loading until users explicitly consent.
Core Problem
The user's Next.js app currently loads various third-party services (analytics, monitoring, marketing tools) automatically. Per EU law, these services require explicit user consent before they can place cookies or track users.
Required Components
1. Consent Management System
Build a consent storage and management layer that:
- Stores user preferences in localStorage
- Tracks three categories: Essential (always on), Analytics (optional), Marketing (optional)
- Includes timestamp of when consent was given
- Provides functions to: get consent, save consent, check if consent exists, clear consent
- Dispatches browser events when consent changes so services can react
2. Cookie Consent Banner
Create a UI component that:
- Appears at bottom (or top) of page on first visit
- Offers three actions: Accept All, Decline, Customize
- Can expand to show details about what each cookie type does
- Hides once user makes a choice
- Stores the choice in localStorage
- Reloads page after user accepts (to initialize tracking services)
- Does NOT appear on the cookie settings page itself
3. Cookie Settings Page
Build a dedicated page where users can:
- See all cookie categories with clear descriptions
- Toggle each optional category on/off with switches
- See which specific services are in each category
- Save their preferences
- Reset to defaults
- See when they last updated preferences
4. Service Wrappers
For each third-party service the user has, create wrappers that:
- Check if consent is granted before loading/initializing
- Only render or initialize if consent exists
- Listen for consent changes and reload page if needed
- Gracefully do nothing if consent is declined
5. Privacy Policy Updates
Add a comprehensive cookies section explaining:
- What cookies the site uses
- Which ones require consent vs essential
- What each service does with user data
- How to manage cookie preferences
- Link to the cookie settings page
6. Easy Access
Add a "Cookie Settings" link in the footer so users can always change their mind.
Critical Technical Challenge: Hydration Errors
The Problem:
Next.js renders on the server first (SSR), then React "hydrates" on the client. If server HTML doesn't match client HTML, React throws hydration errors.
localStorage only exists in the browser (client), not on the server. If you check localStorage during component render, you'll get:
- Server: Renders one thing (no localStorage access)
- Client: Renders something different (has localStorage access)
- Result: Hydration mismatch error
The Solution Pattern:
- Start with a state that matches what the server would render (usually
false or null)
- Use an
isMounted flag that starts false
- In
useEffect, set isMounted to true and THEN check localStorage
- Don't render consent-dependent UI until
isMounted is true
This ensures server and client initially render the same HTML, preventing mismatches.
Key rule: Never check localStorage during component render. Always use useEffect.
Event System for Consent Changes
When user changes their preferences:
- Save to localStorage
- Dispatch a custom browser event with the new consent state
- All service wrappers listen for this event
- When consent changes, services reload the page to apply changes
This creates a reactive system where changing consent in settings automatically propagates to all services.
Hiding Banner on Settings Page
The banner should hide when user is on the cookie settings page (they're already managing preferences there). Use Next.js's routing to detect current page and conditionally show/hide banner.
EU Compliance Requirements
- ✅ Explicit opt-in (no pre-checked boxes)
- ✅ Clear, specific descriptions of what each service does
- ✅ Granular control (can accept some, decline others)
- ✅ Easy to withdraw consent later (settings page)
- ✅ Essential cookies clearly marked as always active
- ✅ No tracking before consent given
User Experience Flow
First-time visitor:
- Lands on site
- Banner appears at bottom
- Chooses Accept/Decline/Customize
- Choice is saved
- Page reloads if they accepted (to start tracking)
- Banner never shows again
Returning visitor with consent:
- Lands on site
- No banner (consent already stored)
- Tracking works based on their previous choice
- Can change mind via footer link
Changing preferences:
- Click "Cookie Settings" in footer
- See current state with toggle switches
- Toggle on/off as desired
- Click Save
- Page reloads to apply changes
What to Ask the User
Before implementing:
- Which third-party services are you using? (analytics, monitoring, ads, etc.)
- Where should the banner appear? (bottom, top, corner)
- What UI library do you use? (Tailwind, Shadcn, MUI, custom)
- Do you need a Marketing category, or just Analytics?
- What's your project name? (for localStorage key)
Success Criteria
When done correctly:
- [ ] No React hydration errors in console
- [ ] First visit shows banner
- [ ] Accepting enables tracking services
- [ ] Declining keeps them disabled
- [ ] Settings page works without banner interference
- [ ] Consent persists across page loads
- [ ] Footer link to settings page exists
- [ ] Privacy policy explains everything
- [ ] Mobile responsive
- [ ] Works with ad blockers (fails gracefully)
Common Mistakes to Avoid
- ❌ Checking localStorage during render
- ❌ Using lazy initialization with
typeof window checks in useState
- ❌ Not handling server-side rendering properly
- ❌ Forgetting to reload page after consent changes
- ❌ Showing banner on settings page
- ❌ Not providing a way to change preferences later
- ❌ Vague descriptions ("we use cookies to improve experience")
- ❌ Pre-checking optional cookies
Implementation Notes
Focus on:
- Preventing hydration errors - This is the hardest part technically
- Clear communication - Users must understand what they're consenting to
- Graceful degradation - Site works without tracking services
- Easy management - Settings should be one click away in footer
- Event-driven - Services should react to consent changes automatically
The goal is a consent system that's legally compliant, user-friendly, and technically solid with zero hydration errors.