Skip to content

✨ feat(legal-terms): add the cookie consent banner alongside the policy - #108

Merged
vtempest merged 2 commits into
masterfrom
claude/cookie-popup-legal-terms-ozu2eb
Sep 21, 2026
Merged

vtempest merged 2 commits into
masterfrom
claude/cookie-popup-legal-terms-ozu2eb

Conversation

@vtempest

Copy link
Copy Markdown
Collaborator

The cookie consent banner makes the same promises the Terms and the Privacy Policy make, in a smaller box, and links to them. Shipping it from this package is what keeps the corner card and the legal page from drifting apart — the same reason the two variants of the document live together here.

Ported from the hand-written popup in the QwkSearch web app (OpenSourceAGI/qwksearch-research-agent), generalized to props and styled to match this package's page.

What's new

src/cookie-consent.ts — the consent record and its localStorage, exported from the framework-free root so analytics gating, a worker or a build script can read the choice without pulling React in:

import { readCookieConsent, clearCookieConsent } from 'legal-terms-privacy-policy';

if (readCookieConsent()?.analytics) loadAnalytics();
clearCookieConsent(); // a "change my choices" link — the banner asks again

The record is { analytics, marketing, functional, timestamp }. "Reject" records essential cookies only rather than nothing — functional stays true, since rejecting it would be rejecting the login — and the timestamp is what proves when consent was given. A malformed or half-written record, and a browser that refuses storage at either the property access or the call, both read as no decision rather than throwing.

src/react/CookieConsent.tsx — the banner, Tailwind-styled and dark-mode ready like the page beside it. appName, links, title/message, acceptLabel/rejectLabel, storageKey, dismissible and onDecision are all props; heightVar publishes the banner's measured height into a CSS custom property on <html> while it is up, so other bottom-right chrome can offset by it instead of sitting underneath.

It shows only when no decision is on record, and that check runs in an effect — so it renders to nothing on the server, and a cached page never shows it to someone who already answered.

Also updated

  • readme.md prose and skills/legal-terms-privacy-policy/SKILL.md — the banner, its props, the stored record, and four new troubleshooting rows.
  • .claude/packages/legal-terms-privacy-policy/CLAUDE.md — notes that the record's shape and its cookie-consent key are a compatibility surface (widen it, don't re-key it), and why the consent tests stub localStorage.
  • Version 0.1.34 → 0.2.0 — new public exports.

Testing

bun run test — 51 pass, 3 files. The consent tests stub localStorage and server-render the banner rather than adding jsdom to a package whose suite runs in node. They cover separate storage keys, a malformed record, a missing timestamp, storage that refuses every call, and no storage at all.

bun run typecheck clean; bun run readmes:check reports every header up to date; the CLI still renders.

One bug surfaced while writing the tests and is fixed here: an onDecision?.(writeCookieConsent(...)) shape would have skipped the write entirely whenever no handler was passed, because an optional call does not evaluate its arguments.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Q5gjihR6tDv5ah4GHbwfQq


Generated by Claude Code

The banner makes the same promises the Terms and the Privacy Policy make, in a
smaller box, and links to them — so it ships from the same package, and the two
stay one thing to maintain.

- `src/cookie-consent.ts` — the consent record and its localStorage, exported
  from the framework-free root so analytics gating and server code can read the
  choice without pulling React in. "Reject" records essential cookies only
  rather than nothing; a malformed record, and a browser that refuses storage
  at either the property access or the call, read as no decision instead of
  throwing.
- `src/react/CookieConsent.tsx` — the banner, Tailwind-styled and dark-mode
  ready like the page beside it, taking its copy, links, labels and storage key
  from props. `heightVar` publishes its measured height so other bottom-right
  chrome can sit above it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5gjihR6tDv5ah4GHbwfQq
@vercel

vercel Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
cccp-deployment Error Error Sep 21, 2026 7:52am UTC
dev-tools-help-docs Error Error Sep 21, 2026 7:52am UTC
test-google-login Error Error Sep 21, 2026 7:52am UTC

…-legal-terms-ozu2eb

# Conflicts:
#	packages/legal-terms-privacy-policy/package.json
@vtempest
vtempest merged commit 9bb83ee into master Sep 21, 2026
25 of 29 checks passed
@codecov

codecov Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 55.73770% with 27 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...l-terms-privacy-policy/src/react/CookieConsent.tsx 33.33% 24 Missing and 2 partials ⚠️
...s/legal-terms-privacy-policy/src/cookie-consent.ts 95.45% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

This branch had an error being deployed

3 failed deployments
Preview – cccp-deployment — 8adfbf10 Deployed Sep 21, 2026 by vercel[bot]
Preview – test-google-login — 8adfbf10 Deployed Sep 21, 2026 by vercel[bot]
Preview – dev-tools-help-docs — 8adfbf10 Deployed Sep 21, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants