Please read and understand the contribution guide before creating an issue or pull request.
- AI/LLM Usage
- Viability
- Procedure
- Requirements
- Testing, Code Style, and Static Analysis
- APIs, Backwards Compatibility, and Deprecation
- Implementation Details
- Translating the Application
If you use AI tools (Claude Code, Cursor, Copilot, etc.) to assist with your contribution, please read and follow our AI/LLM Contribution Policy.
When requesting or submitting new features, first consider whether it might be useful to others. Think about whether your feature is likely to be used by other users of the project.
Before filing an issue:
- Attempt to replicate the problem, to ensure that it wasn't a coincidental incident.
- Check to make sure your feature suggestion isn't already present within the project.
- Check the pull requests tab to ensure that the bug doesn't have a fix in progress.
- Check the pull requests tab to ensure that the feature isn't already in progress.
Before submitting a pull request:
- Check the codebase to ensure that your feature doesn't already exist.
- Check the pull requests to ensure that another person hasn't already submitted the feature or fix.
- Test your changes locally. As an open source project maintained by volunteers, we rely on contributors to verify their changes before submission. This includes running the test suite and manually testing the feature or fix.
-
Follow PSR-12 Coding Standard. Run
composer fixto fix most code style issues automatically. -
Ensure ESLint rules are followed. Run
pnpm lint:fixto fix most code style issues automatically. -
Add tests! - Your patch won't be accepted if it doesn't have tests.
-
Document any change in behaviour - Make sure the
README.mdand any other relevant documentation are up-to-date. If you are changing the API in some way, please also open an accompanying PR in the api-docs repository. -
Consider our release cycle - We try to follow SemVer v2.0.0. Randomly breaking public APIs is not an option.
-
One pull request per feature - If you want to do more than one thing, send multiple pull requests.
-
Send coherent history - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
Backend (PHP)
- Pest is used for testing. Write feature and/or unit tests.
- PHP CS Fixer comes as a dev dependency. Run
composer fixbefore you commit. - PHPStan is used for static analysis. Run
composer analyseand ensure your code has no errors.
Frontend (TypeScript/React)
- Vitest with Testing Library is used for testing React components.
- We target 100% test coverage for frontend code. All React components and utilities should have accompanying tests to verify their functionality.
- Run
pnpm verifyto check linting, TypeScript errors, and run all tests. - Run
pnpm test:run SomeFileto run specific tests.
APIs have to accommodate to old clients' requirements as upgrade paths are very slow for some of them.
Deprecations have to be communicated to users upfront.
Note The V1 Web API (
public/API/API_*.phpfiles) is in maintenance mode. Bug fixes are acceptable, but new features should be implemented in the V2 JSON:API instead.
Authorization
Define abilities in policies.
Authorize explicitly in controllers/actions. There is a variety of custom abilities, we don't want to end up in a hit or miss scenario. Do not use authorizeResource() in Controllers' constructor.
Use FormRequests in controllers for validation. Ignore Form Requests' authorization capabilities (should be done in controllers/actions instead).
Controllers, Actions, Reusable Action Classes
Controllers should be slim, start with an ability authorization, even if it's an "always-public" route.
In case of complex procedures, delegate to a reusable Action that can be injected from the container. If too much is going on in a controller's action it might be a good candidate to be extracted into a dedicated action. Especially if it's something that can be reused.
Frontend assets
This is not a Single Page Application. The project uses Inertia.js with React for page components.
Avoid inline styles and custom CSS unless there's a compelling reason. The project uses TailwindCSS and it should cover most styling needs.
The UI is actively migrating from Blade/Livewire to React. All new frontend work should use React with TypeScript and have comprehensive test coverage.
"Management app"
Back-office administration uses Filament. Admin resources, pages, and widgets are located in app/Filament/. Use Filament for internal management tools rather than building custom React admin interfaces.
Routes
Middleware gets applied for basic abilities (guest, auth, can:accessManagementTools) - specific abilities should be authorized in controller actions.
Slugs are kebab-cased and appended to model IDs (which in turn can be hashed/masked). This allows keeping /create, /edit, etc routes without having to deal with conflicts.
Route keys for route model binding should be validated in the respective RouteServiceProvider.
We welcome contributions to translate the RetroAchievements website into different languages. To get started, please refer to our translations guide for detailed instructions on how to add or update translations.