# dispelled.ca PHP package

This archive is the complete PHP source tree for the site. It requires PHP 8.2+
and the JSON, SimpleXML/XML, mbstring, and OpenSSL extensions. No Node.js,
Composer, database, cron job, or build step is required.

## Source layout

The archive root is the package root:

```text
/var/www/dispelled-ca/
├── package.json
├── router.php
├── cache/
│   └── .gitkeep
├── public/                 # web document root
│   ├── index.php
│   ├── includes/
│   ├── categories/
│   ├── css/
│   ├── images/
│   └── .htaccess
└── scripts/
```

`public/` is the document root for Apache, Nginx, Caddy, and PHP-FPM. Keep the
package root and `cache/` outside that document root. The included
`public/.htaccess` is packaged from the real source tree; it does not depend on
or hard-code a `RewriteBase`, so it also works below a URL prefix.

## Built-in development server

Run this from the package root, not from `public/`:

```sh
php -S 127.0.0.1:3001 router.php
```

For a subdirectory deployment, set `BASE_PATH` to the URL prefix with a leading
slash and no trailing slash, for example `BASE_PATH=/dispelled`. The router
matches that prefix as a complete path segment, so `/app` does not match
`/apple`.

## Web servers

Point the server's document root at `/var/www/dispelled-ca/public`. Configure
PHP-FPM to execute the `.php` files under that directory and allow PHP to write
`/var/www/dispelled-ca/cache`. Nginx and Caddy should deny requests for
`/includes/` and other private files; Apache can use the included
`public/.htaccess` plus the usual virtual-host access rules.

For a subdirectory, map `/dispelled` to the `public/` directory and set
`BASE_PATH=/dispelled`. Do not put the package root itself on the public web.

## Shared hosting

Keep the same separation when the host provides a document-root directory:
upload the contents of `public/` to that document root and keep `cache/` in the
location resolved by `public/includes/config.php`. If the host requires a
different layout, edit that source file's `CACHE_DIR` definition explicitly.
Do not upload runtime cache JSON files. If the host only offers one
directory, ask it for a private writable path for cache rather than exposing
the package root.

The PHP account must be able to create and replace JSON files in `cache/`.
Enable HTTPS, `allow_url_fopen`, outbound DNS/HTTPS, and the listed PHP
extensions. The cache is disposable and is not part of the archive except for
the empty `.gitkeep` marker.

## Apache example

```apache
DocumentRoot /var/www/dispelled-ca/public
<Directory /var/www/dispelled-ca/public>
    Options -Indexes
    AllowOverride All
    Require all granted
</Directory>
<Directory /var/www/dispelled-ca/cache>
    Require all denied
</Directory>
```

## Nginx with PHP-FPM

```nginx
root /var/www/dispelled-ca/public;
index index.php;
location / { try_files $uri $uri/ =404; }
location ~ \.php$ {
    try_files $uri =404;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ^~ /includes/ { deny all; }
```

## Caddy with PHP-FPM

```caddy
root * /var/www/dispelled-ca/public
@private path /includes/*
respond @private 404
php_fastcgi unix//run/php/php8.3-fpm.sock
file_server
```

Check the PHP-FPM socket and filesystem permissions for the operating system.
Do not expose the built-in development server directly to the Internet.