# Website Onboarding & Dashboard Completion Plan

**Created**: 2026-08-18  
**Status**: ✅ READY FOR IMPLEMENTATION  
**Scope**: Website flow unification + Dashboard completion  

---

## 🔍 CURRENT STATE ANALYSIS

### Problem 1: Multiple Website Addition Entry Points
Users can currently add websites from **6+ different places**:
```
1. GET /website → Full website management page
2. POST /api/v1/websites → Direct API call
3. POST /api/v1/websites/validate → Validation API
4. POST /api/v1/websites/onboard → Alternative onboard endpoint
5. GET /settings/connections → Link to add websites
6. Potentially in other dashboard modules
```

**Impact**: 
- Inconsistent user experience
- Hard to maintain multiple add flows
- Confusing for new users
- No single source of truth for onboarding

### Problem 2: No Forced Onboarding
- New users can land on any dashboard page
- No check for "user has no websites"
- Dashboard shows empty state gracefully
- **Should require website before accessing features**

### Problem 3: Dashboard Incomplete
- Current `/dashboard` view has skeleton only
- KPIs, pipeline health, activity all empty
- Needs API integration (GET /api/v1/dashboard)
- Design reference exists but not implemented

---

## 🎯 PROPOSED SOLUTION

### Architecture: Unified Website Onboarding Flow

```
User Login
    ↓
AuthFilter (passes)
    ↓
DashboardModule
    ↓
[NEW] Check: User has ≥1 website?
    ├─ NO  → Redirect to GET /onboard (forced)
    └─ YES → Allow access to requested page
         ↓
      [NEW] Check: Valid selected website?
         ├─ NO  → Redirect to website selector
         └─ YES → Render requested dashboard module
```

### Single Website Addition Entry Point: `/onboard`

**Route**: `GET /onboard` + `POST /api/v1/websites/complete-onboarding`

**Flow**:
```
GET /onboard
    ↓
Show OnboardingController view with:
  - Domain input
  - Max pages slider
  - Verification method selector
  - "Add Website" button
    ↓
POST /api/v1/websites/complete-onboarding
    ↓
Creates website, returns success
    ↓
Redirects to GET /dashboard (now accessible)
```

**Access Control**:
- `GET /onboard` → Anyone (no website required)
- Other dashboard routes → Require ≥1 website OR redirect to onboard

---

## 📋 IMPLEMENTATION PLAN

### Phase 1: Middleware & Access Control (Week 1)

#### 1.1 Create WebsiteRequiredFilter
**File**: `app/Filters/WebsiteRequiredFilter.php`

```php
class WebsiteRequiredFilter implements FilterInterface {
    public function before(RequestInterface $request, $arguments = null) {
        $userId = session()->get('user_id');
        if (!$userId) return null; // Let auth filter handle
        
        $websites = (new WebsiteModel())
            ->where('user_id', $userId)
            ->countAllResults();
        
        if ($websites === 0) {
            return redirect()->to('/onboard');
        }
    }
}
```

**Apply to routes**: All dashboard routes except `/onboard`

#### 1.2 Create WebsiteSelectionFilter
**File**: `app/Filters/WebsiteSelectionFilter.php`

Validates that selected website (via header/session) belongs to current user.

#### 1.3 Update DashboardModule
Add middleware check in `initController()`:
```php
$websites = (new WebsiteModel())
    ->where('user_id', $this->userId)
    ->countAllResults();

if ($websites === 0) {
    redirect('/onboard')->send();
    exit;
}
```

---

### Phase 2: Unified Onboarding Page (Week 1-2)

#### 2.1 Create OnboardingController
**File**: `app/Controllers/OnboardingController.php`

```php
class OnboardingController extends DashboardModule {
    public function index(): string {
        // No website required check for this route
        return $this->render('onboarding/index', [
            'page_title' => 'Add Your First Website',
            'page_kicker' => 'Get started',
        ]);
    }
}
```

