# TemseeEdu Single School Edition Deployment

This guide covers the recommended production setup when TemseeEdu is deployed for one school only.

## Best Deployment Model

Deploy School Edition as one dedicated tenant, not as the public SaaS model.

Recommended simple setup:

```text
schoolname.edu.gh        -> public school website
schoolname.edu.gh/admin  -> school admin panel
```

Optional separated setup:

```text
schoolname.edu.gh        -> public website
admin.schoolname.edu.gh  -> school admin panel
```

The same-domain setup is simpler for schools. The `admin.` subdomain setup is cleaner if the school wants strict separation between the public website and staff/admin access.

## Database Architecture

Even for one school, keep the existing central database plus tenant database structure.

Do not flatten the app into one database. The current codebase expects tenancy for:

- school admin routes;
- public school website routes;
- plugins and module activation;
- tenant storage;
- school-specific AI settings;
- compliance documents;
- school integrations;
- tenant migrations.

## Production Environment

Use production values in `.env`:

```env
APP_ENV=production
APP_DEBUG=false
APP_URL=https://schoolname.edu.gh
TEMSEEEDU_EDITION=school_edition
TEMSEEEDU_INSTALLED=true
```

Configure the real database, mail, queue, cache, SMS, payment, and license values for the school or hosting environment.

## Server Setup

Point the web server document root to:

```text
public/
```

Required writable paths:

```text
storage/
bootstrap/cache/
```

Recommended production commands:

```bash
composer install --optimize-autoloader --no-dev
npm ci
npm run build
php artisan key:generate
php artisan storage:link
```

## Provision The School

Run central migrations first:

```bash
php artisan migrate --force
```

Apply default AI quotas to local pricing plan records:

```bash
php artisan temsee:apply-ai-plan-quotas
```

Provision the single school tenant:

```bash
php artisan temsee:provision-school \
  --tenant-id=schoolname \
  --domain=schoolname.edu.gh \
  --name="School Name" \
  --email="admin@schoolname.edu.gh" \
  --plan=school_edition \
  --years=1
```

If using an admin subdomain instead:

```bash
php artisan temsee:provision-school \
  --tenant-id=schoolname \
  --domain=admin.schoolname.edu.gh \
  --name="School Name" \
  --email="admin@schoolname.edu.gh" \
  --plan=school_edition \
  --years=1
```

Then run tenant migrations:

```bash
php artisan tenants:migrate --force
```

Sync school integrations:

```bash
php artisan temsee:sync-school-integrations
```

Apply AI plan quota defaults if the pricing plan records are used on that deployment:

The web installer and `temsee:provision-school` now run the School Edition post-provision setup automatically:

- central subscription record;
- basic school profile settings;
- default school integration blueprints.

Running `tenants:migrate` and `temsee:sync-school-integrations` again after deployment is still safe and recommended after updates.

## Production Optimization

After setup or every deployment:

```bash
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan filament:cache-components
php artisan queue:restart
```

## Scheduler And Queue

Run Laravel's scheduler every minute:

```cron
* * * * * cd /path/to/temseeedu && php artisan schedule:run >> /dev/null 2>&1
```

Run a queue worker for mail, notifications, and background work:

```bash
php artisan queue:work --tries=3
```

On shared hosting or Plesk without Supervisor, use a cron-based worker:

```cron
* * * * * cd /path/to/temseeedu && php artisan queue:work --max-time=55 --stop-when-empty --tries=3 >> /dev/null 2>&1
```

## What The School Should See

For the simple setup:

```text
Website: https://schoolname.edu.gh
Admin:   https://schoolname.edu.gh/admin
```

For the separated setup:

```text
Website: https://schoolname.edu.gh
Admin:   https://admin.schoolname.edu.gh/admin
```

The school should not see platform internals such as:

- `/temsee`;
- tenant IDs;
- OpenRouter;
- Paystack plan sync;
- SaaS subscription internals;
- platform pricing-plan management.

## AI Assistant

Use OpenRouter only behind the scenes.

For School Edition, AI should be configured by the platform/admin operator, not by normal school users. The school only sees the assistant working inside the school panel.

Recommended pricing model:

- include a small AI request quota in higher School Edition packages;
- sell extra AI usage as an add-on;
- enforce monthly request limits through the existing AI usage quota layer.

## Payments

For School Edition, SaaS subscription checkout is not required for the school's daily use.

The school's own fee collection/payment features can still use school-level payment provider configuration, depending on the enabled Payments module.

The central Paystack plan sync is mainly for the SaaS model where schools subscribe through TemseeEdu's public registration flow.

## Post-Deploy Checklist

Most of this is handled by `./deploy.sh` (composer install, asset build, migrations, config/route/view/Filament caching, `storage:link`, cron setup — see the script's own header comment for flags). What's left is what can't be automated:

- [ ] `APP_ENV=production`
- [ ] `APP_DEBUG=false`
- [ ] `SESSION_SECURE_COOKIE=true` (once SSL is active — see below; a blank value means cookies aren't forced HTTPS-only)
- [ ] `LOG_LEVEL=error` (or `warning`) — the `debug` default floods `storage/logs` fast on a limited disk quota
- [ ] `TRUSTED_PROXIES=*` (or a specific IP/CIDR list) — without this, every visitor appears as the reverse proxy's own IP, which silently breaks every per-IP rate limiter (admission form, login, installer): the first few requests from *anyone* succeed, then everyone else gets throttled together
- [ ] web root points to `public/`
- [ ] central migrations ran successfully
- [ ] tenant was provisioned
- [ ] tenant migrations ran successfully
- [ ] school domain resolves correctly
- [ ] SSL is active for the school domain
- [ ] `/admin` login loads on the school domain
- [ ] scheduler is running (`* * * * * php artisan schedule:run`)
- [ ] queue worker is running, if `QUEUE_CONNECTION` isn't `sync` (cron-triggered `queue:work --stop-when-empty` on shared hosting — see `deploy.sh`)
- [ ] mail credentials are working — send a real test email, don't just check the settings form saved
- [ ] storage link works
- [ ] `php artisan temsee:cpanel-check` passes (School Edition on shared hosting) — also flags whether `exec()` is available, which the database backup/restore feature needs; if it's disabled, backups will silently fail with an unhelpful error until this is checked
- [ ] school integrations are synced
- [ ] AI configuration is tested if AI is included
- [ ] payment provider is tested if Payments is enabled — including the admission-fee paywall if admissions are open, with a real (small) payment, not just a form save
- [ ] composer dependencies audit clean (`composer audit`) — re-check this periodically, not just at initial deploy
