- About annotrAIn
- Features
- Tech Stack
- Installation - Local Development
- Development Environment
- Changelog
- Contributing
- Available Scripts
- Releasing a new version
- Security
- License
- Credits
annotrAIn is a Laravel-based annotation management system. The application manages annotators (users), their roles, and permissions via an Inertia/React SPA.
It includes a complete setup for both the backend and frontend, with support for both DDEV and Native (PHP, Composer, etc. running locally) development environments.
- Support for both DDEV and Native development environments
- React 19 / Inertia.js 2 frontend with Vite for faster development
- Tailwind CSS v4 with React Aria Components for accessible, keyboard-navigable UI
- SCSS support with PostCSS
- TypeScript (strict mode)
- Automated code formatting (PHP, JS/TS, SCSS)
- Git hooks for code quality
- Comprehensive test suite using Pest (backend) and Jest (frontend)
- Role-based access control using Spatie Laravel Permission
- Dark mode support
- Responsive design
- GitHub Actions for CI/CD
-
Backend:
- Laravel 12.x
- PHP 8.4
- MySQL/SQLite
- Laravel Pint (Code Styling)
- PHPStan / Larastan (Static Analysis at level 8)
- Pest (Testing)
-
Frontend:
- React 19 with Inertia.js 2
- TypeScript (strict mode)
- Tailwind CSS v4
- React Aria Components (accessibility-first UI primitives)
- Lucide React (icons)
- Sonner (toast notifications)
- Vite
- ESLint + Prettier + Stylelint
In order to start developing with annotrAIn, you will need to read the guide in the LOCAL-DEVELOPMENT.md file.
The application supports two development environments, controlled by APP_DEVELOPMENT_ENV in your .env file:
APP_DEVELOPMENT_ENV |
How to run commands |
|---|---|
native |
Run directly: composer …, npm …, php artisan …, vendor/bin/… |
ddev |
Prefix with ddev: ddev composer …, ddev npm …, ddev artisan …, ddev exec vendor/bin/… |
All commands in this document are shown in native form. DDEV users: add the
ddevprefix to every command — e.g.composer testbecomesddev composer test,npm run devbecomesddev npm run dev, andphp artisan migratebecomesddev artisan migrate.
Please see CHANGELOG for more information on what has changed recently.
To contribute to the application, follow these steps:
- Fork this repository.
- Read the CONTRIBUTING file.
- Create a branch:
git checkout -b <branch_name>. - Make your changes and commit them:
git commit -m '<commit_message>' - Push to the original branch:
git push origin <project_name>/<location> - Create the pull request
After making changes, follow this workflow:
composer fix # auto-fix everything (Rector + Pint + ESLint + Prettier)
composer check # verify style/lint rules — no file mutations (CI-safe)
composer test # run the Pest test suiteThis application uses Laravel Pint for PHP code styling, managed via Composer scripts.
composer fix # apply all auto-fixes (Rector + Pint + ESLint + Prettier)
composer fix:backend # backend only — no Node required (Rector + Pint)
composer check # dry-run checks — no modifications (CI-safe)Run the full test suite (lint + static analysis + Pest) via:
composer test:backend
# or composer testTo run or filter Pest tests directly:
composer test:backend # all tests
composer test:backend -- --filter TestName # filter by name
composer test:backend -- --testsuite=Feature # specific suiteddev composer test:backend ddev composer test:backend -- --filter UserControllerTest
ddev composer test:backend -- --filter "it creates a user" ddev composer test:backend -- --filter UserControllerTest --coverageTo run with code coverage (requires Xdebug):
XDEBUG_MODE=coverage ddev composer test:coverageWe use Laravel with Pest for end-to-end browser testing via Playwright. This replaces Jest component tests with real Chromium testing.
Prerequisites:
# 1. Kill any running dev servers (to avoid port conflicts)
pkill -f "vite" || pkill -f "composer run dev" || true
# 2. Build frontend assets (required)
npm run buildRun tests:
# Headless mode (CI-friendly)
composer test:browser
# Headed mode — watch the browser (debugging)
BROWSER_HEADLESS=false composer test:browserThe in-process server serves compiled assets from public/build/. Without them, Inertia pages fail to load and tests will fail.
Static analysis runs as part of composer check:types:
composer check:types # PHPStan (level 8) + TypeScript tsc --noEmit
composer check:types:backend # PHPStan only (no Node required)A pre-commit hook runs automatically on every commit. It:
- Scans staged files for secrets with Gitleaks (blocks commit if secrets detected)
- Runs Rector on staged
.phpfiles (automated refactors) - Runs Pint on staged
.phpfiles (code style formatting) - Runs Prettier / ESLint on staged
.js/.ts/.tsxfiles - Runs Prettier on staged
.scss/.cssfiles
Modified files are re-staged automatically, so the committed code always matches the formatted output.
The hook is installed automatically when you run:
composer installFor Gitleaks, you will need also to install the executable. See GITLEAKS-SECURITY.md for details.
If you need to reinstall it manually (e.g. after cloning without running composer install):
bash tools/git-hooks/install.shDDEV users: Git hooks run on the host machine, not inside the container.
Run
ddev composer installto install dependencies inside the container, but the hook script itself executes on the host usingvendor/bin/rector,vendor/bin/pint, andnpmfrom the project root.Make sure PHP and Node are available in your host shell, or run
ddev composer installfirst to populatevendor/bin/.
Bypassing the hook: If you genuinely need to skip it (e.g. a work-in-progress commit), use
git commit --no-verify. This should be rare.
| Script | Description |
|---|---|
composer dev |
Start dev server (auto-detects environment) |
composer fix |
Apply all auto-fixes — Rector + Pint + ESLint + Prettier (mutates files) |
composer fix:backend |
Backend fixes only — Rector + Pint (no Node required) |
composer fix:frontend |
Frontend fixes only — ESLint + Stylelint + Prettier |
composer check |
Verify style/lint rules — no file mutations (CI-safe) |
composer check:backend |
Backend checks only — Pint + Rector dry-run (no Node required) |
composer check:frontend |
Frontend checks only — ESLint + Stylelint + Prettier |
composer check:types |
Type analysis — PHPStan level 8 + TypeScript tsc |
composer check:types:backend |
PHPStan only (no Node required) |
composer test |
Run the Pest test suite (excludes browser tests) |
composer test:all |
Full CI suite: check + check:types + test:backend + test:browser |
composer test:coverage |
Pest with code coverage (requires Xdebug) |
composer update:requirements |
Bump Composer + npm dependencies to latest |
| Script | Description |
|---|---|
npm run dev |
Start Vite development server |
npm run build |
Build frontend assets for production |
npm run fix |
Apply all frontend auto-fixes (ESLint + Stylelint + Prettier) |
npm run fix:js |
ESLint auto-fix |
npm run fix:styles |
Stylelint auto-fix |
npm run fix:format |
Prettier write |
npm run check |
Verify all frontend rules — no file mutations (CI-safe) |
npm run check:js |
ESLint check |
npm run check:styles |
Stylelint check |
npm run check:format |
Prettier dry-run |
npm run types |
TypeScript type-check (tsc --noEmit) |
php artisan migrate # migrate the database
php artisan db:seed # seed the database
php artisan migrate:fresh # drop all tables and re-run migrations
php artisan migrate:fresh --seed # fresh migrate + seed
php artisan key:generate # generate application keyWhen using DDEV, the following project-specific shorthand commands are available in addition to the standard ddev prefix rules:
ddev pint # shorthand for ddev exec vendor/bin/pint
ddev analyse # shorthand for ddev exec vendor/bin/phpstan analyse
ddev format # shorthand for pint + npm format
ddev test # shorthand for ddev exec vendor/bin/pestVersion must be updated in two places before tagging:
package.json—"version": "x.x.x"config/app.php—'version' => env('APP_VERSION', 'x.x.x')
After committing your changes, create a new git tag:
git tag -a vx.y.z -m "This is a nice tag name"(for the x.y.z version number, follow the Semantic Versioning guidelines).
Then, push the tag:
git push origin vx.y.zThen, in the GitHub Releases page, create a new Release and correlate it with the tag that you just created.
Also, don't forget to update the CHANGELOG.md file with the new version name, release date, and release notes.
This project implements several security measures:
- Secret Scanning: Gitleaks integration prevents accidental exposure of sensitive information like API keys, passwords, and tokens. See GITLEAKS-SECURITY.md for detailed configuration and usage.
- Security Headers: Custom middleware adds security headers (CSP, HSTS, etc.)
- CSRF Protection: Laravel's built-in CSRF protection
- Role-based Access Control: Using Spatie Laravel Permission package
If you discover any security-related issues, please email info[at]scify.org, instead of using the issue tracker.
This project is open-sourced software licensed under the Apache License, Version 2.0.