GitHub | Docs | npm | shadcn Components | Example App
Every product adoption tool — Pendo, Appcues, Chameleon — works the same way: collect weeks of server-side analytics, then tell you which users to nudge. They charge $250–$7,000/month for it.
We built a 4 kB client-side engine that makes the same decisions from session one. No server. No data collection. MIT licensed.
This is FeatureDrop v3. (v2 launch post here if you want the backstory — it blew up, so I kept building.)
TL;DR:
- Client-side behavioral engine, 4 kB, zero servers
- Picks the right format (badge / toast / modal) per user automatically
- Free, MIT licensed, 479 tests, works with Next.js / Remix / Astro / Nuxt + shadcn
The Problem With "Just Show It"
Every product adoption tool works the same way: you define a feature, pick a format (badge, modal, toast), set a date, and hope for the best.
But your power users don't need a modal. Your new users don't need a tiny badge. Someone who just dismissed three announcements doesn't want a fourth.
Pendo, Appcues, and Chameleon solve this with server-side analytics pipelines that take weeks to collect enough data.
We solved it with client-side analytics — in 4 kB, from the first session.
The Numbers
Before diving into the how — here's what v3 ships:
| Metric | v2.7 | v3.0 |
|---|---|---|
| Core bundle (gzip) | 3.01 kB | 3.02 kB |
| Engine bundle (gzip) | — | 4.08 kB |
| Tests | 374 | 479 |
| Subpath exports | 20 | 26 |
| Framework integrations | 7 | 11 |
| shadcn components | 0 | 5 |
| CLI commands | 9 | 10 |
The core didn't grow. Zero runtime dependencies. The engine is an opt-in 4 kB add-on. If you don't import it, you don't pay for it.
Meet the AdoptionEngine
npm install featuredrop@3
The AdoptionEngine is a plugin that tracks behavior locally and makes smart decisions:
┌─────────────────────────────────────────┐
│ AdoptionEngine │
├──────────────┬──────────────────────────┤
│ Behavior │ Tracks sessions, dismiss │
│ Tracker │ patterns, engagement │
├──────────────┼──────────────────────────┤
│ Timing │ Cooldowns, fatigue │
│ Optimizer │ detection, optimal gaps │
├──────────────┼──────────────────────────┤
│ Format │ Badge vs toast vs modal │
│ Selector │ based on user behavior │
├──────────────┼──────────────────────────┤
│ Adoption │ A-F grading, breakdown, │
│ Scorer │ recommendations │
└──────────────┴──────────────────────────┘
Here's how you use it:
import { FeatureDropProvider } from 'featuredrop/react'
import { createAdoptionEngine } from 'featuredrop/engine'
import { LocalStorageAdapter } from 'featuredrop'
import features from './features.json'
const engine = createAdoptionEngine()
function App() {
return (
<FeatureDropProvider
manifest={features}
storage={new LocalStorageAdapter()}
engine={engine}
>
<YourApp />
</FeatureDropProvider>
)
}
That's it. The engine now observes user behavior and makes decisions. No config.
useSmartFeature — The Hook That Thinks
Instead of manually deciding "show a badge for this feature," you ask the engine:
import { useSmartFeature } from 'featuredrop/react/hooks'
function Sidebar() {
const { show, format, feature, dismiss, confidence } =
useSmartFeature('ai-search')
if (!show) return null
// Engine decided: badge for power users, toast for new users
if (format === 'badge') return <Badge onClick={dismiss}>{feature.label}</Badge>
if (format === 'toast') return <Toast onClose={dismiss}>{feature.description}</Toast>
if (format === 'banner') return <Banner onDismiss={dismiss}>{feature.label}</Banner>
}
The confidence score tells you how sure the engine is. First session? Low confidence, conservative format. Tenth session with clear patterns? High confidence, optimal format.
Without the engine, the hook gracefully degrades — always shows, always uses badge format. Zero breaking changes.
SmartAnnouncement — Zero-Config Component
Don't want to write conditional rendering? One component handles everything:
import { SmartAnnouncement } from 'featuredrop/react'
// Engine picks the format automatically
<SmartAnnouncement featureId="dark-mode" />
// Or bring your own UI with render props
<SmartAnnouncement featureId="dark-mode">
{({ feature, format, dismiss }) => (
<MyCustomCard title={feature.label} onClose={dismiss} />
)}
</SmartAnnouncement>
Six built-in format renderers: badge, toast, banner, inline, modal, spotlight. Each adapts to the user.
Framework-Native, Not Framework-Adjacent
v3 ships first-class integrations for every major meta-framework. Not wrappers — native patterns.
Next.js (App Router + RSC)
// app/layout.tsx — Server Component
import { getNewCountServer, FeatureDropScript } from 'featuredrop/next'
export default async function Layout({ children }) {
const manifest = await getManifest()
const dismissed = await getDismissedIds(userId)
const newCount = getNewCountServer(manifest, dismissed)
return (
<html>
<body>
{/* Hydrates client provider — no flash of "0 new" */}
<FeatureDropScript manifest={manifest} dismissedIds={dismissed} />
<nav>
What's New {newCount > 0 && <span>{newCount}</span>}
</nav>
{children}
</body>
</html>
)
}
Also ships native integrations for Remix, Astro, and Nuxt — each creates a fresh MemoryAdapter per request, no shared state, no race conditions.
shadcn Registry — Copy-Paste React Components
If you use shadcn/ui, you can now install FeatureDrop components directly:
# Changelog widget for React — yours to customize
npx shadcn@latest add https://featuredrop.dev/r/changelog-widget.json
npx shadcn@latest add https://featuredrop.dev/r/new-badge.json
npx shadcn@latest add https://featuredrop.dev/r/tour.json
npx shadcn@latest add https://featuredrop.dev/r/checklist.json
npx shadcn@latest add https://featuredrop.dev/r/feedback-widget.json
The shadcn registry turns FeatureDrop into a React component library that lives in your codebase. They use your existing shadcn primitives (Badge, Sheet, Dialog), your Tailwind theme, your design tokens. Not our CSS — yours.
AI-Native Developer Experience
Every AI coding assistant now understands FeatureDrop:
npx featuredrop ai-setup
This auto-detects your editor and creates the right context:
| Editor | What it creates |
|---|---|
| Claude Code |
.claude/skills/featuredrop.md + MCP config |
| Cursor |
.cursorrules + .cursor/mcp.json
|
| VS Code | .vscode/mcp.json |
The MCP server gives your AI assistant 5 tools (scaffold features, validate manifests, suggest components) and 6 resources (hooks reference, component catalog, adapter guide).
Tell Claude "add a changelog to my sidebar" and it generates correct imports, hooks, and provider setup — first try.
The Open Source Pendo Alternative
If you're evaluating product adoption tools, here's what the market charges:
| Capability | Pendo | FeatureDrop v3 |
|---|---|---|
| Feature announcements | Yes | Yes |
| Product tours | Yes | Yes |
| Checklists | Yes | Yes |
| NPS/Surveys | Yes | Yes |
| Feedback collection | Yes | Yes |
| Smart timing | Server-side, weeks of data | Client-side, session 1 |
| Format adaptation | Manual rules | Automatic |
| Adoption scoring | Dashboard only | In-app hooks |
| Bundle size | 100-300 kB | 3 kB core + 4 kB engine |
| Data collection | Their servers | Your browser. That's it. |
| Price | $7,000+/year | $0 |
| Vendor lock-in | Yes | MIT licensed |
Key takeaway: You don't need a $7k analytics pipeline to make smart adoption decisions. A 4 kB client-side engine with localStorage is enough.
Get Started in 5 Minutes
npm install featuredrop
- Create
features.jsonwith your features - Wrap your app in
<FeatureDropProvider> - Drop
<SmartAnnouncement featureId="..." />wherever you want - Done. The engine handles the rest.
GitHub | Docs | shadcn Components | Example App
FeatureDrop Cloud (hosted dashboard for teams) is coming soon. The open-source library stays free forever.
If you've used Pendo, Appcues, or Beamer — what made you pay for them vs. building in-house? I'd love to hear in the comments.
I'm GDS K S, building FeatureDrop at GLINR Studios. Star the repo if this is useful.
Top comments (0)