42 KiB
Keywords Library Page Redesign Plan
Created: January 18, 2026
Updated: January 19, 2026 (v1.8.2 released)
Status: ✅ COMPLETED & DOCUMENTED (v1.8.2)
Page: /keywords-library (was /setup/add-keywords)
Priority: 🟢 COMPLETED
Executive Summary
Comprehensive redesign of the Keywords Library page completed and deployed in v1.8.2:
- ✅ Standardize naming to "Keywords Library" across frontend, backend, URLs, menus, and admin
- ✅ Implement cascading filters like Planner pages (Keywords, Clusters, Ideas)
- ⬜ Remove sector selector from AppHeader, use site-only selector (partial - route updated)
- ✅ Add Sector Metric Cards with clickable filtering + 6 bulk add stat options
- ✅ Redesign Smart Suggestions to appear after search/filter with breathing indicator
- ⬜ Center filter bar with sector filter added, matching Planner page styling (needs polish)
- ⬜ Show table data by default (remove "Browse" toggle) (kept existing UX for now)
- ✅ No backward compatibility - single source of truth
- ✅ CRITICAL FIX: Sector-specific filtering - sites now only see keywords from their configured sectors
Release: Version 1.8.2 - January 19, 2026
Changelog: See /CHANGELOG.md for complete details
API Documentation: See /docs/20-API/ENDPOINTS.md for Keywords Library endpoints
Part 1: Terminology Standardization
Current State (Inconsistent)
| Location | Current Term | Usage |
|---|---|---|
| Sidebar | "Keyword Library" | ❌ Should be "Keywords Library" |
| Page Title | "Keyword Library" | ❌ Should be "Keywords Library" |
| URL | /setup/add-keywords |
❌ Legacy |
| Backend Model | SeedKeyword |
✅ Keep internal |
| Backend URL | /v1/auth/seed-keywords/ |
❌ Legacy |
| Backend Admin | "Industry Sector Keywords" | ❌ Should be "Keywords Library" |
| Frontend API | fetchSeedKeywords() |
❌ Legacy |
| High Opportunity | "Quick-Start Keywords" | ❌ Different term |
| Search Modal | Mixed terms | ❌ Inconsistent |
| Onboarding | "Add Keywords" | ❌ Legacy |
| Marketing Pages | "Seed Keywords", "High-Opportunity" | ❌ Mixed |
Target State (Unified)
Standardized Term: "Keywords Library" (plural "Keywords")
Internal/Code: Keep SeedKeyword model name internally
| Location | New Term |
|---|---|
| Sidebar | "Keywords Library" |
| Page Title | "Keywords Library" |
| URL | /keywords-library (NO redirect from legacy) |
| Backend URL | /v1/keywords-library/ (NO legacy alias) |
| Backend Admin | "Keywords Library" |
| Frontend API | fetchKeywordsLibrary() (replace fetchSeedKeywords) |
| Smart Suggestions | "Smart Suggestions" |
| Search Modal | "Keywords Library" |
| Onboarding Step | "Browse Keywords Library" |
Files to Update
Frontend:
- src/layout/AppSidebar.tsx - Menu label → "Keywords Library"
- src/layout/AppHeader.tsx - Route patterns
- src/App.tsx - Route definition (NO redirect, direct change)
- src/components/common/SearchModal.tsx - Search references
- src/components/onboarding/OnboardingWizard.tsx - Step 4 name
- src/components/onboarding/steps/Step4AddKeywords.tsx - Rename to Step4KeywordsLibrary.tsx
- src/components/sites/SiteSetupChecklist.tsx - Link text
- src/services/api.ts - Rename function to fetchKeywordsLibrary()
- src/marketing/pages/Pricing.tsx - Feature descriptions
- src/marketing/pages/Solutions.tsx - Feature descriptions
Backend:
- igny8_core/auth/urls.py - Change URL to /keywords-library/
- igny8_core/admin/ - Change admin menu label to "Keywords Library"
- Keep model name as SeedKeyword (internal only)
Part 2: Filter System Redesign
Current Filters (Keywords Library)
[Search] [Country ▼] [Difficulty ▼] [Status ▼]
Issues:
- ❌ No "Clear Filters" button near active filter indicator
- ❌ No Volume filter (exists on Planner Keywords page)
- ❌ No Sector filter in filter bar
- ❌ Hardcoded country/difficulty options (not cascading)
- ❌ Filters don't show only available options based on current data
- ❌ Active/Clear button positioning doesn't match Planner pages
Target Filters (Match Planner Pages Pattern)
┌─────────────────────────────────────────────────────────────────────────────────┐
│ [🔍 Search] [Sector ▼] [Volume ▼] [Difficulty ▼] [Country ▼] [Status ▼] │
│ │
│ Active: 2 filters [Clear] ← Same position as Planner pages │
│ │
│ ℹ️ Search 54,180 keywords. Filter by volume or difficulty to find your │
│ perfect keywords! │
└─────────────────────────────────────────────────────────────────────────────────┘
Improvements:
- ✅ Active count + Clear button positioned same as Planner pages
- ✅ Add Volume range filter (min/max popup like Planner pages)
- ✅ Add Sector filter dropdown
- ✅ Keep "Not Yet Added" status filter (in_workflow filter)
- ✅ Implement cascading filters - options reflect available data
- ✅ Center filter bar with explainer text below
Filter: Status Options
| Value | Label | Description |
|---|---|---|
all |
All Keywords | Show all keywords |
available |
Not Yet Added | Keywords not in any workflow |
in_workflow |
In Workflow | Keywords already added to site |
Backend API Changes
New Endpoint: GET /v1/keywords-library/filter_options/
Returns available filter options based on current filters (cascading):
# Example Request
GET /v1/keywords-library/filter_options/?industry=5§or=12&difficulty_max=40
# Response
{
"sectors": [
{"value": 12, "label": "Technology", "count": 1250},
{"value": 15, "label": "Mobile Apps", "count": 340},
...
],
"countries": [
{"value": "US", "label": "United States", "count": 1250},
{"value": "GB", "label": "United Kingdom", "count": 340},
...
],
"difficulties": [
{"value": "1", "label": "Very Easy (1-20)", "count": 890},
{"value": "2", "label": "Easy (21-40)", "count": 450},
{"value": "3", "label": "Medium (41-60)", "count": 320},
{"value": "4", "label": "Hard (61-80)", "count": 180},
{"value": "5", "label": "Very Hard (81-100)", "count": 90},
],
"volume_stats": {
"min": 0,
"max": 421000,
"avg": 5420,
"p50": 1200,
"p90": 15000
},
"total_matching": 1590
}
Difficulty Mapping (Backend 1-100 → Frontend 1-5)
| Frontend Level | Label | Backend Range |
|---|---|---|
| 1 | Very Easy | 1-20 |
| 2 | Easy | 21-40 |
| 3 | Medium | 41-60 |
| 4 | Hard | 61-80 |
| 5 | Very Hard | 81-100 |
Low Difficulty = Level 1 and 2 (backend ≤ 40)
Frontend Changes
- Add
fetchKeywordsLibraryFilterOptions()API function - Add Sector filter dropdown (populated from site's sectors)
- Add Volume filter component (reuse from Keywords.tsx)
- Position Active/Clear same as Planner pages
- Load filter options dynamically based on industry/sector selection
- Re-load options when any filter changes (cascading)
Part 3: App Header Selector Change
Current Behavior
- Keywords Library page shows
SiteAndSectorSelector(Site + Sector dropdowns) - This is redundant since page will have sector cards and sector filter
Target Behavior
- Show
SingleSiteSelector(Site only, like Automation pages) - Remove from
SITE_AND_SECTOR_ROUTESarray - Add to
SINGLE_SITE_ROUTESarray
Code Change (AppHeader.tsx)
const SITE_AND_SECTOR_ROUTES = [
'/planner',
'/writer',
- '/setup/add-keywords',
];
const SINGLE_SITE_ROUTES = [
'/automation',
'/publisher',
'/account/content-settings',
'/sites',
+ '/keywords-library',
];
Part 4: Sector Metric Cards
Design
Clickable sector cards that filter the table when clicked. Each card shows stats and has 5-6 bulk add options.
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Your Site Sectors [Add Sector]│
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ 💻 Technology │ │ 📱 Mobile Apps │ │ 🌐 Web Dev │ │
│ │ ─────────────────── │ │ ─────────────────── │ │ ─────────────────── │ │
│ │ │ │ │ │ │ │
│ │ Total: 1,245 │ │ Total: 892 │ │ Total: 456 │ │
│ │ Available: 1,200 │ │ Available: 880 │ │ Available: 456 │ │
│ │ In Workflow: 45 │ │ In Workflow: 12 │ │ In Workflow: 0 │ │
│ │ │ │ │ │ │ │
│ │ ─── Quick Add ───── │ │ ─── Quick Add ───── │ │ ─── Quick Add ───── │ │
│ │ │ │ │ │ │ │
│ │ 📈 High Volume │ │ 📈 High Volume │ │ 📈 High Volume │ │
│ │ 125 kw (>8.5K) │ │ 67 kw (>6.2K) │ │ 50 kw (>3.4K) │ │
│ │ [+50] [+100] │ │ [+50] [+67] │ │ [+50] │ │
│ │ │ │ │ │ │ │
│ │ 🎯 Low Difficulty │ │ 🎯 Low Difficulty │ │ 🎯 Low Difficulty │ │
│ │ 340 kw (≤40) │ │ 212 kw (≤40) │ │ 89 kw (≤40) │ │
│ │ [+50] [+100] │ │ [+50] [+100] │ │ [+50] [+89] │ │
│ │ │ │ │ │ │ │
│ │ 🔥 High Vol + Easy │ │ 🔥 High Vol + Easy │ │ 🔥 High Vol + Easy │ │
│ │ 45 kw │ │ 28 kw │ │ 12 kw │ │
│ │ [+45] │ │ [+28] │ │ [+12] │ │
│ │ │ │ │ │ │ │
│ │ 💎 Premium (>50K) │ │ 💎 Premium (>50K) │ │ 💎 Premium (>50K) │ │
│ │ 12 kw │ │ 8 kw │ │ 3 kw │ │
│ │ [+12] │ │ [+8] │ │ [+3] │ │
│ │ │ │ │ │ │ │
│ │ 🌱 Long Tail │ │ 🌱 Long Tail │ │ 🌱 Long Tail │ │
│ │ 890 kw (4+ words)│ │ 654 kw (4+ words)│ │ 312 kw (4+ words)│ │
│ │ [+50] [+100] │ │ [+50] [+100] │ │ [+50] [+100] │ │
│ │ │ │ │ │ │ │
│ │ [Browse All →] │ │ [Browse All →] │ │ [Browse All →] │ │
│ └─────────────────────┘ └─────────────────────┘ └─────────────────────┘ │
│ │
│ 💡 Click any card to filter the table by that sector │
└─────────────────────────────────────────────────────────────────────────────────┘
Click Behavior
- Click on sector card → Filter table by that sector
- Click on Quick Add button → Add keywords matching that criteria
Stats Per Sector Card (6 Options)
Based on actual keyword data analysis (volume ranges 50-281,000, difficulty 0-99). Dynamic fallback thresholds ensure every sector shows useful data:
| Stat | Criteria | Fallback Logic | Example |
|---|---|---|---|
| 📈 High Volume | Top 50/100 by volume | Dynamic threshold based on available data | "125 kw (>8.5K)" |
| 🎯 Low Difficulty | Difficulty ≤ 40 (levels 1-2) | Fixed threshold | "340 kw (≤40)" |
| 🔥 Best Opportunities | High vol + Difficulty ≤ 40 | Combines above two criteria | "45 kw" |
| 💎 Premium Traffic | Volume > 50,000 | If 0 → try >25,000 → if 0 → try >10,000 | "12 kw (>50K)" |
| 🌱 Long Tail | Words ≥ 4 AND Volume > 1,000 | If 0 → try >500 → if 0 → try >200 | "890 kw (4+ words, >1K)" |
| ⚡ Quick Wins | Difficulty ≤ 20 AND Volume > 1,000 + Available | If 0 → try >500 → if 0 → try >200 | "67 kw" |
Dynamic Threshold Fallback Logic
# Premium Traffic - cascading volume thresholds
def get_premium_traffic(keywords):
for threshold in [50000, 25000, 10000]:
count = keywords.filter(volume__gt=threshold).count()
if count > 0:
return {"count": count, "threshold": threshold}
return {"count": 0, "threshold": 10000}
# Long Tail - cascading volume with word count
def get_long_tail(keywords):
base = keywords.filter(word_count__gte=4)
for threshold in [1000, 500, 200]:
count = base.filter(volume__gt=threshold).count()
if count > 0:
return {"count": count, "min_volume": threshold}
return {"count": 0, "min_volume": 200}
# Quick Wins - cascading volume with low difficulty + available
def get_quick_wins(keywords, attached_ids):
base = keywords.filter(difficulty__lte=20).exclude(id__in=attached_ids)
for threshold in [1000, 500, 200]:
count = base.filter(volume__gt=threshold).count()
if count > 0:
return {"count": count, "min_volume": threshold}
return {"count": 0, "min_volume": 200}
This ensures every sector shows meaningful data regardless of size, making the feature always useful and operational.
High Volume Dynamic Threshold
Instead of fixed 10,000 threshold:
- Get top 50 keywords by volume for sector
- Show threshold as ">X" where X = lowest volume in top 50
- If < 50 keywords available, use top 100 threshold
- Example: "125 kw (>8,540)" means 125 keywords with volume > 8,540
Bulk Add Options
Each stat shows add buttons based on availability:
[+50]- Add top 50[+100]- Add top 100 (if > 50 available)[+200]- Add top 200 (if > 100 available)[+N]- Add all N (if N ≤ 200)
Always show confirmation modal before adding.
Backend API
Endpoint: GET /v1/keywords-library/sector_stats/
# Request
GET /v1/keywords-library/sector_stats/?site_id=21
# Response
{
"sectors": [
{
"sector_id": 12,
"sector_name": "Technology",
"sector_slug": "technology",
"total_keywords": 1245,
"available": 1200,
"in_workflow": 45,
"stats": {
"high_volume": {
"count": 125,
"threshold": 8540, // Dynamic: lowest volume in top 50/100
"total_volume": 1200000
},
"low_difficulty": {
"count": 340,
"threshold": 40, // Backend value (maps to frontend level 2)
"total_volume": 450000
},
"high_vol_easy": {
"count": 45,
"description": "High volume + Low difficulty"
},
"premium": {
"count": 12,
"threshold": 50000, // Dynamic: 50K → 25K → 10K fallback
"used_fallback": false
},
"long_tail": {
"count": 890,
"min_words": 4,
"min_volume": 1000, // Dynamic: 1K → 500 → 200 fallback
"used_fallback": false
},
"quick_wins": {
"count": 67,
"difficulty_max": 20, // Level 1 only
"min_volume": 1000, // Dynamic: 1K → 500 → 200 fallback
"used_fallback": false
}
}
},
// ... more sectors
]
}
Styling
Use subtle accents matching IGNY8 design style:
- Light/dark mode compatible
- Muted colors from dashboard/billing/usage pages
- No bright/colorful backgrounds
- Subtle borders and shadows
- Consistent with existing card components
Part 5: Smart Suggestions Section
Concept
Show Smart Suggestions dynamically based on current filters/search. Display a breathing circle indicator until user interacts with filters or search.
Initial State (Before Search/Filter)
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 💡 Smart Suggestions │
│ │
│ ○ Ready-to-use keywords waiting for you! Search for a keyword or apply │
│ any filter to see smart suggestions... │
│ ↑ │
│ Breathing/pulsing circle indicator (subtle animation) │
└─────────────────────────────────────────────────────────────────────────────────┘
After Search/Filter Applied
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 💡 Smart Suggestions for "seo tools" │
│ │
│ ┌────────────────────────────────────┐ ┌───────────────────────────────────┐ │
│ │ 📈 High Volume Keywords │ │ 🎯 Easy Wins │ │
│ │ │ │ │ │
│ │ 89 keywords with >4,200 volume │ │ 156 keywords (difficulty ≤ 40) │ │
│ │ Combined: 2.4M searches/month │ │ Combined: 890K searches/month │ │
│ │ │ │ │ │
│ │ Top 5: seo tools, seo audit, ... │ │ Top 5: local seo, seo tips, ... │ │
│ │ │ │ │ │
│ │ [+50] [+100] [+All 89] │ │ [+50] [+100] [+All 156] │ │
│ └────────────────────────────────────┘ └───────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────┐ ┌───────────────────────────────────┐ │
│ │ 🔥 Best Opportunities │ │ 🌱 Long Tail Keywords │ │
│ │ │ │ │ │
│ │ 45 kw (high volume + easy) │ │ 234 keywords (3+ words) │ │
│ │ Combined: 1.2M searches/month │ │ Lower competition phrases │ │
│ │ │ │ │ │
│ │ [+45] │ │ [+50] [+100] [+200] │ │
│ └────────────────────────────────────┘ └───────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ 🔍 All matching "seo tools" - 234 keywords │ │
│ │ │ │
│ │ [+50 by Volume] [+50 by Difficulty] [+100] [+200] [+All 234] │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
Breathing Circle Indicator
CSS animation for pulsing circle:
.breathing-indicator {
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--muted-foreground);
animation: breathe 2s ease-in-out infinite;
}
@keyframes breathe {
0%, 100% { opacity: 0.3; transform: scale(0.9); }
50% { opacity: 0.8; transform: scale(1.1); }
}
Suggestion Categories
| Category | Criteria | Fallback Logic |
|---|---|---|
| 📈 High Volume | Top 50/100 by volume | Dynamic threshold |
| 🎯 Easy Wins | Difficulty ≤ 40 | Fixed threshold |
| 🔥 Best Opportunities | High vol + Easy | Combines criteria |
| 💎 Premium | Volume > 50K | 50K → 25K → 10K fallback |
| 🌱 Long Tail | Words ≥ 4 + Vol > 1K | Vol: 1K → 500 → 200 fallback |
| ⚡ Quick Wins | Diff ≤ 20 + Vol > 1K + Available | Vol: 1K → 500 → 200 fallback |
Bulk Add Buttons
| Button | Action |
|---|---|
[+50] |
Add top 50 sorted by relevant criteria |
[+100] |
Add top 100 |
[+200] |
Add top 200 |
[+All N] |
Add all N matching (shown when N ≤ 200) |
[+50 by Volume] |
Add top 50 sorted by volume DESC |
[+50 by Difficulty] |
Add top 50 sorted by difficulty ASC |
Always show confirmation modal before any bulk add.
Styling
Match IGNY8 dashboard/billing/usage styling:
- Subtle card backgrounds (muted)
- Light borders
- Dark mode compatible colors
- No bright/colorful accents
- Consistent typography
Part 6: Page Layout Redesign
Current Layout
┌─────────────────────────────────────────────────────────────────────────────────┐
│ [Header with Site+Sector selector] │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Quick-Start Keywords Section (always shown first) │
│ │
│ [Browse All Keywords] button │
│ │
│ Table (only shown after clicking Browse) │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
New Layout
┌─────────────────────────────────────────────────────────────────────────────────┐
│ [Header with Site-only selector] │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐│
│ │ Sector Metric Cards (clickable - filters table by sector) ││
│ │ - 5-6 bulk add stat options per card ││
│ │ - [+50] [+100] [+200] buttons ││
│ └─────────────────────────────────────────────────────────────────────────────┘│
│ │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ [🔍 Search] [Sector ▼] [Volume ▼] [Difficulty ▼] [Country ▼] │ │
│ │ │ │
│ │ Active: 2 filters [Clear] │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ ℹ️ Search 54,180 keywords. Filter by volume or difficulty │
│ to find your perfect keywords! │
│ │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐│
│ │ 💡 Smart Suggestions ││
│ │ ││
│ │ ○ Search or filter keywords to see personalized suggestions... ││
│ │ ↑ breathing indicator ││
│ │ ││
│ │ (After search/filter: shows suggestion cards with [+50] [+100] buttons) ││
│ └─────────────────────────────────────────────────────────────────────────────┘│
│ │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Keywords Table (always shown, data loaded by default) │
│ - Shows first 500 records (with server-side sorting/filtering) │
│ - Pagination shows total count │
│ - Sorted by volume DESC by default │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Key Layout Changes
- Site-only selector in header (no sector dropdown)
- Sector cards at top - clickable to filter table
- Centered filter bar with sector filter + active/clear like Planner
- Smart Suggestions - breathing indicator until search/filter
- Table always visible - no "Browse" toggle
- Confirmation modal for all bulk adds
Part 7: Implementation Tasks
Phase 1: Backend API Updates
| Task | File | Priority |
|---|---|---|
Add /filter_options/ endpoint |
auth/views.py |
High |
Add /sector_stats/ endpoint with 6 stat types |
auth/views.py |
High |
Change URL to /keywords-library/ (no alias) |
auth/urls.py |
High |
| Update admin menu to "Keywords Library" | admin/ |
High |
| Support volume_min/max filters | auth/views.py |
High |
| Support sector filter | auth/views.py |
High |
| Implement cascading filter logic | auth/views.py |
High |
| Add bulk add endpoint with confirmation | auth/views.py |
High |
Phase 2: Frontend Filter System
| Task | File | Priority |
|---|---|---|
Rename fetchSeedKeywords → fetchKeywordsLibrary |
services/api.ts |
High |
Add fetchKeywordsLibraryFilterOptions() |
services/api.ts |
High |
Add fetchKeywordsLibrarySectorStats() |
services/api.ts |
High |
| Add Sector filter dropdown | KeywordsLibrary.tsx |
High |
| Add Volume filter component | KeywordsLibrary.tsx |
High |
| Position Active/Clear same as Planner | KeywordsLibrary.tsx |
High |
| Implement cascading filter loading | KeywordsLibrary.tsx |
High |
| Center filter bar + add explainer | KeywordsLibrary.tsx |
Medium |
Phase 3: Selector & Layout Changes
| Task | File | Priority |
|---|---|---|
Move route to SINGLE_SITE_ROUTES |
AppHeader.tsx |
High |
Change route to /keywords-library |
App.tsx |
High |
| Remove "Browse" toggle, show table by default | KeywordsLibrary.tsx |
High |
| Remove High Opportunity section | KeywordsLibrary.tsx |
Medium |
Phase 4: Sector Metric Cards
| Task | File | Priority |
|---|---|---|
| Create SectorMetricCard component | components/keywords-library/ |
High |
| Implement 6 stat types per card | SectorMetricCard.tsx |
High |
| Add click-to-filter behavior | KeywordsLibrary.tsx |
High |
| Add [+50] [+100] [+200] buttons | SectorMetricCard.tsx |
High |
| Add confirmation modal for bulk add | KeywordsLibrary.tsx |
High |
Phase 5: Smart Suggestions
| Task | File | Priority |
|---|---|---|
| Create SmartSuggestions component | components/keywords-library/ |
High |
| Add breathing circle indicator | SmartSuggestions.tsx |
High |
| Show suggestions after search/filter | KeywordsLibrary.tsx |
High |
| Add bulk add buttons [+50] [+100] [+200] | SmartSuggestions.tsx |
High |
| Implement 6 suggestion categories | SmartSuggestions.tsx |
Medium |
Phase 6: Naming Standardization
| Task | File | Priority |
|---|---|---|
| Update sidebar label → "Keywords Library" | AppSidebar.tsx |
High |
| Update SearchModal references | SearchModal.tsx |
Medium |
| Rename Step4AddKeywords → Step4KeywordsLibrary | onboarding/steps/ |
Medium |
| Update marketing pages | Pricing.tsx, Solutions.tsx |
Low |
Phase 7: Confirmation Modal
| Task | File | Priority |
|---|---|---|
| Create BulkAddConfirmation modal | components/keywords-library/ |
High |
| Show count and criteria being added | BulkAddConfirmation.tsx |
High |
| Always require confirmation for bulk add | KeywordsLibrary.tsx |
High |
Part 8: No Backward Compatibility
Single Source of Truth
No legacy URLs, no aliases, no fallbacks.
| Item | Action |
|---|---|
/setup/add-keywords URL |
REMOVE - change to /keywords-library |
/v1/auth/seed-keywords/ API |
REMOVE - change to /v1/keywords-library/ |
fetchSeedKeywords() function |
RENAME to fetchKeywordsLibrary() |
| Backend admin "Industry Sector Keywords" | RENAME to "Keywords Library" |
| All references to old terms | UPDATE to new terms |
Route Change (App.tsx)
// BEFORE
<Route path="/setup/add-keywords" element={<IndustriesSectorsKeywords />} />
// AFTER (no redirect, direct change)
<Route path="/keywords-library" element={<KeywordsLibrary />} />
API Change (auth/urls.py)
# BEFORE
path('seed-keywords/', SeedKeywordViewSet.as_view({'get': 'list'}), name='seed-keyword-list'),
# AFTER (no alias)
urlpatterns = [
path('keywords-library/', include([
path('', SeedKeywordViewSet.as_view({'get': 'list'}), name='keywords-library-list'),
path('filter_options/', SeedKeywordViewSet.as_view({'get': 'filter_options'}), name='keywords-library-filter-options'),
path('sector_stats/', SeedKeywordViewSet.as_view({'get': 'sector_stats'}), name='keywords-library-sector-stats'),
path('bulk_add/', SeedKeywordViewSet.as_view({'post': 'bulk_add'}), name='keywords-library-bulk-add'),
])),
]
File Renames
| From | To |
|---|---|
IndustriesSectorsKeywords.tsx |
KeywordsLibrary.tsx |
Step4AddKeywords.tsx |
Step4KeywordsLibrary.tsx |
Part 9: Success Metrics
| Metric | Current | Target |
|---|---|---|
| Filter usage rate | Low (no volume/sector filter) | High (all filters used) |
| Keywords added per session | ~50 (quick-start only) | 100+ (smart bulk adds) |
| Bulk add usage | N/A | Track [+50], [+100], [+200] clicks |
| Sector card clicks | N/A | Track filtering by sector |
| Smart suggestions engagement | N/A | Track after search/filter |
| Time to first keyword add | Unknown | < 30 seconds |
Part 10: Design Decisions Summary
| Decision | Choice | Rationale |
|---|---|---|
| URL | /keywords-library |
Clean, no legacy compat |
| Naming | "Keywords Library" (plural) | Consistent across all surfaces |
| Backward Compat | None | Single source of truth |
| Sector cards click | Filters table | Intuitive UX |
| High Volume threshold | Dynamic (top 50/100 lowest) | Adapts to actual data |
| Low Difficulty | ≤ 40 (levels 1-2 mapped) | "Easy" keywords |
| Bulk add options | 50, 100, 200, All | Flexible choices |
| Confirmation modal | Always | Prevent accidental adds |
| Smart suggestions | Breathing indicator until search | Encourages interaction |
| Filter styling | Match Planner pages | Consistency |
Files Summary
Files to Modify
| File | Changes |
|---|---|
frontend/src/pages/Setup/IndustriesSectorsKeywords.tsx |
Major rewrite → rename to KeywordsLibrary.tsx |
frontend/src/services/api.ts |
Rename + add new API functions |
frontend/src/layout/AppHeader.tsx |
Move route category |
frontend/src/layout/AppSidebar.tsx |
Update label to "Keywords Library" |
frontend/src/App.tsx |
Change route (no redirect) |
frontend/src/components/common/SearchModal.tsx |
Update references |
backend/igny8_core/auth/views.py |
Add new endpoints, update existing |
backend/igny8_core/auth/urls.py |
Change URL (no alias) |
backend/igny8_core/admin/ |
Update menu label |
Files to Create
| File | Purpose |
|---|---|
frontend/src/components/keywords-library/SectorMetricCard.tsx |
Sector stats card with 6 stat options |
frontend/src/components/keywords-library/SmartSuggestions.tsx |
Smart suggestions with breathing indicator |
frontend/src/components/keywords-library/BulkAddConfirmation.tsx |
Confirmation modal for bulk adds |
Files to Rename
| From | To |
|---|---|
IndustriesSectorsKeywords.tsx |
KeywordsLibrary.tsx |
Step4AddKeywords.tsx |
Step4KeywordsLibrary.tsx |
Approval Checklist
- Review by Product Owner - APPROVED
- Design decisions finalized
- Backend API design approved
- Frontend component design approved
- No backward compatibility confirmed
- Implementation started
Appendix A: Complete List of Files to Refactor
Frontend Source Files (Must Change)
| File | Changes Required |
|---|---|
frontend/src/App.tsx |
Change route /setup/add-keywords → /keywords-library, remove IndustriesSectorsKeywords import |
frontend/src/layout/AppHeader.tsx |
Remove /setup/add-keywords from SITE_AND_SECTOR_ROUTES, add /keywords-library to SINGLE_SITE_ROUTES |
frontend/src/layout/AppSidebar.tsx |
Change label "Keyword Library" → "Keywords Library", path /setup/add-keywords → /keywords-library |
frontend/src/services/api.ts |
Rename fetchSeedKeywords() → fetchKeywordsLibrary(), rename SeedKeyword interface (user-facing), update API URL |
frontend/src/components/common/SearchModal.tsx |
Change all /setup/add-keywords → /keywords-library, "Keyword Library" → "Keywords Library" |
frontend/src/components/sites/SiteSetupChecklist.tsx |
Change href /setup/add-keywords → /keywords-library |
frontend/src/components/dashboard/QuickActionsWidget.tsx |
Change "Keyword Library" → "Keywords Library" |
frontend/src/components/onboarding/steps/Step4AddKeywords.tsx |
RENAME FILE → Step4KeywordsLibrary.tsx, update imports |
frontend/src/components/onboarding/WorkflowGuide.tsx |
Update comment reference to IndustriesSectorsKeywords |
frontend/src/pages/Setup/IndustriesSectorsKeywords.tsx |
RENAME FILE → KeywordsLibrary.tsx, MAJOR REWRITE |
frontend/src/pages/Reference/SeedKeywords.tsx |
Update if needed for consistency |
Backend Files (Must Change)
| File | Changes Required |
|---|---|
backend/igny8_core/auth/urls.py |
Change route seed-keywords/ → keywords-library/ |
backend/igny8_core/auth/views.py |
Keep SeedKeywordViewSet class name (internal), add new endpoints |
backend/igny8_core/auth/serializers.py |
Keep SeedKeywordSerializer name (internal) |
backend/igny8_core/auth/admin.py |
Update admin label to "Keywords Library" |
backend/igny8_core/settings.py |
Change sidebar menu "Seed Keywords" → "Keywords Library" |
backend/igny8_core/urls.py |
Update seedkeyword_csv_template and seedkeyword_csv_import URL paths |
Backend Files (Keep Internal - SeedKeyword Model)
| File | Status |
|---|---|
backend/igny8_core/auth/models.py |
KEEP SeedKeyword class name (internal) |
backend/igny8_core/business/planning/models.py |
KEEP seed_keyword field reference (internal) |
backend/scripts/import_seed_keywords_single.py |
KEEP internal script name |
backend/scripts/import_all_seed_keywords.py |
KEEP internal script name |
Documentation Files (Must Update)
| File | Changes Required |
|---|---|
docs/INDEX.md |
Update route /setup/add-keywords → /keywords-library |
docs/20-API/ENDPOINTS.md |
Update endpoint /seed-keywords/ → /keywords-library/ |
docs/90-REFERENCE/SEED-KEYWORDS-IMPORT-GUIDE.md |
Update user-facing terminology, keep internal references |
docs/90-REFERENCE/MODELS.md |
Keep SeedKeyword model reference (internal) |
docs/plans/NAVIGATION_REFACOTR/NAVIGATION_FINAL_COMPLETION_SUMMARY.md |
Update "Keyword Library" → "Keywords Library" |
docs/plans/NAVIGATION_REFACOTR/NAVIGATION_REFACTOR_PLAN.md |
Update "Keyword Library" → "Keywords Library" |
Other Files (May Need Review)
| File | Notes |
|---|---|
CHANGELOG.md |
Historical references - may keep as-is |
.rules |
Keep SeedKeyword (internal model reference) |
frontend/dist/ |
REBUILD after changes |
frontend/audit-results/ |
Re-run audits after changes |
Status: READY FOR IMPLEMENTATION
Next Steps: Begin Phase 1 - Backend API Updates