Imported from github.com/cyguin/banner
Find a file
2026-05-17 17:41:08 -07:00
coverage gsd: pre-implementation lint/format cleanup 2026-05-17 17:41:08 -07:00
src gsd: pre-implementation lint/format cleanup 2026-05-16 14:17:56 -07:00
.gitignore gsd: pre-implementation lint/format cleanup 2026-05-16 14:17:56 -07:00
LICENSE chore: normalize cyguin package metadata 2026-04-21 09:26:39 -05:00
package-lock.json docs: align banner dark theme docs 2026-04-21 09:32:43 -05:00
package.json gsd: pre-implementation lint/format cleanup 2026-05-17 17:41:08 -07:00
README.md gsd: pre-implementation lint/format cleanup 2026-05-16 14:17:56 -07:00
tsconfig.json chore: initial publish 2026-04-05 08:09:21 -05:00
tsup.config.ts gsd: pre-implementation lint/format cleanup 2026-05-16 14:17:56 -07:00
vitest.config.ts gsd: pre-implementation lint/format cleanup 2026-05-17 17:41:08 -07:00

@cyguin/banner

Cookie consent and GDPR notice drop-in for Next.js. Stores consent decisions in DB for audit trail, renders a dismissible consent banner.

Install

npm install @cyguin/banner

Configure Adapter

SQLite

// lib/banner.ts
import { SQLiteAdapter } from "@cyguin/banner/adapters/sqlite";

export const bannerAdapter = SQLiteAdapter({ path: "./data/banner.db" });

Postgres

// lib/banner.ts
import { PostgresAdapter } from "@cyguin/banner/adapters/postgres";

export const bannerAdapter = PostgresAdapter({
  connectionString: process.env.DATABASE_URL!,
});

Add API Route

// app/api/banner/[...cyguin]/route.ts
import { createBannerHandler } from "@cyguin/banner/next";
import { bannerAdapter } from "@/lib/banner";

export const GET = createBannerHandler({ adapter: bannerAdapter });
export const POST = createBannerHandler({ adapter: bannerAdapter });

Drop In Component

// app/layout.tsx (or any page)
import { ConsentBanner } from "@cyguin/banner/react";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html>
      <body>
        {children}
        <ConsentBanner
          apiBase="/api/banner"
          userId="user_123" // optional
          theme="dark" // or "light"
          onAccept={() => console.log("accepted")}
          onReject={() => console.log("rejected")}
        />
      </body>
    </html>
  );
}

Theming

The banner uses --cyguin-* CSS custom properties. Default is dark.

// Light theme
<ConsentBanner theme="light" />

Customise via CSS:

.cyguin-banner {
  --cyguin-accent: #ff6600;
  --cyguin-radius: 0;
}

Exports

Import What
@cyguin/banner Types: ConsentRecordData, ConsentDecision, BannerAdapter
@cyguin/banner/next createBannerHandler
@cyguin/banner/react ConsentBanner
@cyguin/banner/adapters/sqlite SQLiteAdapter
@cyguin/banner/adapters/postgres PostgresAdapter

API

Method Route Description
GET /api/banner/[...cyguin] Get current consent record for user
POST /api/banner/[...cyguin] Record consent decision

DB Schema

CREATE TABLE consent_records (
  id TEXT PRIMARY KEY,
  user_id TEXT,
  decision TEXT NOT NULL,
  categories TEXT NOT NULL DEFAULT '[]',
  created_at INTEGER NOT NULL
);