fredonbytes-consent-cookies
v1.4.8
Published
Next.js consent cookies management with Supabase and optional next-intl support
Maintainers
Readme
FredonBytes Consent Cookies
GDPR-compliant consent management for Next.js with Supabase storage and next-intl internationalization support.
Features
- 🚀 Easy integration with Next.js 15+ (App Router)
- ⚡ Server Component compatible - No performance degradation
- 🌍 Multilingual support - Built-in: English, Czech, German
- 🔄 Optional next-intl - Works with or without next-intl
- 💾 Supabase backend for consent persistence
- 🎨 Tailwind CSS styling
- 🔒 GDPR compliant
- 📦 Lightweight and tree-shakeable
- 🤖 SEO-friendly - No blocking, robots can crawl
Installation
npm install fredonbytes-consent-cookies
# or
yarn add fredonbytes-consent-cookies
# or
pnpm add fredonbytes-consent-cookiesQuick Start
1. Environment Variables
Add to your .env.local:
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_keyNote: This package requires
react,react-dom, andnext(>=15.0.0) as peer dependencies.next-intl(>=3.0.0) is optional.
2. Database Setup
Option A: Using Supabase Migrations (Recommended for Production)
This package includes an automated migration file for easy setup.
- Copy migration file to your project:
cp node_modules/fredonbytes-consent-cookies/supabase/migrations/* ./supabase/migrations/- Push migrations to your Supabase project:
supabase migration upOr use the Supabase CLI to apply:
supabase db pushOption B: Manual SQL Setup (Alternative)
If you prefer manual setup, execute the following SQL in your Supabase SQL editor:
-- Enable pgcrypto extension for UUID generation
CREATE EXTENSION IF NOT EXISTS pgcrypto;
-- Cookie Consent Table
CREATE TABLE IF NOT EXISTS consents (
id BIGSERIAL PRIMARY KEY,
consent_id UUID UNIQUE NOT NULL,
-- Consent choices (4 categories)
essential BOOLEAN NOT NULL DEFAULT true,
analytics BOOLEAN NOT NULL DEFAULT false,
marketing BOOLEAN NOT NULL DEFAULT false,
personalization BOOLEAN NOT NULL DEFAULT false,
-- Privacy and tracking
ip_hash VARCHAR(64), -- SHA-256 hash, only if analytics=true
user_agent TEXT,
-- Compliance markers
consent_version VARCHAR(10) NOT NULL DEFAULT '1.0',
explicit_timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(),
-- Audit trail
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
last_updated TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Indexes
CREATE INDEX IF NOT EXISTS idx_consents_consent_id ON consents(consent_id);
CREATE INDEX IF NOT EXISTS idx_consents_version ON consents(consent_version);
CREATE INDEX IF NOT EXISTS idx_consents_updated ON consents(last_updated);Graceful Fallback
If Supabase is not configured or unavailable:
- ✅ Consent banner still displays and can be dismissed
- ✅ Preferences are stored in browser localStorage
- ✅ API returns success with warning message
- ⚠️ No persistent server-side storage until database is configured
This ensures your application gracefully degrades even without database connectivity.
3. Basic Usage (Server-Side Rendering)
Add to your root layout (remains a server component):
import FredonBytesConsent from 'fredonbytes-consent-cookies';
// ✅ This layout stays a server component!
// No "use client" needed - preserves SSR, streaming, and performance
export default function RootLayout({ children }) {
return (
<html>
<body>
<FredonBytesConsent />
{children}
</body>
</html>
);
}Why this works:
- The package now uses automatic JSX runtime (
react-jsx) - React and jsx-runtime are externalized (not bundled)
preserveModulesmaintains server/client boundariesFredonBytesConsentis a server component wrapper that creates a client boundary only for the consent banner
4. Internationalization (Optional)
Without next-intl (Simple Projects)
The package automatically uses English as fallback. No additional setup needed!
With next-intl (Multi-language Projects)
Merge consent messages with your app translations:
// i18n.ts
import { getRequestConfig } from 'next-intl/server';
import { loadConsentMessages } from 'fredonbytes-consent-cookies/server';
export default getRequestConfig(async ({ requestLocale }) => {
const locale = await requestLocale;
const appMessages = (await import(`./messages/${locale}.json`)).default;
const consentMessages = await loadConsentMessages(locale); // Server-side loading
return {
locale,
messages: {
...appMessages,
...consentMessages, // Adds 'consent.*' keys
},
};
});Supported Languages:
en- English (default fallback)cs- Czechde- German
Adding Custom Translations:
If you need a language not supported by the package, add consent.* keys to your project's message files:
// messages/fr.json (example)
{
"consent": {
"title": "Préférences des cookies",
"description": "Nous utilisons des cookies...",
"acceptAll": "Tout accepter",
"rejectAll": "Tout rejeter",
// ... see src/messages/en.json for all keys
}
}Advanced Usage
Individual Components
import {
ConsentBanner,
ConsentModule,
ConsentCompact,
ConsentFooterLinks
} from 'fredonbytes-consent-cookies';
// Use specific components
export function MyLayout() {
return (
<>
<ConsentBanner />
<ConsentFooterLinks />
</>
);
}
// Preference management page
export function PreferencesPage() {
return <ConsentModule />;
}Client Utilities
import {
getConsentPreferences,
setConsentPreferences,
hasConsent
} from 'fredonbytes-consent-cookies';
// Check if user has given consent
if (hasConsent()) {
const prefs = getConsentPreferences();
if (prefs.analytics) {
// Initialize analytics
}
}TypeScript Support
import type {
ConsentPreferences,
ConsentPayload,
Locale
} from 'fredonbytes-consent-cookies';
const preferences: ConsentPreferences = {
analytics: true,
marketing: false,
preferences: true
};API Reference
Components
FredonBytesConsent(default): Complete consent banner solutionConsentBanner: Modal/banner for first-time consentConsentModule: Full preferences management UIConsentCompact: Compact widget versionConsentFooterLinks: Footer links for consent pages
Utilities
loadConsentMessages(locale): Load consent translationsgetConsentLocales(): Get supported localesgetConsentPreferences(): Get current preferencessetConsentPreferences(prefs): Set preferenceshasConsent(): Check if consent exists
Types
ConsentPreferences: User consent choicesConsentPayload: Full consent data structureLocale: Supported locale types
Supported Locales
cs(Czech) - Defaulten(English)
Custom locales can be added by providing your own message files.
Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| NEXT_PUBLIC_SUPABASE_URL | Yes | Your Supabase project URL |
| NEXT_PUBLIC_SUPABASE_ANON_KEY | Yes | Your Supabase anonymous key |
Performance & Architecture
Server Component First: The default export FredonBytesConsent is a server component wrapper. This means:
- ✅ Your layout remains a server component
- ✅ No degradation of SSR, streaming, or suspense
- ✅ Client boundary created only for the consent widget
- ✅ Preserves all Next.js performance optimizations
The consent widget itself uses client components internally (for user interactions), but the wrapper ensures your application layout stays server-side rendered.
Peer Dependencies
next>= 15.0.0react>= 18.0.0react-dom>= 18.0.0next-intl>= 3.0.0
Development
Build Package
npm run build:packageLocal Development
npm run devLicense
MIT ©2025 FredonBytes | Your All-in-one Digital army
Support
For questions or professional services, visit: FredonBytes Site
