# FeedbackFlow FeedbackFlow is a pay-first indie inbox. Paste one prompt into Cursor, Claude, or Codex. It installs a report control in a Next.js site, Expo app, or Swift app. User problems land in one inbox and email the project maker. Who it is for: founders shipping a product who want reports without a tracked-user meter or a seat tax. How it works: - Web: global bottom-right Feedback FAB (.ff-fab). Required on websites. - Expo / iOS / Swift: shake opens the sheet. First install and first launch after an update show a one-time tip. The only persistent door is a Settings row. Never a floating chip on every screen. - Pay first: $19/month or $349 lifetime. No trial. Pilot of 25 paid inboxes. - New reports email the project owner and the FeedbackFlow founder. A saved Slack or Discord webhook also fires. Coming soon (not shipped): an MCP so Cursor or Claude can read reports (`list_reports`, `get_report`) and draft a fix. New features and wishes need a human approve in the inbox before any agent may implement. No autonomous deploys. Canonical host: https://www.tryfeedflow.com Landing: https://www.tryfeedflow.com/ Docs: https://www.tryfeedflow.com/docs Install spec: https://www.tryfeedflow.com/llms.txt Skill: https://www.tryfeedflow.com/skill.txt MCP manifesto: https://www.tryfeedflow.com/mcp # FeedbackFlow agent install You are installing FeedbackFlow, an indie feedback inbox. Public submissions POST to https://www.tryfeedflow.com/api/v1/feedback Docs: https://www.tryfeedflow.com/docs Skill: https://www.tryfeedflow.com/skill.txt Landing: https://www.tryfeedflow.com/ Canonical host: https://www.tryfeedflow.com Use www.tryfeedflow.com in every install snippet. The user message includes a public key starting with ff_pk_. Use that exact key. Do not invent a vendor, DSN, or analytics tool. Do not add Sentry, Instabug, Canny, UserVoice, Intercom, or a second feedback product. ## Detect the stack - Next.js / web: package.json has "next", or there is app/layout.tsx or pages/_app. - Expo / React Native: package.json has "expo" or "react-native" and no next (or an apps/mobile package). - Swift: Package.swift, *.xcodeproj, or *.xcworkspace. Follow exactly one section below. In a monorepo, install on each shipped surface. ## HIGHLIGHT: wear the host app This is required, not optional. The launcher, report sheet, success state, and shake/tip UI must use the host product’s design language: typeface, radius, spacing, and accent/tint. FeedbackFlow navy (#0F1B31) is a fallback only when the host has no tokens. Never ship a foreign-looking widget on a branded app. Never brand the host UI as “FeedbackFlow” except on FeedbackFlow’s own marketing preview. - Web: inherit document font-family, accent-color, --primary, --ff-accent, --background, --foreground, --radius. Pass them through the script as data-accent / data-background / data-foreground if CSS variables are not on :root. The hosted embed.js already samples these. - Expo: copy sdk/expo or packages/expo. Import FeedbackProvider, FeedbackSettingsRow, FeedbackButton, themeFromHostColors. Pass theme={themeFromHostColors(Colors)} or theme={{ accent: Colors.tint, background, foreground }} from the app’s existing Colors / tokens. - Swift: add the local package at sdk/swift or packages/swift. Color.accentColor + system backgrounds. Keep the app’s .tint() so shake and the sheet match Settings, not a third-party overlay. Do not swizzle UIWindow. ## Never leak leftover brands Do not mention, print, or brand UmmahSignal, UMMAHSIGNAL, or any previous product name. If those strings exist in copy, comments, or UI, replace them with the host product name (or “Feedback”). ## HIGHLIGHT: web FAB vs mobile — they are not the same Websites: a global bottom-right Feedback FAB (.ff-fab) is correct and required. Expo / React Native / Swift / iOS: a global floating Feedback FAB, pill, or chip is FORBIDDEN — do not add a global FAB. The anti-pattern is a persistent “Feedback” chip overlaying every screen — especially over the iOS tab bar on Settings. Do not do that. Do not invent a Portal, absolute View, or ZStack overlay to “make feedback discoverable.” Mobile defaults in the SDK: - showFab = false. Do not pass showFab or set it true. - enableShake = true. Shake opens the report sheet. - showShakeTip = true. First install and first launch after an update show “Shake to send feedback” (or “Shake your device to send a report to the founder.”) once. Persist last-seen app version (AsyncStorage / localStorage on Expo, UserDefaults on Swift). Do not fire every cold start. - The only persistent visible door is a host-placed Settings row: FeedbackSettingsRow or FeedbackButton inside an existing Settings list. Not at the root. Not over the tab bar. If sensors are missing, Settings still opens the sheet. Do not add a FAB as a fallback. ## Next.js / website 1. Prefer the hosted script (zero npm). Add this once in the root layout, before or in a client component mounted from app/layout.tsx: Optional attributes when CSS variables are not enough: data-accent, data-background, data-foreground, data-font, data-radius. 2. If the project already uses React and you want an in-tree component instead, copy sdk/web from the FeedbackFlow repo (or vendor components/widget/feedback-widget.tsx) and render: Set CSS variables --ff-accent, --ff-on-accent, --ff-font on a parent, or pass nothing and inherit --primary. 3. Default launcher: a bottom-right chat button (FAB, class .ff-fab) labeled "Feedback" on desktop and mobile web, plus Ctrl/Cmd+Shift+F. Hide the button while the panel is open. Do not use a right-edge sidebar tab (.ff-tab). z-index must stay above page chrome (80+). Colors and type come from the host, not a hardcoded navy pill. 4. Do not add a marketing banner. Do not wrap the whole app in extra providers unless using the React helper. 5. The hosted sheet kicker may show this project’s name. That is the host product — not FeedbackFlow — except on FeedbackFlow’s own marketing preview. 6. Keep submit motion: pending (“Sending”) then a short success state. Honor prefers-reduced-motion. ## Expo / React Native 1. Copy sdk/expo (or packages/expo) into the app. Package name @feedbackflow/expo. Main/types/exports point at src/index.tsx. JS-only; Expo Go must keep working. 2. import { FeedbackProvider, FeedbackSettingsRow, FeedbackButton, themeFromHostColors } from "./path/to/expo/src" Wrap the root with FeedbackProvider publicKey="ff_pk_REPLACE" apiUrl="https://www.tryfeedflow.com" enableShake theme={themeFromHostColors(Colors)}. Defaults: showFab false, enableShake true, showShakeTip true. Do not pass showFab. 3. Enable shake via expo-sensors Accelerometer (optional peer — install with npx expo install expo-sensors). Call isAvailableAsync before addListener. Require two acceleration peaks (~2.05g) within 450ms, 1.6s cooldown, skip if the sheet is already open. 4. Place FeedbackSettingsRow (or FeedbackButton) on the Settings screen only — an explicit row the host owns. Never mount a global overlay. 5. First install / first launch after an update: the SDK shows “Shake your device to send a report to the founder.” once and persists the app version. Keep showShakeTip at its default. Optional peer @react-native-async-storage/async-storage (localStorage is used on Expo web). 6. Capture screen name if a navigation container exists; capture appVersion from expo-constants if present. 7. POST JSON { publicKey, type, message, reporterEmail, platform: "expo", screen, appVersion, screenshotBase64 } to https://www.tryfeedflow.com/api/v1/feedback 8. If expo-sensors is missing, Settings still works. Do not fall back to a FAB. The sheet uses the same theme as the rest of the app. ## Swift iOS 1. Add the local Swift package at sdk/swift or packages/swift (Package.swift) or copy Sources/FeedbackFlow. 2. Call FeedbackFlow.configure(publicKey: "ff_pk_REPLACE", apiUrl: "https://www.tryfeedflow.com") at launch. 3. Wrap the root in ShakeFeedbackHost(enableShake: true) so shake presents the sheet. Defaults: showFab false, enableShake true, showShakeTip true. Do not pass showFab: true. 4. Add FeedbackSettingsRow() or FeedbackButton() to the Settings screen (a Form / List row). Not a global floating pill. Not over the tab bar. 5. Shake uses a first-responder detector, not a UIWindow override or method swizzle. The sheet is a system Form. Preserve the app’s tint (Color.accentColor). 6. First-install / post-update tip: “Shake your device to send a report to the founder.”, persisted in UserDefaults by CFBundleShortVersionString. 7. POST the same JSON with platform: "ios". 8. Keep ShakeFeedbackHost at the root — do not put it only on a pushed screen you pop. Test shake on a device or Simulator → Device → Shake. ## Verify Web: open the bottom-right FAB, confirm host type/accent, submit "test from agent install", confirm HTTP 201. Mobile: Home and Settings must have no floating Feedback chip. Shake opens the sheet. The Settings row opens the same sheet. The shake tip appears once, then stays gone on the same version. Do not commit secrets. The public key is not a secret.