Files
xamxam/docs/development.md
T

5.8 KiB

Development Guide

Setup, workflow, building assets, and testing for XAMXAM development.


Requirements

  • PHP ≥ 8.4 with ext-json, ext-openssl, ext-pdo (and ext-sqlite3 for the local DB)
  • Composer for PHP dependencies
  • Node.js / npm for frontend asset builds (rolldown, lightningcss, biome)
  • SQLite3 CLI (for just query, just init-db)

One-time setup

From the repo root, install dependencies (manually — there is no just recipe for these):

composer install           # PHP deps (vendor/)
npm ci                     # JS build deps (node_modules/)
just migrate               # create/update the SQLite DB from schema + migrations

just setup exists but its backing script (scripts/setup-dev.sh) is stale — it still clones the old php-live-reload library and creates legacy admin/data/ directories. Live-reload now ships inside the app (app/public/live-reload.php), and assets are built with rolldown/lightningcss, not the live-reload watcher. Prefer the explicit composer install + npm ci above.

Project Structure

xamxam/
├── app/                      # All application code (the project root on the server)
│   ├── bootstrap.php         # App bootstrapping (constants, autoload, config)
│   ├── router.php            # Router for the PHP built-in dev server
│   ├── public/               # DocumentRoot (web-accessible only)
│   │   ├── index.php         # Front controller / entry point
│   │   ├── request-access.php
│   │   ├── live-reload.php
│   │   ├── admin/            # Admin panel
│   │   ├── partage/          # Student submission via share links
│   │   └── assets/           # Built CSS/JS, fonts, images (dist/ is generated)
│   ├── src/                  # PHP classes
│   │   ├── Controllers/      # Request controllers (Home, Search, Tfe, Export, …)
│   │   ├── Form/             # Form helper
│   │   ├── Database.php      # DB access + queries
│   │   ├── AdminAuth.php     # Session auth for admin
│   │   ├── RateLimit.php
│   │   ├── FilepondHandler.php
│   │   ├── PeerTubeService.php
│   │   └── …                 # (see list in src/)
│   ├── templates/            # Template partials (public, admin, partials, partage)
│   ├── storage/              # Database + uploads (private)
│   │   ├── xamxam.db         # SQLite database
│   │   ├── schema.sql        # Base schema
│   │   ├── theses/ tfe/      # Uploaded files
│   │   └── cache/ logs/      # Runtime data
│   └── migrations/           # Migration runner + applied migrations
├── scripts/                  # Build / deploy / utility scripts
├── tests/phpunit/            # PHPUnit tests
├── nginx/                    # Server configuration + docs
├── deploy/                   # Cron configs (backup, cleanup)
├── justfile                  # Task runner
├── composer.json / package.json
└── TODO.md

Development Workflow

Start the dev server

just dev

This runs a one-shot asset build, applies pending migrations, opens http://127.0.0.1:8000/ (public) and /admin/ (admin), then starts the PHP built-in server (php -S 127.0.0.1:8000) with a chokidar watcher that rebuilds CSS/JS on change.

  • Public site: http://127.0.0.1:8000/
  • Admin panel: http://127.0.0.1:8000/admin/

Stop it with just stop.

If you only need the server without browsers/ui, run just dev-build first, then start the PHP built-in server manually with the php -d … -S command shown in the dev recipe (or add a just serve alias locally).

Frontend assets

Source CSS lives in app/public/assets/css/, source JS in app/public/assets/js/app/. They are bundled and minified into app/public/assets/dist/ by scripts/build*.mjs (rolldown + lightningcss).

just dev-build        # one-shot build (quicker output than full)
just build            # full build
just build-css        # CSS only
just build-js         # JS only
just build-check      # verify build output is up to date

There is no live-reloading in production — app/public/live-reload.php only activates under the PHP built-in server.

Testing

PHPUnit is used. Configuration lives in phpunit.xml, tests in tests/phpunit/ (with tests/bootstrap.php and tests/TestDatabase.php helpers).

just test              # run all PHPUnit tests
just test-coverage     # run with HTML coverage into coverage/

Linting / formatting

just lint-php     # phpstan (static analysis) + php-cs-fixer (coding standards)
just lint-css     # biome lint on app/public/assets/css/
just lint-js      # biome lint on app/public/assets/js/app/ + scripts/
just lint         # all linters
just fix          # auto-fix (biome + php-cs-fixer)

Database Operations

just migrate        # run pending migrations
just init-db        # create/reset DB from app/storage/schema.sql
just reset-db       # rm DB + init-db
just query          # open an interactive SQLite shell
just backup         # SQL dump into app/storage/backup_<timestamp>.sql
just backup-snapshot # WAL-safe hot backup + gzip into storage/backups/
just cleanup-drafts [--no-dry-run]   # remove orphaned drafts > 24h

See database.md for the full schema reference.

Deployment

See deployment.md. Files are pushed to the server with just deploy (rsync → xamxam:/var/www/xamxam/). There is no git repo on the remote.

Troubleshooting

just logs        # tail the dev error log (error.log)
just stop        # kill the dev server / asset watcher

If the browser doesn't hot-reload, confirm the asset watcher is still running and the rebuild succeeded (just dev-build).