Imported from github.com/cyguin/feedback
Find a file
2026-05-16 15:17:38 -07:00
src fix #1: [smoke-test] Test coverage review: 12 source files, 1 test files (8.3% 2026-05-16 15:17:38 -07:00
.gitignore gsd: pre-implementation lint/format cleanup 2026-05-16 14:54:34 -07:00
DEV_LOG.md gsd: pre-implementation lint/format cleanup 2026-05-16 14:54:34 -07:00
LICENSE chore: normalize cyguin package metadata 2026-04-21 09:26:39 -05:00
package-lock.json docs: align feedback dark theme docs 2026-04-21 09:32:43 -05:00
package.json docs: align feedback dark theme docs 2026-04-21 09:32:43 -05:00
README.md gsd: pre-implementation lint/format cleanup 2026-05-16 14:54:34 -07:00
tsconfig.json chore: initial publish 2026-04-05 08:11:49 -05:00
tsup.config.ts gsd: pre-implementation lint/format cleanup 2026-05-16 14:54:34 -07:00

@cyguin/feedback

Drop-in user feedback widget for Next.js — capture thumbs, star ratings, or free-text feedback from inside any page.

Install

npm install @cyguin/feedback

Setup

1. Create the API route

Create app/api/feedback/[...cyguin]/route.ts in your Next.js app:

import { createFeedbackHandler } from "@cyguin/feedback/server";
import { createInMemoryAdapter } from "@cyguin/feedback/adapters/in-memory";

const adapter = createInMemoryAdapter();
const handler = createFeedbackHandler({
  adapter,
  secret: process.env.FEEDBACK_SECRET,
});

export { handler as GET, handler as POST, handler as PATCH };

For production with Supabase:

import { createFeedbackHandler } from "@cyguin/feedback/server";
import { createSupabaseAdapter } from "@cyguin/feedback/adapters/supabase";

const adapter = createSupabaseAdapter(supabaseClient);
const handler = createFeedbackHandler({
  adapter,
  secret: process.env.FEEDBACK_SECRET,
});

export { handler as GET, handler as POST, handler as PATCH };

2. Run migrations

CREATE TABLE feedback (
  id TEXT PRIMARY KEY,
  user_id TEXT,
  type TEXT NOT NULL,
  body TEXT NOT NULL,
  url TEXT NOT NULL,
  created_at INTEGER NOT NULL,
  reviewed INTEGER NOT NULL DEFAULT 0
);

3. Add the widget

import { FeedbackWidget } from '@cyguin/feedback/react';

// Thumbs mode
<FeedbackWidget type="thumbs" />

// Star rating mode (default 5 stars)
<FeedbackWidget type="rating" maxStars={5} />

// Free text mode
<FeedbackWidget type="text" placeholder="Share your feedback..." />

All three modes submit to your API and show a "Thanks for your feedback!" message for 3 seconds.

Theming

FeedbackWidget defaults to the cyguin dark theme. Pass theme="light" to opt into the light theme.

Use --cyguin-* CSS custom properties on a parent element or :root:

.feedback-widget {
  --cyguin-bg: #ffffff;
  --cyguin-bg-subtle: #f5f5f5;
  --cyguin-border: #e5e5e5;
  --cyguin-border-focus: #f5a800;
  --cyguin-fg: #0a0a0a;
  --cyguin-fg-muted: #888888;
  --cyguin-accent: #f5a800;
  --cyguin-accent-dark: #c47f00;
  --cyguin-accent-fg: #0a0a0a;
  --cyguin-radius: 6px;
  --cyguin-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}

Switch to light theme with the theme prop:

<FeedbackWidget type="thumbs" theme="light" />

Dark theme applies these overrides automatically:

--cyguin-bg: #0a0a0a;
--cyguin-bg-subtle: #1a1a1a;
--cyguin-border: #2a2a2a;
--cyguin-fg: #f5f5f5;
--cyguin-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);

Supabase Adapter Setup

import { createFeedbackHandler } from "@cyguin/feedback/server";
import { createSupabaseAdapter } from "@cyguin/feedback/adapters/supabase";
import { createClient } from "@supabase/supabase-js";

const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_ROLE_KEY!,
);
const adapter = createSupabaseAdapter(supabase);

const handler = createFeedbackHandler({
  adapter,
  secret: process.env.FEEDBACK_SECRET,
});

export { handler as GET, handler as POST, handler as PATCH };

Required environment variable for admin routes: FEEDBACK_SECRET — Bearer token for listing and reviewing feedback. Public feedback submission does not use this token.

API Routes

Method Route Description
GET /api/feedback List feedback (admin, requires Bearer token)
POST /api/feedback Submit new feedback (public widget endpoint)
PATCH /api/feedback/:id/reviewed Toggle reviewed flag

License

MIT