Component Usage Analytics
Component Usage Analytics
Overview
Track component usage across your codebase to make data-driven decisions about deprecation, refactoring, and component library management.
Key Use Cases:
- Find all usages of a component
- Analyze impact of breaking changes
- Plan component deprecations
- Track adoption of new components
- Identify unused components
When to Use This Skill
Trigger this skill when the user:
- Asks "where is this component used?"
- Wants to "deprecate a component" or "plan a migration"
- Mentions "component analytics" or "usage tracking"
- Asks about "which components are unused"
- Wants to "analyze breaking change impact"
- Needs to "track component adoption"
Core Capabilities
1. Usage Analysis
Find all component usages with context:
$ npm run analyze:usage Button
Analyzing Button component...
📊 Usage Report:
Total Usages: 52 imports across 47 files
By Feature:
- Dashboard: 15 usages (8 files)
- Settings: 12 usages (7 files)
- Profile: 8 usages (5 files)
- Auth: 7 usages (4 files)
- Admin: 10 usages (23 files)
By Variant:
- Primary: 34 usages (65%)
- Secondary: 13 usages (25%)
- Outline: 5 usages (10%)
Recent Changes:
- Button@v2 released 14 days ago
- 8 files still using Button@v1 (deprecated)
- Migration progress: 83% (44/52 files)
Top Users (files with most usages):
1. src/features/Dashboard/widgets.tsx (6 usages)
2. src/features/Settings/preferences.tsx (4 usages)
3. src/features/Profile/edit.tsx (3 usages)
2. Deprecation Planning
Analyze impact before deprecating:
$ npm run analyze:deprecate Button@v1
⚠️ Deprecation Impact Analysis: Button@v1
Current Usage:
- 8 files still using v1
- 12 total usages
- Across 3 features
Migration Effort:
Low effort: 5 files (simple props update)
Medium effort: 2 files (variant renamed)
High effort: 1 file (custom styling conflicts)
Breaking Changes in v2:
1. 'success' variant removed → use 'primary' with success color
2. 'loading' prop renamed → use 'pending' prop
3. 'icon' prop now requires IconComponent type
Estimated Migration Time:
- Low effort files: 30 mins total (6 mins each)
- Medium effort files: 1 hour total (30 mins each)
- High effort file: 2 hours (complex refactor)
Total: ~3.5 hours
Recommendations:
1. Create migration guide for developers
2. Add deprecation warnings to v1
3. Set sunset date: 30 days from now
4. Track migration progress weekly
Generate migration guide? [Yes] [No]
3. Unused Component Detection
Find components that can be removed:
$ npm run analyze:unused
Scanning codebase...
🗑️ Unused Components (12 found):
Safe to Remove (no usages):
1. LegacyCard - Last used 6 months ago
2. OldButton - Replaced by Button v2
3. DeprecatedModal - Migrated to Modal v3
Potentially Unused (only in stories/tests):
4. ExperimentalBadge - Used in Storybook only
5. PrototypeAlert - Used in visual tests only
Low Usage (< 5 usages):
6. RareTooltip - 2 usages (last 90 days)
7. SpecializedInput - 3 usages (niche use case)
Recommendations:
- Remove: LegacyCard, OldButton, DeprecatedModal
- Review: ExperimentalBadge, PrototypeAlert
- Keep: RareTooltip, SpecializedInput (still needed)
Estimated bundle savings: 47 KB (8% reduction)
4. Adoption Tracking
Track new component adoption:
$ npm run analyze:adoption Button@v2
📈 Adoption Report: Button@v2 (released 14 days ago)
Current Adoption:
- 44 files using v2 (83%)
- 8 files still on v1 (17%)
Adoption Trend:
Day 1-7: 32 files migrated (61%)
Day 8-14: 12 files migrated (22%)
This week: 0 new migrations
Migration Velocity:
- Week 1: 4.6 files/day
- Week 2: 1.7 files/day
- Slowing down ⚠️
Blockers:
- High effort migration in src/Admin/dashboard.tsx
- Team waiting for migration guide
- Need code review bandwidth
Actions:
1. Publish migration guide (high priority)
2. Schedule pairing session for high-effort file
3. Set team goal: 100% migration by end of month
Technical Implementation
Component Usage Scanner
// scripts/scan-usage.ts
interface ComponentUsage {
component: string;
version: string;
file: string;
line: number;
importPath: string;
props: string[];
variant?: string;
}
async function scanComponentUsage(
componentName: string
): Promise<ComponentUsage[]> {
const usages: ComponentUsage[] = [];
// Find all files importing the component
const files = await findImports(componentName);
for (const file of files) {
const ast = parseFile(file);
// Find JSX usages
const jsxElements = findJSXElements(ast, componentName);
for (const element of jsxElements) {
usages.push({
component: componentName,
version: getComponentVersion(file, componentName),
file: file.path,
line: element.loc.start.line,
importPath: getImportPath(ast, componentName),
props: extractProps(element),
variant: getVariant(element),
});
}
}
return usages;
}
function getVariant(element: JSXElement): string | undefined {
// Look for variant prop
const variantProp = element.attributes.find(
attr => attr.name === 'variant'
);
if (variantProp && variantProp.value.type === 'StringLiteral') {
return variantProp.value.value;
}
return undefined;
}
Deprecation Impact Analyzer
// scripts/analyze-deprecation.ts
interface DeprecationImpact {
component: string;
version: string;
totalUsages: number;
affectedFiles: number;
affectedFeatures: string[];
migrationEffort: {
low: number;
medium: number;
high: number;
};
breakingChanges: string[];
estimatedHours: number;
}
async function analyzeDeprecationImpact(
component: string,
version: string
): Promise<DeprecationImpact> {
const usages = await scanComponentUsage(component);
const versionUsages = usages.filter(u => u.version === version);
// Group by file
const fileGroups = groupBy(versionUsages, u => u.file);
// Analyze migration effort for each file
const efforts = await Promise.all(
Object.entries(fileGroups).map(([file, fileUsages]) =>
analyzeMigrationEffort(file, fileUsages)
)
);
// Categorize by effort
const migrationEffort = {
low: efforts.filter(e => e.effort === 'low').length,
medium: efforts.filter(e => e.effort === 'medium').length,
high: efforts.filter(e => e.effort === 'high').length,
};
// Estimate total hours
const estimatedHours =
migrationEffort.low * 0.1 +
migrationEffort.medium * 0.5 +
migrationEffort.high * 2;
// Get breaking changes
const breakingChanges = await getBreakingChanges(component, version);
return {
component,
version,
totalUsages: versionUsages.length,
affectedFiles: Object.keys(fileGroups).length,
affectedFeatures: extractFeatures(versionUsages),
migrationEffort,
breakingChanges,
estimatedHours,
};
}
async function analyzeMigrationEffort(
file: string,
usages: ComponentUsage[]
): Promise<{ file: string; effort: 'low' | 'medium' | 'high' }> {
const code = await readFile(file);
// Factors that increase effort:
// - Custom styling on component
// - Complex prop transformations
// - Type conflicts
// - Multiple usages in same file
let complexityScore = 0;
// Check for custom styling
if (code.includes('styled(') && code.includes(usages[0].component)) {
complexityScore += 2;
}
// Check for prop spreading
if (usages.some(u => u.props.includes('...'))) {
complexityScore += 1;
}
// Number of usages
if (usages.length > 5) {
complexityScore += 1;
}
// Categorize
if (complexityScore === 0) return { file, effort: 'low' };
if (complexityScore <= 2) return { file, effort: 'medium' };
return { file, effort: 'high' };
}
Unused Component Detector
// scripts/detect-unused.ts
interface UnusedComponent {
name: string;
path: string;
usageCount: number;
lastUsed?: Date;
category: 'safe-to-remove' | 'potentially-unused' | 'low-usage';
bundleSize: number;
}
async function detectUnusedComponents(): Promise<UnusedComponent[]> {
// Get all components
const components = await getAllComponents();
const unused: UnusedComponent[] = [];
for (const component of components) {
const usages = await scanComponentUsage(component.name);
// Exclude test and story usages for "potentially unused" check
const productionUsages = usages.filter(
u => !u.file.includes('.test.') && !u.file.includes('.stories.')
);
let category: UnusedComponent['category'];
if (productionUsages.length === 0 && usages.length === 0) {
category = 'safe-to-remove';
} else if (productionUsages.length === 0) {
category = 'potentially-unused';
} else if (productionUsages.length < 5) {
category = 'low-usage';
} else {
continue; // Not unused
}
// Get last usage date
const lastUsage = usages.length > 0
? await getLastModifiedDate(usages[0].file)
: await getLastModifiedDate(component.path);
// Get bundle size
const bundleSize = await getComponentBundleSize(component.path);
unused.push({
name: component.name,
path: component.path,
usageCount: productionUsages.length,
lastUsed: lastUsage,
category,
bundleSize,
});
}
return unused;
}
Example Commands
Analyze Single Component
npm run analyze:usage Button
# Output: Usage report for Button component
Deprecation Analysis
npm run analyze:deprecate Button@v1
# Output: Deprecation impact analysis with migration effort
Find Unused Components
npm run analyze:unused
# Output: List of unused/low-usage components with recommendations
Track Adoption
npm run analyze:adoption Button@v2
# Output: Adoption metrics and migration progress
Generate Migration Guide
npm run generate:migration-guide Button@v1 Button@v2
# Output: Markdown migration guide with examples
Integration with CI/CD
# .github/workflows/component-analytics.yml
name: Component Analytics
on:
schedule:
- cron: '0 0 * * 0' # Weekly on Sunday
jobs:
analytics:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: npm ci
- name: Analyze component usage
run: npm run analyze:all
- name: Generate report
run: npm run generate:analytics-report
- name: Create issue for unused components
run: |
npm run analyze:unused --json > unused.json
gh issue create --title "Weekly: Unused Components" \
--body-file unused.json \
--label "maintenance,components"
Dashboard Integration
Create a component analytics dashboard:
// src/analytics/dashboard.tsx
export function ComponentAnalyticsDashboard() {
const [analytics, setAnalytics] = useState<Analytics | null>(null);
useEffect(() => {
loadAnalytics().then(setAnalytics);
}, []);
return (
<div>
<h1>Component Usage Analytics</h1>
<section>
<h2>Most Used Components</h2>
<BarChart data={analytics?.topComponents} />
</section>
<section>
<h2>Unused Components</h2>
<Table data={analytics?.unusedComponents} />
</section>
<section>
<h2>Migration Progress</h2>
<MigrationProgressChart data={analytics?.migrations} />
</section>
<section>
<h2>Adoption Trends</h2>
<LineChart data={analytics?.adoptionTrends} />
</section>
</div>
);
}
Best Practices
- Regular Scanning - Run analytics weekly or on PR merges
- Track Trends - Monitor adoption over time, not just snapshots
- Automate Alerts - Create issues for unused components automatically
- Migration Planning - Use effort estimates for sprint planning
- Documentation - Generate migration guides from analysis results
Limitations
- Requires AST parsing (works with TS/JS/TSX/JSX)
- May miss dynamic imports
- Cannot detect runtime usage patterns
- Estimates are guidelines, not precise timings
Integration with Other Skills
- visual-regression-testing - Test after component migrations
- accessibility-remediation - Verify a11y after refactoring
- story-generation - Generate stories for migrated components
- ci-cd-generator - Add analytics to CI pipeline
Files Reference
references/ast-parsing.md- AST parsing techniquesexamples/migration-guides.md- Example migration guidesscripts/scan-usage.ts- Usage scannerscripts/analyze-deprecation.ts- Deprecation analyzerscripts/detect-unused.ts- Unused component detector
Summary
Component Usage Analytics provides data-driven insights for managing your component library. Track usage, plan deprecations, detect unused code, and monitor adoption.
Key Benefits:
- ✅ Data-driven component decisions
- ✅ Safe deprecation planning
- ✅ Identify bundle bloat
- ✅ Track migration progress
- ✅ Optimize component library
Use this skill to analyze component usage, plan deprecations, find unused components, and track adoption metrics.
More from flight505/storybook-assistant
visual-design
Generate style guides, component mockups, and visual assets using AI (Gemini 3 Pro Image, FLUX.2 Pro). Optional feature - gracefully skips if OPENROUTER_API_KEY unavailable.
7plugin guide & help
Use this skill when users ask specifically about the Storybook Assistant plugin - "what can the storybook assistant do", "storybook plugin features", "storybook assistant commands", "help with storybook assistant", "storybook plugin capabilities". ONLY triggers when user explicitly mentions "storybook assistant", "storybook plugin", or asks about Storybook-specific features. Does NOT trigger on generic help questions.
7ai-powered visual regression testing
Use this skill when users mention "visual regression", "detect UI changes", "screenshot comparison", "visual testing", "pixel diff", "UI regression", or want to set up intelligent visual testing that understands intentional vs accidental changes. Analyzes visual diffs with AI to categorize changes as expected, warnings, or errors based on git history and design tokens.
7storybook-config
Generate and configure Storybook 10 for any framework with automatic detection, SOTA best practices, and platform-specific optimizations (Web, Tauri, Electron)
5bidirectional design token sync
Use this skill when users mention "sync design tokens", "Figma to code", "design system sync", "token drift", "keep tokens in sync", or want to synchronize design tokens between Figma and codebase bidirectionally with automatic drift detection and conflict resolution.
5story-generation
Use this skill when the user asks to "generate stories for components", "parse component props", "detect component variants", "analyze components", "create stories automatically", mentions "component parser", "story automation", or wants to generate Storybook stories from existing component files. This skill provides intelligent component analysis and CSF 3.0 story generation with interaction tests and accessibility checks.
4