# TemseeEdu School Edition On Shared cPanel

This mode is for shared cPanel hosting where Composer, Redis, Supervisor, persistent queue workers, and `CREATE DATABASE` privileges may not be available.

## When To Use This

Use this mode when the host only gives you:

- cPanel File Manager or FTP/SFTP;
- cPanel MySQL Databases;
- PHP selector;
- cron jobs;
- limited SSH or no Composer.

For VPS, Railway, Plesk VPS, or managed servers, use the standard deployment flow instead.

## Key Differences From Standard Hosting

cPanel mode assumes:

- the package is built before upload;
- central and tenant databases are created manually in cPanel;
- Laravel uses file sessions and file cache;
- queues run synchronously;
- scheduler runs through cron;
- tenant database creation is skipped.

## Build The Package Locally

Run this locally before upload:

```bash
SKIP_ENCODING=1 ./scripts/build-school-edition.sh demo
```

Upload:

```text
dist/temseeedu-school-edition-demo.zip
```

The package must include production vendor files. The build script verifies this and fails if critical files are missing, including:

```text
vendor/livewire/livewire/dist/livewire.min.js
vendor/laravel/framework/src/Illuminate/Foundation/resources/exceptions/renderer/dist/styles.css
public/vendor/livewire/livewire.min.js
```

Do not upload a partially copied `vendor/` folder from File Manager. If `vendor/livewire/livewire/dist` is missing on the server, Filament login will load but Livewire JavaScript will return `500`.

The School Edition build sets shared-hosting-safe defaults in `.env.example`:

```env
TEMSEEEDU_EDITION=school_edition
TEMSEEEDU_HOSTING_MODE=cpanel
SESSION_DRIVER=file
CACHE_STORE=file
QUEUE_CONNECTION=sync
```

## Create Databases In cPanel

Create two databases manually:

```text
cpaneluser_edu
cpaneluser_tenantschool
```

Create one MySQL user and assign it to both databases with full privileges.

For example, if:

```env
TENANCY_DB_PREFIX=cpaneluser_tenant
TENANCY_DB_SUFFIX=
```

and the tenant ID is:

```text
school
```

then the tenant database must be:

```text
cpaneluser_tenantschool
```

## Required `.env`

Set these values in the deployed `.env`:

```env
APP_ENV=production
APP_DEBUG=false
APP_URL=https://schooldomain.com

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=cpaneluser_edu
DB_USERNAME=cpaneluser_dbuser
DB_PASSWORD=your_password

TEMSEEEDU_EDITION=school_edition
TEMSEEEDU_HOSTING_MODE=cpanel
TEMSEEEDU_INSTALLED=true

TENANCY_DB_PREFIX=cpaneluser_tenant
TENANCY_DB_SUFFIX=

SESSION_DRIVER=file
CACHE_STORE=file
QUEUE_CONNECTION=sync
```

Make sure these folders exist and are writable:

```text
storage/
storage/framework/
storage/framework/cache/
storage/framework/cache/data/
storage/framework/sessions/
storage/framework/views/
bootstrap/cache/
```

## If Composer Is Not Installed Globally

Many cPanel hosts do not provide a global `composer` command. If you need Composer on the server, install it locally inside the app folder:

```bash
cd /home/cpaneluser/path/to/school-edition
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php composer.phar install --no-dev --optimize-autoloader
```

Prefer uploading the prebuilt package from `dist/` instead of relying on Composer on shared hosting. Some Composer/package distributions omit non-PHP frontend bundles, so the TemseeEdu build script restores and verifies the required Livewire `dist/` files before zipping.

## Install The School

Run from the deployed app folder:

```bash
php artisan temsee:cpanel-install-school \
  --tenant-id=school \
  --domain=schooldomain.com \
  --name="School Name" \
  --email="admin@schooldomain.com" \
  --years=1
```

This command:

- runs central migrations;
- applies default AI plan quotas;
- checks that the tenant database exists;
- creates or updates the tenant row without trying to create a database;
- attaches the school domain;
- runs tenant migrations;
- seeds roles, permissions, classes, and the first school admin;
- creates the School Edition subscription record;
- writes school profile settings;
- syncs school integration blueprints;
- attempts `storage:link`.

If `storage:link` is blocked by the host, create the symlink from cPanel if available. If symlinks are not allowed, uploaded public files may need an alternate serving strategy.

## Post-Upload Health Check

After upload or update, run:

```bash
php artisan temsee:cpanel-check --fix
php artisan temsee:cpanel-check
```

The check verifies cPanel-safe settings, writable folders, Laravel exception renderer assets, Livewire vendor assets, and published Livewire public assets.

Then verify Livewire directly:

```bash
curl -I 'https://schooldomain.com/livewire/livewire.min.js?id=dev'
```

Expected:

```text
HTTP/1.1 200 OK
Content-Type: application/javascript
```

If it returns `500`, check:

```bash
ls -la vendor/livewire/livewire/dist
ls -la public/vendor/livewire
```

Then rerun:

```bash
php artisan livewire:publish --assets
php artisan optimize:clear
```

## Cron

Use cPanel Cron Jobs:

```cron
* * * * * cd /home/cpaneluser/path/to/school-edition && php artisan schedule:run >> /dev/null 2>&1
```

Keep:

```env
QUEUE_CONNECTION=sync
```

Do not use a permanent queue worker on shared hosting unless the provider explicitly supports it.

## Updating

For updates:

1. Build a new package locally.
2. Upload and replace code files.
3. Keep the existing `.env` and `storage/`.
4. Run:

```bash
php artisan temsee:cpanel-check --fix
php artisan migrate --force
php artisan tenants:migrate --tenants=school --force
php artisan temsee:sync-school-integrations --tenant=school
php artisan optimize:clear
php artisan temsee:cpanel-check
```

## Practical Limits

Shared cPanel can work for a small school install, but it is not ideal for heavy traffic, large uploads, background jobs, or many plugins. For serious production use, VPS or Railway is still the better long-term host.