#### 2.2 Create Onboarding View
**File**: `app/Views/onboarding/index.php`

**Contents**:
- Header: "Add Your First Website"
- Single form with:
  - Domain input (required)
  - Max pages slider (100-10,000, default 500)
  - Verification method (DNS TXT | HTML File | GSC)
  - Add Website button
- Progress indicator (Step 1 of 3)

**Design**: Use existing dash-* components from dashboard

#### 2.3 Create Complete-Onboarding Endpoint
**File**: `app/Controllers/Api/V1/OnboardingController.php`

```php
public function complete(): ResponseInterface {
    $body = $this->request->getJSON(true) ?? [];
    
    // Validate domain, max_pages
    // Create website via WebsiteModel
    // Return success + redirect URL
    
    return $this->ok([
        'website' => [...],
        'next_url' => '/dashboard'
    ]);
}
```

**Route**: `POST /api/v1/onboarding/complete-website`

---

### Phase 3: Consolidate Website Management (Week 2)

#### 3.1 Disable Dispersed Add Points
- Remove "Add Website" from `/settings/connections`
- Remove `POST /api/v1/websites` from public routes
- Redirect old flows to `/onboard`

#### 3.2 Keep Website List & Management
**Route**: `GET /website` still available
- But only for users with ≥1 website
- Shows list of all websites
- Allows edit/delete of existing websites
- Has "+ Add Website" button → `/onboard`

#### 3.3 Create Website Selector Component
**New**: Website dropdown in dashboard header
- Shows user's websites
- Allows quick switch
- Stores selected website in session/localStorage

---

### Phase 4: Complete Dashboard Page (Week 2-3)

#### 4.1 API Endpoint: GET /api/v1/dashboard

**Returns**:
```json
{
  "website": { "id": 123, "domain": "example.com" },
  "kpis": {
    "organic_clicks": 48120,
    "organic_clicks_delta": 12.4,
    "impressions": 1240000,
    "impressions_delta": 8.1,
    "conversions": 1043,
    "conversions_delta": 5.6,
    "attributed_revenue": 312400,
    "attributed_revenue_delta": 9.3
  },
  "pipeline": {
    "open_opportunities": 37,
    "pending_approvals": 6,
    "crawl_coverage": 92,
    "connector_health": "3 of 4",
    "next_job": { "type": "full_crawl", "time": "2026-08-18T23:00:00Z" }
  },
  "recent_activity": [
    {
      "type": "deployment",
      "title": "Deployment published",
      "description": "Emergency plumbing — Austin · v14",
      "tone": "success",
      "timestamp": "12m ago"
    },
    // ... more items
  ]
}
```

**Data Sources**:
- KPIs: Google Search Console API (cached)
- Pipeline: wc_opportunities, wc_approvals, crawl status, integrations
- Activity: wc_audit_logs or event table

#### 4.2 Update Dashboard View
**File**: `app/Views/dashboard/index.php` 

Currently has skeleton, needs to populate via JS:
- Fill KPI tiles with values
- Render trend chart (bars showing 14-day clicks/impressions)
- Populate pipeline health grid
- Render recent activity list

#### 4.3 Create Dashboard JS
**File**: `public/assets/js/dashboard.js`

```js
function boot() {
    wcFetch('dashboard')
        .then(r => r.json())
        .then(data => {
            hydratKpis(data.kpis);
            hydratePipeline(data.pipeline);
            hydrateActivity(data.recent_activity);
            renderTrendChart(data.kpis.clicks_trend);
        });
}
```

---

### Phase 5: Website Selector & Session (Week 3)

#### 5.1 Website Selector Component
**Location**: Dashboard header/navbar

Shows:
```
[Company Logo]  [Website Dropdown ▼]  [User Menu]
                └─ example.com (✓ selected)
                └─ client.com
                └─ project.io
                └─ [+ Add Website]
```

#### 5.2 Session Management
Store selected website:
- In `session('selected_website_id')`
- Sync with localStorage for persistence
- Validate ownership in API calls

