# Onboarding Redirect-to-Source Feature

**Status**: ✅ IMPLEMENTED  
**Date**: 2026-08-18  
**Purpose**: When users click "Create Project" from different pages, they return to that page after completing onboarding

---

## 📍 How It Works

### Default Behavior
```
User on dashboard → Click "Create Project" → Completes onboarding → Back to dashboard
```

### With Redirect Parameter
```
User on /crawl → Click "Create Project" → /onboarding?redirect=crawl → Creates website → Back to /crawl
User on /reports → Click "Create Project" → /onboarding?redirect=reports → Creates website → Back to /reports
```

---

## 🔧 Technical Implementation

### 1. OnboardingController (Backend)
```php
// Extract redirect parameter from URL
$redirect = $this->request->getGet('redirect') ?? 'dashboard';

// Validate against whitelist of safe pages
$validRedirects = ['dashboard', 'crawl', 'website', 'reports', 'audit', 'keywords', 'rank-tracking'];
if (!in_array($redirect, $validRedirects, true)) {
    $redirect = 'dashboard';
}

// Pass to view
$data['redirect'] = $redirect;
```

**Why whitelist?** Prevents open redirects and malicious URLs

**Valid redirects**:
- `dashboard` - Main dashboard
- `crawl` - Crawl history page
- `website` - Website management
- `reports` - Reports page
- `audit` - Audit results
- `keywords` - Keyword tracking
- `rank-tracking` - Rank tracking page

---

### 2. Onboarding View (Frontend)
```php
<!-- Header skip link -->
<a href="<?= site_url($redirect) ?>" class="onboarding-skip">Skip for now →</a>

<!-- Footer button -->
<a href="<?= site_url($redirect) ?>" class="onboarding-btn onboarding-btn--primary">
  Go to <?= $redirect === 'dashboard' ? 'dashboard' : ucfirst($redirect) ?>
</a>

<!-- JavaScript storage -->
<script>
  const onboardingRedirect = '<?= site_url($redirect) ?>';
</script>
```

---

### 3. Website Creation Modal (Modal Component)
```js
// When opening modal from onboarding, set global redirect target
window.wcProjectModalRedirect = onboardingRedirect;
WCCreateProjectModal.open();

// After successful website creation
setTimeout(() => {
  if (window.wcProjectModalRedirect) {
    window.location.href = window.wcProjectModalRedirect;  // Redirect to source
  } else {
    window.location.reload();  // Default: reload current page
  }
}, 1500);
```

**Flow**:
1. User on `/onboarding?redirect=crawl` clicks "Continue" on Website step
2. Modal opens, receives redirect URL via `window.wcProjectModalRedirect`
3. User fills form and submits
4. Website created successfully
5. Modal redirects to `/crawl` (not back to onboarding, not dashboard)

---

## 🎯 Usage: How to Link to Onboarding with Redirect

### From Dashboard (no redirect needed)
```php
<a href="<?= site_url('onboarding') ?>" class="btn btn-primary">
  Create Project
</a>
<!-- Defaults to redirect=dashboard -->
```

### From Crawl Page
```php
<a href="<?= site_url('onboarding?redirect=crawl') ?>" class="btn btn-primary">
  Create Project
</a>
```

### From Reports Page
```php
<a href="<?= site_url('onboarding?redirect=reports') ?>" class="btn btn-primary">
  Create Project
</a>
```

### Generic Button in Any Page
```php
<?php
// Determine current page name from route
$currentPage = $router->routes()[uri_string()] ?? 'dashboard';
$redirectUrl = site_url("onboarding?redirect=" . $currentPage);
?>
<a href="<?= $redirectUrl ?>" class="btn btn-primary">
  Create Project
</a>
```

---

## 🔄 Complete User Flow Example

### Scenario: User on Crawl Page Wants to Add Website

```
1. User navigates to /crawl
2. Crawl page empty, sees button: "Create your first project"
3. Button links to: /onboarding?redirect=crawl
4. /onboarding loads with:
   - $redirect = 'crawl'
   - onboardingRedirect = 'http://site.com/crawl'
   - Skip link → /crawl
   - Go to button → /crawl
5. User clicks "Continue" on Website step
6. Modal opens (wcProjectModalRedirect = '/crawl')
7. User fills domain: example.com, max pages: 500, verification: DNS
8. Clicks "Create Project"
9. API call: POST /api/v1/websites
10. Success → Modal shows success message
11. After 1.5 seconds → Redirects to /crawl (not dashboard)
12. User back on crawl page with their new website ready to crawl
```

---

## 🧪 Testing the Redirect Feature

### Test Case 1: Redirect to Crawl
```
1. Navigate to: /onboarding?redirect=crawl
2. Should see "Go to Crawl" button (not "Go to Dashboard")
3. Click "Skip for now" → Goes to /crawl
4. Create website → After success → Redirects to /crawl
```

### Test Case 2: Redirect to Reports
```
1. Navigate to: /onboarding?redirect=reports
2. Should see "Go to Reports" button
3. Skip or complete → Goes to /reports
```

### Test Case 3: Invalid Redirect (Security)
```
1. Navigate to: /onboarding?redirect=evil.com
2. Should treat as invalid and redirect to dashboard
3. No open redirect vulnerability
```

### Test Case 4: No Redirect (Default)
```
1. Navigate to: /onboarding (no ?redirect param)
2. Should default to dashboard
3. All buttons → dashboard
```

### Test Case 5: Modal Without Redirect
```
1. On dashboard, modal already open
2. Create website via modal (no redirect set)
3. After success → Reloads current page (dashboard)
```

---

## 📋 Files Modified

| File | Changes |
|------|---------|
| `app/Controllers/OnboardingController.php` | Extract and validate redirect param, pass to view |
| `app/Views/onboarding/index.php` | Use redirect in header skip link, footer button, JS variable |
| `app/Views/dashboard/components/create-project-modal.php` | Check for redirect and navigate instead of reload |

---

## 🔒 Security Considerations

✅ **Whitelist Validation**: Only specific known pages can be redirect targets  
✅ **Site URL Encoding**: Uses `site_url()` helper to ensure proper URL construction  
✅ **No User Input**: Redirect comes from URL but validated against whitelist  
✅ **Default Fallback**: Invalid redirects default to safe 'dashboard'  

---

## 🚀 Future Enhancements

- [ ] Add more pages to redirect whitelist as new features are added
- [ ] Dynamic redirect based on user's last visited page
- [ ] Remember redirect choice for future onboarding flows
- [ ] Analytics: Track which pages users start onboarding from
- [ ] Modal variant: Embed website creation form directly in onboarding (no modal)

---

## 📝 Notes

**Why use global variable for redirect?**
- Modal component doesn't have direct access to controller variables
- Simple and reliable way to pass data between onboarding and modal
- Global variable is cleared after use, no state pollution

**Why redirect from modal and not from controller?**
- Modal handles the actual website creation (API call)
- Modal already has success/error handling and timing
- Better UX: user sees success message before redirect

**What if website creation fails?**
- Modal shows error message
- User can try again or close modal
- No redirect happens on error
- User stays on onboarding page to retry

---

*Last updated: 2026-08-18*
