keywrod library sorting issue and fitlers inclusion, adn PLAN for refactor of whole page realted
This commit is contained in:
850
docs/plans/KEYWORDS-LIBRARY-REDESIGN-PLAN.md
Normal file
850
docs/plans/KEYWORDS-LIBRARY-REDESIGN-PLAN.md
Normal file
@@ -0,0 +1,850 @@
|
||||
# Keywords Library Page Redesign Plan
|
||||
|
||||
**Created:** January 18, 2026
|
||||
**Updated:** January 18, 2026
|
||||
**Status:** APPROVED - READY FOR IMPLEMENTATION
|
||||
**Page:** `/setup/add-keywords` → `/keywords-library`
|
||||
**Priority:** 🟡 HIGH - UX Improvement
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Comprehensive redesign of the Keywords Library page to:
|
||||
1. **Standardize naming** to "Keywords Library" across frontend, backend, URLs, menus, and admin
|
||||
2. **Implement cascading filters** like Planner pages (Keywords, Clusters, Ideas)
|
||||
3. **Remove sector selector** from AppHeader, use site-only selector
|
||||
4. **Add Sector Metric Cards** with clickable filtering + 5-6 bulk add stat options
|
||||
5. **Redesign Smart Suggestions** to appear after search/filter with breathing indicator
|
||||
6. **Center filter bar** with sector filter added, matching Planner page styling
|
||||
7. **Show table data by default** (remove "Browse" toggle)
|
||||
8. **No backward compatibility** - single source of truth
|
||||
|
||||
---
|
||||
|
||||
## 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:**
|
||||
1. ❌ No "Clear Filters" button near active filter indicator
|
||||
2. ❌ No Volume filter (exists on Planner Keywords page)
|
||||
3. ❌ No Sector filter in filter bar
|
||||
4. ❌ Hardcoded country/difficulty options (not cascading)
|
||||
5. ❌ Filters don't show only available options based on current data
|
||||
6. ❌ 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:**
|
||||
1. ✅ Active count + Clear button positioned **same as Planner pages**
|
||||
2. ✅ Add Volume range filter (min/max popup like Planner pages)
|
||||
3. ✅ Add Sector filter dropdown
|
||||
4. ✅ Keep "Not Yet Added" status filter (in_workflow filter)
|
||||
5. ✅ Implement cascading filters - options reflect available data
|
||||
6. ✅ 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):
|
||||
|
||||
```python
|
||||
# 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
|
||||
|
||||
1. **Add `fetchKeywordsLibraryFilterOptions()` API function**
|
||||
2. **Add Sector filter dropdown** (populated from site's sectors)
|
||||
3. **Add Volume filter component** (reuse from Keywords.tsx)
|
||||
4. **Position Active/Clear same as Planner pages**
|
||||
5. **Load filter options dynamically** based on industry/sector selection
|
||||
6. **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_ROUTES` array
|
||||
- Add to `SINGLE_SITE_ROUTES` array
|
||||
|
||||
### Code Change (AppHeader.tsx)
|
||||
|
||||
```diff
|
||||
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
|
||||
|
||||
```python
|
||||
# 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/`
|
||||
|
||||
```python
|
||||
# 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:
|
||||
```css
|
||||
.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
|
||||
|
||||
1. **Site-only selector** in header (no sector dropdown)
|
||||
2. **Sector cards at top** - clickable to filter table
|
||||
3. **Centered filter bar** with sector filter + active/clear like Planner
|
||||
4. **Smart Suggestions** - breathing indicator until search/filter
|
||||
5. **Table always visible** - no "Browse" toggle
|
||||
6. **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)
|
||||
|
||||
```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)
|
||||
|
||||
```python
|
||||
# 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
|
||||
|
||||
- [x] Review by Product Owner - **APPROVED**
|
||||
- [x] Design decisions finalized
|
||||
- [x] Backend API design approved
|
||||
- [x] Frontend component design approved
|
||||
- [x] 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
|
||||
Reference in New Issue
Block a user