#### 5.3 API Headers
Add to all API calls:
```
X-Website-Id: 123
```

DashboardModule validates this header matches user's website.

---

## 🏗️ IMPLEMENTATION CHECKLIST

### Phase 1: Access Control
- [ ] Create WebsiteRequiredFilter
- [ ] Update DashboardModule with website check
- [ ] Apply filter to routes
- [ ] Test: New user redirects to /onboard
- [ ] Test: User with website can access dashboard

### Phase 2: Unified Onboarding
- [ ] Create OnboardingController
- [ ] Create onboarding/index.php view
- [ ] Create OnboardingController API
- [ ] POST endpoint: /api/v1/onboarding/complete-website
- [ ] Test: Complete onboarding flow
- [ ] Test: Redirect to dashboard after adding website

### Phase 3: Consolidation
- [ ] Remove "Add Website" from other pages
- [ ] Redirect old flows to /onboard
- [ ] Keep website management at /website
- [ ] Test: No broken entry points

### Phase 4: Dashboard Completion
- [ ] Create GET /api/v1/dashboard endpoint
- [ ] Implement KPI data fetch (GSC)
- [ ] Implement pipeline data fetch
- [ ] Implement activity data fetch
- [ ] Update dashboard/index.php view
- [ ] Create dashboard.js
- [ ] Test: All KPIs populate
- [ ] Test: Charts render correctly

### Phase 5: Website Selector
- [ ] Create website selector component
- [ ] Integrate into layout/top
- [ ] Add localStorage persistence
- [ ] Add X-Website-Id header to API calls
- [ ] Test: Switching websites works
- [ ] Test: Session persists across pages

---

## 🎨 UI/UX FLOW DIAGRAM

```
┌─────────────────────────────────────────────────────┐
│                   NEW USER LOGIN                    │
└────────────────────┬────────────────────────────────┘
                     ↓
        ┌────────────────────────────┐
        │  Check: Has websites?      │
        └────────────┬───────────────┘
             NO / YES
             ↙       ↘
   ┌──────────┐    ┌────────────────────────────────┐
   │ /onboard │    │   Select website from list     │
   │  (NEW)   │    │  ┌──────────────────────────┐  │
   │          │    │  │ My Websites Dropdown:    │  │
   │- Domain  │    │  │  • example.com (active)  │  │
   │- Pages   │    │  │  • client.com            │  │
   │- Verify  │    │  │  • + Add New Website     │  │
   │          │    │  └──────────────────────────┘  │
   └──────────┘    │                                │
        ↓          │  Select to continue...         │
        ↓          └────────────────────────────────┘
        └─────────────────┬──────────────────────────┘
                         ↓
          ┌──────────────────────────────┐
          │    /dashboard (HOME)         │
          │  ┌──────────────────────────┐│
          │  │ KPIs (4 tiles)           ││
          │  │ • Organic clicks         ││
          │  │ • Impressions            ││
          │  │ • Conversions            ││
          │  │ • Attributed Revenue     ││
          │  └──────────────────────────┘│
          │  ┌──────────────────────────┐│
          │  │ Trend Chart (28 days)    ││
          │  │ [████████░░░░░░░░░░░░░░] ││
          │  └──────────────────────────┘│
          │  ┌──────────────────────────┐│
          │  │ Pipeline Health          ││
          │  │ • Open Opportunities: 37 ││
          │  │ • Pending Approvals: 6   ││
          │  │ • Crawl Coverage: 92%    ││
          │  └──────────────────────────┘│
          │  ┌──────────────────────────┐│
          │  │ Recent Activity          ││
          │  │ • Deployment published   ││
          │  │ • Approval requested     ││
          │  └──────────────────────────┘│
          └──────────────────────────────┘
                     ↓
          ┌──────────────────────────────┐
          │ Other Dashboard Modules:     │
          │ • Crawl History              │
          │ • Opportunities              │
          │ • Reviews                    │
          │ • Deployments                │
          │ • Site Overview              │
          └──────────────────────────────┘
```

