|
| 1 | +--- |
| 2 | +name: featuredrop-setup |
| 3 | +description: > |
| 4 | + Configure FeatureDrop product adoption toolkit in any project. Use when adding |
| 5 | + changelogs, feature badges, onboarding tours, checklists, hotspots, feedback |
| 6 | + widgets, or surveys to an application. |
| 7 | +--- |
| 8 | + |
| 9 | +# FeatureDrop — Product Adoption Toolkit |
| 10 | + |
| 11 | +Open-source, zero-dependency library for in-app feature discovery. < 3 kB core. |
| 12 | + |
| 13 | +## Setup Pattern |
| 14 | + |
| 15 | +1. `npm install featuredrop` |
| 16 | +2. Create a JSON manifest: `[{ id, label, description, releasedAt, showNewUntil? }]` |
| 17 | +3. Wrap root: `<FeatureDropProvider manifest={features} storage={new LocalStorageAdapter()}>` |
| 18 | +4. Add components or use headless hooks. |
| 19 | + |
| 20 | +## Imports (ALWAYS use subpath imports) |
| 21 | + |
| 22 | +```ts |
| 23 | +// Core (no React, no UI) |
| 24 | +import { isNew, getNewFeatures, createManifest, LocalStorageAdapter } from 'featuredrop' |
| 25 | + |
| 26 | +// React components (ready-made UI) |
| 27 | +import { NewBadge, ChangelogWidget, Tour, Checklist, Banner, Toast } from 'featuredrop/react' |
| 28 | + |
| 29 | +// Headless hooks (data + actions, no JSX — for custom design systems / shadcn) |
| 30 | +import { useChangelog, useNewFeature, useNewCount, useTour, useChecklist } from 'featuredrop/react/hooks' |
| 31 | + |
| 32 | +// Storage adapters |
| 33 | +import { PostgresAdapter, RedisAdapter, IndexedDBAdapter, HybridAdapter } from 'featuredrop/adapters' |
| 34 | + |
| 35 | +// Validation |
| 36 | +import { validateManifest } from 'featuredrop/schema' |
| 37 | + |
| 38 | +// Testing helpers |
| 39 | +import { createMockManifest, createMockStorage, TestProvider } from 'featuredrop/testing' |
| 40 | + |
| 41 | +// Tailwind plugin |
| 42 | +import { featureDropPlugin } from 'featuredrop/tailwind' |
| 43 | +``` |
| 44 | + |
| 45 | +## Hooks (prefer these for custom UI / shadcn projects) |
| 46 | + |
| 47 | +| Hook | Returns | |
| 48 | +|------|---------| |
| 49 | +| `useNewFeature(id)` | `{ isNew, feature, dismiss }` | |
| 50 | +| `useNewCount()` | `number` — unread badge count | |
| 51 | +| `useChangelog()` | `{ features, newFeatures, newCount, dismiss, dismissAll, markAllSeen, getByCategory }` | |
| 52 | +| `useTour(id)` | `{ currentStep, stepIndex, totalSteps, isActive, start, next, prev, skip, complete, goTo }` | |
| 53 | +| `useChecklist(id)` | `{ tasks, completedCount, totalCount, progress, isComplete, completeTask, resetTask }` | |
| 54 | +| `useSurvey(id)` | `{ isVisible, questions, submit, askLater, dismiss }` | |
| 55 | +| `useFeatureDrop()` | Full provider context (features, count, dismiss, throttle controls, engine) | |
| 56 | +| `useTabNotification()` | Browser tab title: `"(3) My App"` | |
| 57 | + |
| 58 | +## Components (ready-made UI) |
| 59 | + |
| 60 | +NewBadge, ChangelogWidget, ChangelogPage, Tour, Checklist, Spotlight, SpotlightChain, |
| 61 | +Hotspot, TooltipGroup, Banner, Toast, AnnouncementModal, Survey, FeedbackWidget, |
| 62 | +FeatureRequestButton, FeatureRequestForm |
| 63 | + |
| 64 | +## Feature Manifest Format |
| 65 | + |
| 66 | +```ts |
| 67 | +{ |
| 68 | + id: string // unique identifier |
| 69 | + label: string // display title |
| 70 | + description: string // what changed |
| 71 | + releasedAt: string // ISO date |
| 72 | + showNewUntil?: string // ISO date — auto-expire badge |
| 73 | + category?: string // group: "ui", "api", "billing" |
| 74 | + type?: string // "feature" | "improvement" | "fix" | "deprecation" |
| 75 | + priority?: string // "low" | "medium" | "high" | "critical" |
| 76 | + cta?: { label: string; url: string } |
| 77 | + audience?: Record<string, string[]> // user segmentation |
| 78 | +} |
| 79 | +``` |
| 80 | + |
| 81 | +## Storage Adapters |
| 82 | + |
| 83 | +Default: `LocalStorageAdapter` (browser). Server: `PostgresAdapter`, `RedisAdapter`. |
| 84 | +Offline: `IndexedDBAdapter`. Hybrid: `HybridAdapter` (local + remote sync). |
| 85 | +Custom: implement `{ getWatermark, setWatermark, getDismissedIds, addDismissedId }`. |
| 86 | + |
| 87 | +## Provider Props |
| 88 | + |
| 89 | +```tsx |
| 90 | +<FeatureDropProvider |
| 91 | + manifest={features} // required |
| 92 | + storage={adapter} // required |
| 93 | + analytics={{ onFeatureSeen, onFeatureDismissed, onFeatureClicked }} |
| 94 | + userContext={{ plan, role, region }} // for audience targeting |
| 95 | + appVersion="2.1.0" // semver gating |
| 96 | + throttle={{ maxToastsPerSession: 3, modalCooldownMs: 120_000 }} |
| 97 | + locale="en" // i18n (en/es/fr/de/pt/zh-cn/ja/ko/ar/hi) |
| 98 | + animation="normal" // "none" | "subtle" | "normal" | "playful" |
| 99 | + engine={engineInstance} // optional: FeatureDropEngine for smart delivery |
| 100 | +/> |
| 101 | +``` |
| 102 | + |
| 103 | +## Tailwind Integration |
| 104 | + |
| 105 | +```ts |
| 106 | +// tailwind.config.ts |
| 107 | +import { featureDropPlugin } from 'featuredrop/tailwind' |
| 108 | + |
| 109 | +export default { |
| 110 | + plugins: [featureDropPlugin({ prefix: 'fd' })], |
| 111 | +} |
| 112 | +// Adds: fd-badge, fd-badge-dot, fd-badge-count, fd-animate-pulse, fd-animate-fade-in |
| 113 | +// CSS vars: --fd-new, --fd-changelog-bg, --fd-tour-bg (auto dark mode) |
| 114 | +``` |
| 115 | + |
| 116 | +## Rules |
| 117 | + |
| 118 | +- Always use subpath imports (`featuredrop/react`, not just `featuredrop`) |
| 119 | +- Prefer hooks from `featuredrop/react/hooks` when the project uses shadcn, Radix, or custom design system |
| 120 | +- Features auto-expire via `showNewUntil` — don't build manual expiry logic |
| 121 | +- Zero production dependencies — don't add external deps |
| 122 | +- TypeScript strict mode — no `any` types |
| 123 | +- All components support headless mode via render props |
| 124 | +- Core < 3 kB, React ~12 kB, fully tree-shakeable |
0 commit comments