Skip to content

Commit 2b6f912

Browse files
thegdsksglinr
andcommitted
feat: Phase J v2.7 — headless hooks, tailwind plugin, engine interface, AI-native
- Add featuredrop/react/hooks subpath with useChangelog() and 10-hook barrel - Add featuredrop/tailwind plugin with CSS vars, keyframes, dark mode, reduced-motion - Add FeatureDropEngine interface + 7 types (TimingDecision, AdoptionScore, etc.) - Wire engine prop to FeatureDropProvider with initialize/destroy lifecycle - Add Claude Code plugin structure (.claude-plugin/ + skills/) - Add Context7 config for AI documentation indexing - Add .cursorrules template and Claude skill reference - Update README with Headless Hooks and AI-Native sections Co-Authored-By: Glinr <bot@glincker.com>
1 parent 5576dc8 commit 2b6f912

16 files changed

Lines changed: 826 additions & 14 deletions

File tree

.claude-plugin/plugin.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "featuredrop",
3+
"description": "AI-assisted product adoption setup — changelogs, tours, checklists, badges, feedback widgets. Helps Claude Code configure FeatureDrop in any project.",
4+
"version": "2.5.0",
5+
"author": {
6+
"name": "GLINR STUDIOS",
7+
"url": "https://glincker.com"
8+
},
9+
"homepage": "https://featuredrop.dev",
10+
"repository": "https://github.com/GLINCKER/featuredrop",
11+
"license": "MIT",
12+
"keywords": [
13+
"feature-discovery",
14+
"changelog",
15+
"product-tours",
16+
"onboarding",
17+
"saas",
18+
"react",
19+
"developer-tools"
20+
]
21+
}

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ claude.md
5858
.windsurf/
5959
.wrangler/
6060
.zencoder/
61-
skills/
61+
skills/*
62+
!skills/featuredrop-setup/
6263
skills-lock.json
6364

6465
# Debug

README.md

Lines changed: 77 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -223,18 +223,84 @@ npx featuredrop migrate --from launchnotes --input launchnotes-export.json
223223

224224
---
225225

226-
## React Hooks
226+
## Headless Hooks (for shadcn / custom UI)
227227

228-
| Hook | Returns |
229-
|---|---|
230-
| `useFeatureDrop()` | Full context: features, count, dismiss, throttle controls |
231-
| `useNewFeature(key)` | Single nav item: `{ isNew, feature, dismiss }` |
232-
| `useNewCount()` | Current unread badge count |
233-
| `useTour(id)` | Imperative tour controls and step snapshot |
234-
| `useTourSequencer(sequence)` | Ordered multi-tour orchestration |
235-
| `useChecklist(id)` | Checklist progress + task controls |
236-
| `useSurvey(id)` | Survey controls: `show`, `hide`, `askLater` |
237-
| `useTabNotification()` | Browser tab title count: `"(3) My App"` |
228+
Don't want our components? Use hooks — **data + actions, zero JSX**:
229+
230+
```tsx
231+
import { useChangelog } from 'featuredrop/react/hooks'
232+
import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet'
233+
import { Badge } from '@/components/ui/badge'
234+
235+
function MyChangelog() {
236+
const { newFeatures, newCount, dismiss, markAllSeen } = useChangelog()
237+
238+
return (
239+
<Sheet onOpenChange={() => markAllSeen()}>
240+
<SheetTrigger>
241+
What's New {newCount > 0 && <Badge>{newCount}</Badge>}
242+
</SheetTrigger>
243+
<SheetContent>
244+
{newFeatures.map(f => (
245+
<div key={f.id} onClick={() => dismiss(f.id)}>
246+
<h3>{f.label}</h3>
247+
<p>{f.description}</p>
248+
</div>
249+
))}
250+
</SheetContent>
251+
</Sheet>
252+
)
253+
}
254+
```
255+
256+
| Hook | Import | Returns |
257+
|---|---|---|
258+
| `useFeatureDrop()` | `featuredrop/react/hooks` | Full context: features, count, dismiss, throttle controls |
259+
| `useNewFeature(key)` | `featuredrop/react/hooks` | `{ isNew, feature, dismiss }` |
260+
| `useNewCount()` | `featuredrop/react/hooks` | Current unread badge count |
261+
| `useChangelog()` | `featuredrop/react/hooks` | `{ features, newFeatures, newCount, dismiss, dismissAll, markAllSeen, getByCategory }` |
262+
| `useTour(id)` | `featuredrop/react/hooks` | Imperative tour controls and step snapshot |
263+
| `useTourSequencer(sequence)` | `featuredrop/react/hooks` | Ordered multi-tour orchestration |
264+
| `useChecklist(id)` | `featuredrop/react/hooks` | Checklist progress + task controls |
265+
| `useSurvey(id)` | `featuredrop/react/hooks` | Survey controls: `show`, `hide`, `askLater` |
266+
| `useTabNotification()` | `featuredrop/react/hooks` | Browser tab title count: `"(3) My App"` |
267+
268+
> **When to use hooks vs components:** If your project uses shadcn/ui, Radix, or any custom design system, use hooks from `featuredrop/react/hooks`. If you want out-of-the-box UI, use components from `featuredrop/react`.
269+
270+
---
271+
272+
## AI-Native
273+
274+
FeatureDrop is built for the AI coding era. Your AI assistant already knows how to use it.
275+
276+
### Claude Code Plugin
277+
278+
```bash
279+
# Install the plugin — Claude Code learns FeatureDrop's API automatically
280+
/plugin install featuredrop
281+
```
282+
283+
Then just ask: *"Add a changelog widget with auto-expiring badges to my app"* — Claude handles the rest.
284+
285+
### Cursor / Copilot
286+
287+
```bash
288+
# Auto-detect your IDE and copy the right context files
289+
npx featuredrop ai-setup
290+
```
291+
292+
### Tailwind Plugin
293+
294+
```ts
295+
// tailwind.config.ts
296+
import { featureDropPlugin } from 'featuredrop/tailwind'
297+
298+
export default {
299+
plugins: [featureDropPlugin()],
300+
// Adds: fd-badge, fd-badge-dot, fd-badge-count, animations, CSS variables
301+
// Auto dark mode, reduced-motion support
302+
}
303+
```
238304

239305
---
240306

context7.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"$schema": "https://context7.com/schema/context7.json",
3+
"projectTitle": "FeatureDrop",
4+
"description": "Open-source product adoption toolkit — changelogs, badges, tours, checklists, hotspots, feedback widgets, surveys. Zero dependencies, < 3 kB core, 8 framework adapters, 12 storage adapters. Free Beamer/Pendo alternative.",
5+
"folders": ["apps/docs/content", "skills"],
6+
"excludeFolders": ["node_modules", "dist", "coverage", ".git", "examples", "docs-local"],
7+
"excludeFiles": ["CHANGELOG.md", "CODE_OF_CONDUCT.md"],
8+
"rules": [
9+
"Always use subpath imports: featuredrop/react, featuredrop/react/hooks, featuredrop/adapters",
10+
"Prefer hooks from featuredrop/react/hooks for custom design systems (shadcn, Radix, etc.)",
11+
"Features are defined in a JSON manifest with { id, label, description, releasedAt, showNewUntil? }",
12+
"Core bundle is under 3 kB gzipped with zero production dependencies",
13+
"All components support headless mode via render props for full customization"
14+
]
15+
}

package.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,26 @@
195195
"types": "./dist/testing.d.cts",
196196
"default": "./dist/testing.cjs"
197197
}
198+
},
199+
"./react/hooks": {
200+
"import": {
201+
"types": "./dist/react-hooks.d.ts",
202+
"default": "./dist/react-hooks.js"
203+
},
204+
"require": {
205+
"types": "./dist/react-hooks.d.cts",
206+
"default": "./dist/react-hooks.cjs"
207+
}
208+
},
209+
"./tailwind": {
210+
"import": {
211+
"types": "./dist/tailwind.d.ts",
212+
"default": "./dist/tailwind.js"
213+
},
214+
"require": {
215+
"types": "./dist/tailwind.d.cts",
216+
"default": "./dist/tailwind.cjs"
217+
}
198218
}
199219
},
200220
"typesVersions": {
@@ -246,6 +266,12 @@
246266
],
247267
"flags": [
248268
"./dist/flags.d.ts"
269+
],
270+
"react/hooks": [
271+
"./dist/react-hooks.d.ts"
272+
],
273+
"tailwind": [
274+
"./dist/tailwind.d.ts"
249275
]
250276
}
251277
},
@@ -255,6 +281,11 @@
255281
"dist/**/*.d.ts",
256282
"dist/**/*.d.cts",
257283
"dist/**/*.map",
284+
".claude-plugin/**",
285+
"skills/**",
286+
"context7.json",
287+
"src/ai/cursorrules.txt",
288+
"src/ai/claude-skill.md",
258289
"README.md",
259290
"LICENSE"
260291
],

skills/featuredrop-setup/SKILL.md

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
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

Comments
 (0)