---

## 📊 DATA MODEL

### Website Selection Flow
```
Session Storage:
├─ user_id (from auth)
├─ selected_website_id (NEW)
└─ selected_website_name (NEW)

API Header:
├─ Authorization: Bearer {token}
└─ X-Website-Id: 123 (NEW)

Database Query:
SELECT * FROM wc_websites 
WHERE user_id = {user_id} 
AND id = {selected_website_id}
LIMIT 1
```

### Onboarding Data
```
POST /api/v1/onboarding/complete-website
{
  "domain": "example.com",
  "protocol": "https",
  "max_crawl_pages": 500,
  "verification_method": "dns_txt|html_file|search_console",
  "sitemap_url": "https://example.com/sitemap.xml"
}

Response:
{
  "success": true,
  "website": {
    "id": 123,
    "domain": "example.com",
    "status": "unverified"
  },
  "next_url": "/dashboard"
}
```

---

## 🔐 Security Considerations

1. **User Ownership Validation**
   - Every API call checks: `user_id` matches token
   - Website header `X-Website-Id` validated in middleware
   - Never trust client-side website selection

2. **Onboarding Protection**
   - Rate limit domain additions (max 5/hour per user)
   - Validate domain format strictly
   - Store IP of onboarding request for audit

3. **Session Management**
   - Website selection doesn't grant permissions
   - Permissions still checked per API call
   - Session timeout invalidates selection

---

## ⏱️ EFFORT ESTIMATES

| Phase | Tasks | Effort | Duration |
|-------|-------|--------|----------|
| 1 | Access Control | 3 days | 2-3 days |
| 2 | Onboarding UI/API | 4 days | 3-4 days |
| 3 | Consolidation | 2 days | 1-2 days |
| 4 | Dashboard Data | 5 days | 4-5 days |
| 5 | Website Selector | 3 days | 2-3 days |
| **Total** | **17 tasks** | **17 days** | **12-17 days** |

---

## 🧪 TESTING STRATEGY

### Unit Tests
- [ ] WebsiteRequiredFilter redirects correctly
- [ ] OnboardingController validates inputs
- [ ] API endpoint creates website
- [ ] Dashboard API returns correct data structure

### Integration Tests
- [ ] New user flow: signup → onboard → dashboard
- [ ] Multiple website selection and switching
- [ ] Website ownership validation
- [ ] Permission checks across modules

### E2E Tests
- [ ] Complete onboarding flow
- [ ] Dashboard data loads
- [ ] Website switching maintains session
- [ ] Logout/login preserves website selection

---

## 📝 ROLLOUT PLAN

### Week 1: Internal Testing
- Deploy to staging
- Test with team members
- Gather feedback

### Week 2: Beta Rollout
- Enable feature flag for beta users
- Monitor analytics
- Collect user feedback

### Week 3: Full Rollout
- Remove feature flag
- Sunset old entry points
- Update documentation

---

## 🎯 SUCCESS METRICS

- **Onboarding completion rate**: >90%
- **Dashboard load time**: <500ms
- **No broken entry points**: 0
- **User satisfaction**: >4/5 (survey)
- **Support tickets**: <2/week related to website flow

---

## 📚 DEPENDENCIES

- Google Search Console API connection (for KPIs)
- Database migrations (if new tables needed)
- Frontend framework (already Vue.js based)
- Session/Storage mechanism (already in place)

---

## ❓ OPEN QUESTIONS

1. Should old `/api/v1/websites POST` endpoint be deprecated or completely removed?
2. Should users be able to have 0 websites temporarily (e.g., during deletion)?
3. Should website selector appear in onboarding or only after first website added?
4. Should "recently used" website be auto-selected on login?

---

**Document Status**: READY FOR REVIEW & APPROVAL  
**Next Step**: Approve plan + assign implementation tasks
