# HostTiller — cPanel Deployment Guide
======================================

## You need:
1. All project files (this folder)
2. database/hosttiller.sql
3. .env.cpanel (rename to .env after upload)

---

## Steps:

### 1. Create MySQL Database in cPanel
- Go to "MySQL Databases" in cPanel
- Create a new database (e.g., hosttiller_db)
- Create a database user with a password
- Add the user to the database with ALL PRIVILEGES
- Note down: database name, username, password

### 2. Import the Database
- Go to "phpMyAdmin" in cPanel
- Select your new database
- Click "Import" tab
- Choose file: database/hosttiller.sql
- Click "Go" / "Import"

### 3. Upload All Files
- Upload the ENTIRE project folder via File Manager or FTP
- Make sure these folders exist with correct structure:
    hosttiller.com/
    ├── app/
    ├── bootstrap/
    ├── config/
    ├── database/
    ├── public/
    │   ├── build/        (compiled frontend assets)
    │   ├── index.php
    │   └── .htaccess
    ├── resources/
    ├── routes/
    ├── storage/
    ├── vendor/           (PHP dependencies)
    ├── .env
    ├── artisan
    └── .htaccess         (root redirect)

### 4. Setup .env
- Delete or rename .env.cpanel to .env
- Edit .env and update these 3 values:
    DB_DATABASE=your_database_name
    DB_USERNAME=your_database_user
    DB_PASSWORD=your_database_password
- Also update APP_URL to your domain

### 5. Set Document Root in cPanel
- Go to "Domains" in cPanel
- Set your domain's document root to:
    /home/yourusername/hosttiller.com/public
    OR
    public_html/hosttiller.com/public
- IMPORTANT: Point to the "public" folder!

### 6. Set Folder Permissions
Via File Manager or SSH, set these permissions:
- storage/           → 775 (recursive)
- bootstrap/cache/   → 775 (recursive)

If no SSH, do this in File Manager:
- Right-click folder → Permissions → set 775 → check "Recurse into subdirectories"

### 7. Run Laravel Setup (SSH required)
If your cPanel has Terminal/SSH access:
    cd /home/yourusername/hosttiller.com
    php artisan config:cache
    php artisan route:cache
    php artisan view:cache
    php artisan migrate --force

If NO SSH access, the site may still work but slower on first load.

### 8. Cron Job (Optional, for queue/scheduler)
In cPanel → Cron Jobs, add:
    * * * * * cd /home/yourusername/hosttiller.com && php artisan schedule:run >> /dev/null 2>&1

---

## IMPORTANT — Server-Side Rendering (SSR) for SEO

HostTiller is a React app (Inertia). Without SSR the page <body> ships empty,
so Google and SEO crawlers that don't run JavaScript report:
"0 words on this page", "No paragraphs detected", "title words not used in content".

-> After deploy, the SSR node server MUST be running on 127.0.0.1:13714
   (config/inertia.php `ssr.url`). Do ONE of the following:

Option A (recommended, cPanel Node.js App):
- cPanel → Setup Node.js App (Application Manager/Passenger)
- App root:  /home/yourusername/hosttiller.com
- Startup file: node bootstrap/ssr/ssr.js
- Passenger keeps it alive and restarts it automatically.
- If you set a different port, update INERTIA_SSR_URL in .env too:
    INERTIA_SSR_URL=http://127.0.0.1:PORT  (default 13714)

Option B (cron keep-alive, if no Node.js App available):
- Upload start-ssr.sh (in project root) to the server.
- cPanel → Cron Jobs, run every minute:
    * * * * * /bin/bash /home/yourusername/hosttiller.com/start-ssr.sh >/dev/null 2>&1
- The script starts `node bootstrap/ssr/ssr.js` if it isn't already running.

Verify it works (SSH):
    curl -s https://www.hosttiller.com/ | grep -c "Welcome to Hosttiller"
  > 2+ lines means the page body is server-rendered and crawlers see words.

Note: resources/views/app.blade.php also ships a <noscript> block with 250+
words of real content, so even if SSR is momentarily down the page never
returns an empty <body> to crawlers.

---

## Performance & response time

Fully-rendered anonymous public pages (homepage, pricing, etc.) are served
from cache by the CachePublicResponses middleware — TTFB drops from ~700ms
to a few ms. After editing content in the admin, changes appear within
PUBLIC_CACHE_TTL seconds (default 300). To apply instantly:
    php artisan cache:clear
To tune freshness vs. speed, add to .env:
    PUBLIC_CACHE_TTL=300

Extra speed (recommended on cPanel):
1. Enable PHP OPcache in cPanel (MultiPHP INI Editor -> opcache.enable = On,
   opcache.validate_timestamps = 0 during stable deploys). Largest win.
2. Cache Laravel's compiled config/routes/views:
    php artisan optimize
   (after changing .env run: php artisan config:clear && php artisan optimize)
3. Confirm the cache table exists (cross-checkbox in MySQL Databases) since
   CACHE_STORE=database is used for the page cache.

Excluded from caching on purpose: /contact, /secure-admin (admin), Inertia
navigations, JSON/API responses, and any request from a logged-in session.

---

## Troubleshooting:
- 500 Error? → Check .env exists and DB credentials are correct
- Blank page? → Check APP_DEBUG=false and storage/ has write permissions
- Assets not loading? → Make sure public/build/ folder was uploaded
- Routes not working? → Make sure document root points to "public/" folder
