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(andext-sqlite3for 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).