cbrew
v0.2.0
Published
Context Brew — a drop-in feedback widget (React FAB + framework-agnostic script-tag embed) for the hosted cbrew.co feedback product. Point it at the hosted API with a publishable app key; you provision nothing.
Maintainers
Readme
Context Brew — cbrew
A hosted feedback product: a drop-in "Send feedback" FAB widget + a feedback board + an
AI-agent build loop, backed by a multi-tenant serverless API at cbrew.co. You embed the widget
and point it at the hosted API with a publishable key — you provision nothing.
- Site & docs: https://cbrew.co/#/docs · Sign up: https://cbrew.co/#/signup
- Your board:
https://board.cbrew.co/<workspace> - CLI (agent loop):
@cbrew/cli
Quickstart — React (incl. Next.js)
npm i cbrew// once, at app startup (any client module)
import { configureFeedbackApi } from 'cbrew'
import 'cbrew/styles.css'
configureFeedbackApi({
apiBase: 'https://api.cbrew.co',
feedbackKey: 'fbk_your_publishable_key', // browser-safe — mint at board.cbrew.co → Settings → App keys
})// anywhere in your tree (mount once, globally)
import { FeedbackFab } from 'cbrew'
<FeedbackFab boardUrl="https://board.cbrew.co/your-workspace" workspaceName="Acme" />Next.js App Router: works out of the box — the package ships prebuilt with "use client",
so you can import it without transpilePackages or wrapper gymnastics. Put the
configureFeedbackApi call + <FeedbackFab/> in any client component and render it from your
root layout.
Peer deps: react >= 18 and lucide-react >= 0.400.0.
Quickstart — any other stack (Vue/Nuxt, Rails, Laravel, plain HTML)
One script tag; React is bundled inside, styles self-inject:
<script src="https://cdn.cbrew.co/embed.js"
data-key="fbk_your_publishable_key"
data-name="Acme"
data-board="https://board.cbrew.co/your-workspace"></script>The same file ships in this package at cbrew/dist/embed.js
(mirrored at https://unpkg.com/cbrew/dist/embed.js), so bundler pipelines
(Rails jsbundling/importmap, Laravel Vite) can serve it themselves.
What you get
Screenshot capture, paste & drag-drop images, file attachments, ⌘D speech-to-text, screen-recording
walkthroughs, priorities, private items, email-verified identity (6-digit code, no passwords),
notifications at every step, and a public "What's new" changelog written automatically when items
ship. Approved items become markdown work orders in your repo (cbrew pull → feedback/FB-<n>.md)
so your AI agent can build them — see AGENTS.md and npm i -g @cbrew/cli.
Keys & auth (host-independent)
- Publishable app key (
fbk_…, headerx-feedback-key): safe in the browser; authorizes rate-limited submits + the email-code handshake; origin-locked from the board. - Secret key (
fbsk_…): backend-only (admin ops + the identity trust bridge). Never ship it to a frontend. - End users verify by emailed 6-digit code — no anonymous submits, AUP consent recorded.
Repo internals (provider-side — none of this ships to npm)
Consumers embed the widget (src/client, built to dist/). The provider (us) runs the
service + infra:
src/
client/ the WIDGET — FeedbackFab, FeedbackPage, HandleCard, Avatar, api, feedback-scope.css
+ embed.js (script-tag self-mount)
server/ the API — index (routes) · store (DDB) · auth · identity · email · config
+ tenant (resolve tenant→table/plan) · lambda (the service entrypoint)
infra/ the provider's Terraform stack (DDB · Lambda · API GW · CloudFront · ACM · Route53 · SES · secret)
adapters/ integration notes (e.g. how the first tenant consumed the widget pre-npm)
board/ board.cbrew.co SPA · site/ cbrew.co marketing+docs · cli/ the @cbrew/cli agent loopBuild: npm run build → dist/ (ESM+CJS with peers externalized, feedback.css, self-contained
embed.js). Publishing runs it automatically (prepublishOnly); dist/ stays gitignored. The
files allowlist is the tarball gate — verify with npm pack --dry-run.
Multi-tenancy: shared DynamoDB table with T#<tenant># key prefixes by default; dedicated
tables plan-gated for enterprise; a TENANT#<id> registry maps app keys → tenant + plan → table.
SES: sends from feedback.cbrew.co (domain identity + DKIM + MAIL FROM). CORS: the API echoes
allowed origins from each app key's origins[] allow-list.
