# Folder Structure & Domain Configuration Guide

**Version:** 2.0.0
**Date:** December 2025
**Purpose:** Separation of concerns - Dashboard vs Redirect handling

---

## Table of Contents

1. [Overview](#overview)
2. [Folder Structure](#folder-structure)
3. [Domain Configuration](#domain-configuration)
4. [URL Routing](#url-routing)
5. [Deployment Steps](#deployment-steps)
6. [Security Considerations](#security-considerations)
7. [Testing](#testing)
8. [Troubleshooting](#troubleshooting)

---

## Overview

### Architecture Philosophy

The application is split into **two separate domains/folders**:

1. **Dashboard** (`/public`) - Admin interface for managing domains and shortlinks
2. **Redirect** (`/redirect`) - Public-facing shortlink redirect handler

### Why Separate Folders?

**Benefits:**

- **Security**: Admin dashboard separated from public redirect handler
- **Performance**: Different caching strategies for each
- **Scalability**: Can deploy redirects on separate servers/CDN
- **Maintenance**: Update dashboard without affecting live redirects
- **Flexibility**: Different domain names for dashboard vs redirects

**Example Setup:**

```
Dashboard:    https://dashboard.yourdomain.com  → /public
Redirects:    https://go.yourdomain.com         → /redirect
              https://short.yourdomain.com      → /redirect
              https://link.yourdomain.com       → /redirect
```

---

## Folder Structure

```
domain-dashboard-final/
│
├── bootstrap/              # Initialization files
│   └── init.php           # Application bootstrap
│
├── config/                # Configuration files
│   └── database.php       # Database config
│
├── database-migrations/   # SQL migration files
│   ├── 001_*.sql
│   ├── 002_*.sql
│   ├── 003_*.sql
│   ├── 004_*.sql
│   └── 005_*.sql
│
├── public/                # DASHBOARD - Admin Interface
│   ├── index.php          # Main dashboard UI
│   ├── .htaccess          # Dashboard routing
│   └── ajax/              # AJAX endpoints
│       ├── submit-domain.php
│       ├── get-domains.php
│       ├── submit-shortlink.php
│       ├── get-shortlinks.php
│       ├── get-system-settings.php
│       ├── update-system-settings.php
│       ├── get-waf-stats.php
│       ├── whitelist-ip.php
│       └── track-shim-analytics.php
│
├── redirect/              # REDIRECTS - Public Shortlinks
│   ├── s.php              # Shortlink redirect handler
│   ├── shim.php           # Shim page (intermediate redirect)
│   ├── .htaccess          # Redirect routing & rewrite rules
│   ├── index.php          # Optional: Redirect to dashboard or 404
│   ├── api.php            # Optional: Public API endpoints
│   ├── robots.txt         # SEO rules for redirect domain
│   └── README.md          # Redirect folder documentation
│
├── src/                   # Application logic
│   ├── Domain/            # Domain entities
│   ├── Integration/       # External API integrations
│   ├── Repository/        # Database access layer
│   └── Service/           # Business logic
│       ├── DomainService.php
│       ├── ShortlinkService.php
│       ├── GlobalRedirectService.php
│       └── MiniWAFService.php
│
├── vendor/                # Composer dependencies
├── .env                   # Environment variables
├── composer.json          # PHP dependencies
└── README.md              # Project documentation
```

---

## Domain Configuration

### Setup 1: Single Domain (Subdirectories)

**Use Case:** Testing, small deployments

```
https://yourdomain.com/              → /public/index.php (Dashboard)
https://yourdomain.com/s/abc123      → /redirect/s.php?slug=abc123
https://yourdomain.com/shim.php      → /redirect/shim.php
```

**Apache Virtual Host:**

```apache
<VirtualHost *:80>
    ServerName yourdomain.com
    DocumentRoot /home/user/domain-dashboard-final/public

    <Directory /home/user/domain-dashboard-final/public>
        AllowOverride All
        Require all granted
    </Directory>

    # Alias for redirect folder
    Alias /s /home/user/domain-dashboard-final/redirect
    Alias /shim.php /home/user/domain-dashboard-final/redirect/shim.php

    <Directory /home/user/domain-dashboard-final/redirect>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
```

### Setup 2: Separate Subdomains (Recommended)

**Use Case:** Production deployments

```
Dashboard:  https://dashboard.yourdomain.com  → /public
Redirects:  https://go.yourdomain.com         → /redirect
```

**Apache Virtual Hosts:**

```apache
# Dashboard
<VirtualHost *:80>
    ServerName dashboard.yourdomain.com
    DocumentRoot /home/user/domain-dashboard-final/public

    <Directory /home/user/domain-dashboard-final/public>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

# Redirects
<VirtualHost *:80>
    ServerName go.yourdomain.com
    ServerAlias link.yourdomain.com
    ServerAlias short.yourdomain.com
    DocumentRoot /home/user/domain-dashboard-final/redirect

    <Directory /home/user/domain-dashboard-final/redirect>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
```

### Setup 3: Multiple Redirect Domains (Anti-Block)

**Use Case:** High-traffic, anti-blocking

```
Dashboard:   https://admin.yourdomain.com       → /public
Redirects:   https://go1.yourdomain.com         → /redirect
             https://go2.yourdomain.com         → /redirect
             https://go3.yourdomain.com         → /redirect
```

**Benefits:**

- Domain rotation prevents blocking
- Load distribution
- Redundancy

**Configuration:**

```sql
-- Add domains to rotation pool
INSERT INTO domain_rotation_pool (domain, status, priority)
VALUES
    ('go1.yourdomain.com', 'active', 10),
    ('go2.yourdomain.com', 'active', 20),
    ('go3.yourdomain.com', 'active', 30);

-- Enable domain rotation in System Settings
UPDATE global_redirect_settings
SET antiblock_enabled = 1;
```

### Setup 4: cPanel Configuration

**For shared hosting with cPanel:**

1. **Create Addon Domain** for redirect:
   - Domain: `go.yourdomain.com`
   - Document Root: `/home/username/domain-dashboard-final/redirect`

2. **Create Subdomain** for dashboard:
   - Subdomain: `dashboard.yourdomain.com`
   - Document Root: `/home/username/domain-dashboard-final/public`

3. **Wildcard Subdomain** (optional):
   - `*.yourdomain.com` → `/home/username/domain-dashboard-final/redirect`
   - Allows: `abc.yourdomain.com`, `xyz.yourdomain.com`, etc.

---

## URL Routing

### Dashboard URLs (`/public`)

```
GET  /                              → Main dashboard UI
POST /ajax/submit-domain.php        → Add new domain
GET  /ajax/get-domains.php          → Fetch domains list
POST /ajax/submit-shortlink.php     → Create shortlink
GET  /ajax/get-shortlinks.php       → Fetch shortlinks
GET  /ajax/get-system-settings.php  → Get system settings
POST /ajax/update-system-settings.php → Save settings
GET  /ajax/get-waf-stats.php        → WAF statistics
POST /ajax/whitelist-ip.php         → Add IP to whitelist
POST /ajax/track-shim-analytics.php → Track shim interaction
```

### Redirect URLs (`/redirect`)

```
GET  /abc123                        → s.php?slug=abc123 (Rewrite)
GET  /s/abc123                      → s.php?slug=abc123 (Rewrite)
GET  /s.php?slug=abc123             → Direct access
GET  /shim.php?slug=abc&dest=...    → Shim page
GET  /api.php?action=stats          → Public API (optional)
```

### URL Rewrite Flow

**Clean URL Processing:**

```
User visits: https://go.yourdomain.com/abc123
             ↓
.htaccess rewrite rule matches: ^([a-zA-Z0-9_-]+)$
             ↓
Internally rewrites to: s.php?slug=abc123
             ↓
s.php handles redirect logic
             ↓
Global redirect check → Shim check → Final redirect
```

**Rewrite Rules Priority:**

```apache
1. Real files/folders (RewriteCond %{REQUEST_FILENAME} !-f)
2. Exclude specific files (shim.php, api.php, index.php)
3. Match slug pattern: [a-zA-Z0-9_-]+
4. Rewrite to s.php?slug=$1
```

---

## Deployment Steps

### Step 1: Directory Permissions

```bash
cd /home/user/domain-dashboard-final

# Set folder permissions
chmod 755 public redirect bootstrap config src
chmod 755 public/ajax

# Set file permissions
chmod 644 public/index.php
chmod 644 redirect/s.php
chmod 644 redirect/shim.php
chmod 644 redirect/.htaccess
chmod 644 public/.htaccess

# Writable cache (if using file cache)
# chmod 775 cache
# chown www-data:www-data cache
```

### Step 2: Update Bootstrap Path

**Verify `redirect/s.php` and `redirect/shim.php` have correct path:**

```php
// In redirect/s.php and redirect/shim.php
require_once __DIR__ . '/../bootstrap/init.php';

// NOT: require_once __DIR__ . '/bootstrap/init.php';
```

### Step 3: Test Redirect Folder

```bash
# Navigate to redirect folder
cd redirect/

# Test bootstrap loading
php -r "require 'bootstrap/init.php'; echo 'Bootstrap OK';"
```

**Expected:** `Bootstrap OK`

### Step 4: Configure Virtual Hosts

**Option A: Separate Subdomains (Recommended)**

```bash
# Create Apache config
sudo nano /etc/apache2/sites-available/dashboard.conf
sudo nano /etc/apache2/sites-available/redirects.conf

# Enable sites
sudo a2ensite dashboard.conf
sudo a2ensite redirects.conf

# Reload Apache
sudo systemctl reload apache2
```

**Option B: Single Domain with Alias**

```bash
# Create single config with Alias directives
sudo nano /etc/apache2/sites-available/domain-dashboard.conf
sudo a2ensite domain-dashboard.conf
sudo systemctl reload apache2
```

### Step 5: Update .env

```bash
# Copy example .env
cp .env.example .env

# Edit configuration
nano .env
```

**.env content:**

```ini
DB_HOST=localhost
DB_NAME=dashboard_db
DB_USER=dashboard_user
DB_PASS=secure_password

CPANEL_HOST=cpanel.yourdomain.com
CPANEL_USERNAME=cpanel_user
CPANEL_API_TOKEN=your_api_token
CPANEL_PORT=2083

CLOUDFLARE_EMAIL=your@email.com
CLOUDFLARE_API_KEY=your_cloudflare_key

# Dashboard URL (for AJAX calls)
DASHBOARD_URL=https://dashboard.yourdomain.com

# Redirect domain (primary)
REDIRECT_DOMAIN=go.yourdomain.com
```

### Step 6: Test URLs

```bash
# Test dashboard
curl -I https://dashboard.yourdomain.com/
# Expected: 200 OK

# Test redirect (should show 404 if no shortlink)
curl -I https://go.yourdomain.com/nonexistent
# Expected: 404 Not Found

# Create test shortlink in dashboard
# Then test:
curl -I https://go.yourdomain.com/test123
# Expected: 302 Found → Location: destination_url
```

### Step 7: Enable HTTPS (Recommended)

```bash
# Install Certbot
sudo apt install certbot python3-certbot-apache

# Get SSL certificates
sudo certbot --apache -d dashboard.yourdomain.com
sudo certbot --apache -d go.yourdomain.com

# Auto-renewal
sudo certbot renew --dry-run
```

---

## Security Considerations

### 1. Folder Isolation

**Dashboard (`/public`):**

- Protected by authentication (if implemented)
- CSRF protection on all POST requests
- Input validation & sanitization
- Rate limiting on sensitive endpoints

**Redirects (`/redirect`):**

- Public access (no authentication)
- Mini WAF protection
- IP blocking for attacks
- Bot detection for crawlers

### 2. File Permissions

```bash
# Correct permissions
drwxr-xr-x (755)  Folders
-rw-r--r-- (644)  PHP files
-rw------- (600)  .env file (sensitive)

# NEVER use 777 permissions!
```

### 3. .htaccess Security

**Dashboard `.htaccess`:**

```apache
# Block direct access to sensitive files
<Files ".env">
    Require all denied
</Files>

<Files "*.sql">
    Require all denied
</Files>
```

**Redirect `.htaccess`:**

```apache
# Protect sensitive files
<FilesMatch "\.(env|log|sql|md|git)$">
    Order allow,deny
    Deny from all
</FilesMatch>
```

### 4. Database Access

**Principle of Least Privilege:**

```sql
-- Create dedicated database user
CREATE USER 'dashboard_user'@'localhost' IDENTIFIED BY 'secure_password';
GRANT SELECT, INSERT, UPDATE, DELETE ON dashboard_db.* TO 'dashboard_user'@'localhost';
FLUSH PRIVILEGES;

-- DO NOT use root account
```

### 5. Environment Variables

**Never commit `.env` to Git:**

```.gitignore
.env
.env.local
.env.production
*.log
vendor/
```

---

## Testing

### Test Checklist

**Dashboard Tests:**

- [ ] Can access dashboard UI
- [ ] Can create domain
- [ ] Can create shortlink
- [ ] AJAX endpoints work
- [ ] CSRF protection working
- [ ] System Settings tab loads
- [ ] Mini WAF stats display

**Redirect Tests:**

- [ ] Clean URL works: `/abc123`
- [ ] With prefix works: `/s/abc123`
- [ ] Direct PHP works: `/s.php?slug=abc123`
- [ ] Shim page shows (if enabled)
- [ ] Global redirect overrides (if enabled)
- [ ] OG meta tags present
- [ ] Facebook crawler detection works

**Security Tests:**

- [ ] SQL injection blocked by WAF
- [ ] XSS attempts blocked
- [ ] Sensitive files not accessible
- [ ] .env file not accessible
- [ ] CSRF tokens validated

### Manual Testing

**1. Create Test Shortlink:**

```
Dashboard → Shortlinks Tab → Create Shortlink
Slug: test123
Destination: https://example.com
OG Title: Test Link
```

**2. Test Redirect:**

```bash
curl -I https://go.yourdomain.com/test123
```

**Expected Response:**

```
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
...
```

**Then auto-redirects to:** `https://example.com`

**3. Test Shim Page:**

Enable shim in System Settings:

```
System Settings → Shim Page → Enable
Delay: 3 seconds
```

Visit shortlink:

```
https://go.yourdomain.com/test123
```

**Expected:** Intermediate page with countdown → Auto-redirect after 3s

**4. Test WAF:**

```bash
# SQLi attempt
curl "https://go.yourdomain.com/test?id=1' OR '1'='1"

# Expected: 403 Forbidden
```

**5. Test Facebook Preview:**

Use [Facebook Sharing Debugger](https://developers.facebook.com/tools/debug/):

```
URL: https://go.yourdomain.com/test123
```

**Expected:** OG meta tags displayed correctly

---

## Troubleshooting

### Issue: Redirect URLs Not Working

**Symptoms:** 404 errors on shortlink URLs

**Solutions:**

1. Check .htaccess exists:

```bash
ls -la redirect/.htaccess
```

2. Verify mod_rewrite enabled:

```bash
sudo a2enmod rewrite
sudo systemctl restart apache2
```

3. Check AllowOverride:

```apache
<Directory /path/to/redirect>
    AllowOverride All  # NOT None
    Require all granted
</Directory>
```

4. Test rewrite manually:

```bash
curl -I https://go.yourdomain.com/s.php?slug=test123
# Should work directly
```

### Issue: Bootstrap Not Found

**Symptoms:** `require_once: failed to open stream`

**Solutions:**

1. Check relative path in s.php:

```php
// Correct for /redirect/s.php
require_once __DIR__ . '/../bootstrap/init.php';
```

2. Verify bootstrap exists:

```bash
ls -la bootstrap/init.php
```

3. Check file permissions:

```bash
chmod 644 bootstrap/init.php
```

### Issue: Dashboard URLs Not Working

**Symptoms:** AJAX requests return 404

**Solutions:**

1. Check AJAX path in index.php:

```javascript
// Correct paths (relative to public/)
fetch('ajax/get-domains.php')
fetch('/ajax/get-domains.php')  // With leading slash
```

2. Verify AJAX files exist:

```bash
ls -la public/ajax/
```

3. Check document root:

```apache
DocumentRoot /home/user/domain-dashboard-final/public
# NOT: /home/user/domain-dashboard-final/
```

### Issue: Cross-Origin Errors

**Symptoms:** CORS errors in browser console

**Solutions:**

1. If dashboard and redirects on different domains, add CORS headers:

```php
// In ajax/*.php files
header('Access-Control-Allow-Origin: https://dashboard.yourdomain.com');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
```

2. Or use same domain with subdirectories (easier)

---

## Migration from Old Structure

### If you have old files in `/public`:

**Step 1: Backup**

```bash
cp -r public/s.php public/s.php.bak
cp -r public/shim.php public/shim.php.bak
```

**Step 2: Remove old files**

```bash
rm public/s.php
rm public/shim.php
```

**Step 3: Update links**

If any internal links reference `/s.php`, update to redirect domain:

```
OLD: https://dashboard.yourdomain.com/s/abc123
NEW: https://go.yourdomain.com/abc123
```

**Step 4: Test**

```bash
# Should NOT work anymore
curl -I https://dashboard.yourdomain.com/s/test123
# Expected: 404

# Should work
curl -I https://go.yourdomain.com/test123
# Expected: 302 redirect
```

---

## Production Checklist

- [ ] Apache/Nginx virtual hosts configured
- [ ] Document roots point to correct folders
- [ ] .htaccess files present and correct
- [ ] File permissions set (755 folders, 644 files)
- [ ] .env file configured (NOT committed to Git)
- [ ] Database credentials correct
- [ ] SSL certificates installed (HTTPS)
- [ ] mod_rewrite enabled
- [ ] AllowOverride All in config
- [ ] Test shortlink redirects
- [ ] Test dashboard AJAX calls
- [ ] Mini WAF active
- [ ] Error logging configured
- [ ] Backup strategy in place

---

## Summary

**Folder Separation Benefits:**

✅ **Security**: Admin isolated from public redirects
✅ **Performance**: Different caching per folder
✅ **Scalability**: Can deploy separately
✅ **Maintenance**: Update dashboard without downtime
✅ **Flexibility**: Multiple redirect domains possible

**Recommended Setup:**

```
https://dashboard.yourdomain.com  → /public  (Admin only)
https://go.yourdomain.com         → /redirect (Public)
```

**Key Files:**

- `/public/index.php` - Dashboard UI
- `/redirect/s.php` - Shortlink handler
- `/redirect/shim.php` - Intermediate redirect page
- `/redirect/.htaccess` - URL rewriting rules

---

**End of Folder Structure Guide**
