Maintainability Code Coverage FOSSA Status Known Vulnerabilities Laravel REUSE status Simple micropython software repository for Badges.
Live Site | API Playground | Documentation | GitHub
- Requires PHP 8.4.1 or later, with the
curl,dom,fileinfo,gd,gmp,mbstring,pdo_mysql,pdo_sqlite,pharandzlibextensions. Distributions often package these separately;pdo_sqlitein particular is easy to miss, and the licence list needs it. A missing one is reported by name on the first request rather than failing somewhere obscure. - Requires Python 3.6 or later
- Requires Node.js 22 or later
- Requires Redis 3.2 or later
- Requires Git 2.8 or later
For deployment on a server.
cp .env.example .env
Edit your database, mail and other settings..
Or copy the local dev environment config.
cp .env.dev .env
Install and configure required items.
pip install pyflakes composer install php artisan key:generate php artisan migrate npm ci npm run build
Install assets.
php artisan storage:link
Installing and configuring the async websocket server. Broadcasting goes over Redis into laravel-echo-server, which is no longer maintained upstream; Laravel Reverb is the modern replacement, but moving to it is not a drop in change.
npm install -g laravel-echo-server laravel-echo-server init
Compiling and installing the patched minigzip. Eggs are gzipped with a 13 bit window so the badges can inflate them, which stock gzip cannot do.
curl -O https://zlib.net/fossils/zlib-1.2.11.tar.gz tar xf zlib-1.2.11.tar.gz cd zlib-1.2.11 ./configure echo -e "#define MAX_WBITS 13\n$(cat zconf.h)" > zconf.h make sudo cp minigzip /usr/local/bin/
The Dockerfile does the same, pinned to that version and checked against its
sha256, with a mirror to fall back on when zlib.net turns CI traffic away.
If you would like to have Verilog support.
Install Icarus Verilog 0.9 or later.
TODO more info ;)
You'll need a be running Laravel Horizon service.
For the websocket server.
cp laravel-echo-server.json.example laravel-echo-server.json laravel-echo-server start
laravel-echo-server.json is deliberately not in the repository or the release
tarball: it holds host specific paths. Together with .env it is one of the two
files a deployment has to carry across by hand, and losing it is silent — the
site keeps working, only live updates stop.
Two settings need attention:
-
keyPrefixmust match the prefix Laravel puts on its Redis keys, or the server subscribes to a pattern nothing publishes to. That prefix defaults toStr::slug(APP_NAME) . '-database-', so it changes ifAPP_NAMEdoes. Ask the application rather than guessing:php artisan tinker --execute='echo config("database.redis.options.prefix"), PHP_EOL;' -
The
ssl*Pathentries are read once at startup, so the server keeps serving the certificate it started with. Restart it after a renewal, or it will eventually be offering an expired one.
To check a running server, from anywhere:
curl 'https://hatchery.example.com:6001/socket.io/?EIO=4&transport=polling'A session id comes back when it is healthy. "devMode": true logs every channel
it sees, which is the quickest way to confirm events are arriving — note that it
prints the channel name before the key prefix is stripped, so the prefix showing
up there is expected and not a misconfiguration.
After going through the steps
php artisan serve
If you don't want to install things and do the above steps, Docker makes all the above as easy as:
docker compose up # -d for daemon mode docker exec -it hatchery-laravel-1 php artisan migrate --seed docker exec -it hatchery-laravel-1 npm run watch
Enjoy your Hatchery at http://localhost:8000
See: https://hatchery.badge.team/api
Three suites, and they cover different things. The PHP tests need a database, the browser tests need the application running.
vendor/bin/pest # everything vendor/bin/pest --testsuite Unit # one suite, see phpunit.xml vendor/bin/pest tests/Unit/IconTest.php # one file vendor/bin/pest --filter "resized" # one case
Clear the caches first if the app has been run in between:
php artisan route:clear && php artisan config:clearnpm test # vitest, unit tests for the editor and icon helpers npm run test:watch
Playwright drives a real Chromium against a running Hatchery. It needs the
fixtures, and it starts the server itself unless APP_BASE_URL points at one.
php artisan db:seed --class=E2eSeeder --force npx playwright install --with-deps chromium npm run test:e2e
These cover the parts only a browser can answer: that the editor mounts and saves, that the public file view is read only, and that the editor bundle stays off pages that do not need it.
vendor/bin/phpstan analyse # level 8 vendor/bin/phpcs -q --warning-severity=0 vendor/bin/phpcbf # fix what it can npm run lint
vendor/bin/pest --coverage # summary in the terminal vendor/bin/pest --coverage-html docs/coverage # browsable report npm run coverage # JavaScript
CI publishes both to Qlty.
The JavaScript figure is lower than it looks because app.js and bootstrap.js
are browser entry points: they are exercised by the Playwright tests, which are
not instrumented, so they count as uncovered here. Everything a unit test can
reasonably reach is covered.
Files are stored in the database, so a large upload has to get past four
separate limits. The Docker image and docker-compose.yaml set all of these;
a hand rolled deployment needs them too.
| limit | where | needs to be |
|---|---|---|
upload_max_filesize |
php.ini | at least the ceiling |
post_max_size |
php.ini | a little above it |
memory_limit |
php.ini | file is read into a string |
max_allowed_packet |
MariaDB | one file is one big INSERT |
The ceiling itself is App\Models\File::MAX_UPLOAD_MEGABYTES, which the
uploader and the validation rule both read, so raising it is a one line change
plus matching server settings.
Hatchery follows the REUSE specification, so every file states its copyright and licence.
-
Source files carry an SPDX header:
// SPDX-FileCopyrightText: 2017 - 2026 Badge.Team contributors // SPDX-License-Identifier: MIT
-
Files that cannot hold a comment (images, JSON, lock files) and files that came from elsewhere are annotated in
REUSE.toml. -
Full licence texts live in
LICENSES/.
New files need a header. Check before pushing:
docker run --rm -v "$PWD:/data" fsfe/reuse lintA few assets predate this and could not be traced; they are marked
LicenseRef-Unidentified in REUSE.toml with a note on what each is suspected
to be. If you recognise one, please correct its entry.
Hatchery is open-sourced software licensed under the MIT license.
The Laravel framework is open-sourced software licensed under the MIT license.