base on The RetroAchievements.org platform. Includes core functionality for managing achievements, game data, and community features. <p align="center" dir="auto"><a href="https://retroachievements.org" rel="nofollow"><img src="https://raw.githubusercontent.com/RetroAchievements/RAWeb/master/public/assets/images/ra-icon.webp" width="200" alt="RetroAchievements Logo" style="max-width: 100%;"></a></p> **RAWeb** is [RetroAchievements.org](https://retroachievements.org)'s platform application. It is a Laravel application using [Inertia.js](https://inertiajs.com/) with React, TypeScript, and server-side rendering (SSR). The frontend is actively migrating from Blade/Livewire to React. Back-office administration is built with [Filament](https://filamentphp.com/). ## Requirements - Local web server - [PHP 8.4](http://php.net/manual/en/) - [Composer](https://getcomposer.org/) PHP dependency manager - [MariaDB 10](https://mariadb.com/docs/server/) - [Node.js 24](https://nodejs.org/) - [pnpm 10](https://pnpm.io/) Validated to run on Windows, macOS, and Linux with any of the setup options below (Docker via Laravel Sail, VM with either nginx or Apache, Laravel Valet on macOS). ### **[Docker Compose](https://docs.docker.com/compose/install/)** (Windows, Linux, macOS) Recommended. See [Laravel Sail documentation](https://laravel.com/docs/sail). ### **[XAMPP](https://www.apachefriends.org/download.html)** (Windows, Linux, macOS) Install the XAMPP version packaged with PHP 8.4 to run an Apache web server, MariaDB, and PHP on your system. You might have to enable some extensions in `php.ini` (see the `ext-*` requirements in [composer.json](composer.json)): ``` extension=curl extension=gmp extension=mysqli extension=pdo_mysql extension=gd extension=intl extension=sockets ``` ### **[Laravel Valet](https://laravel.com/docs/valet)** (macOS only) A [local valet driver](LocalValetDriver.php) is provided. ## Installation ```shell composer install ``` ### Run setup script ```shell composer setup ``` ### Configure The environment configuration file (`.env`) contains a sensible set of default values. **Docker/Laravel Sail** No additional configuration is needed; the configuration automatically detects whether it's running the application via the Laravel Sail application container and adjusts hosts and ports accordingly. However, you might want to adjust the forwarded container port numbers to your liking (`APP_PORT`, `FORWARD_*`). Now is a good time to create the containers. Sail forwards commands to Docker Compose: ```shell sail up # Daemonize: sail up -d ``` > **Note** > Mentions of `sail` commands assume that it has been aliased to the `./sail` executable according to Sail's docs. > I.e. run `./sail up` if you haven't aliased it. **XAMPP/Valet** Adjust the local environment configuration (`.env`): - Enter the credentials of your local database instance (`DB_*`) - Change the application URL (`APP_URL`) - static assets URL (`ASSET_URL`) should be the same as `APP_URL` > **Note** > `APP_URL` varies depending on your setup. By default it's configured to use the forwarded application Docker container port. > E.g. using an Apache vhost or linking a domain via Laravel Valet this should be adjusted accordingly: ```dotenv APP_URL=https://raweb.test ASSET_URL=https://raweb.test ``` **Hybrid Docker setup** When running the application locally (i.e. web server and PHP via XAMPP/Valet) it's possible to use the provided Docker services, too. Use database and redis services: ```dotenv DB_PORT=${FORWARD_DB_PORT} REDIS_PORT=${FORWARD_REDIS_PORT} ``` > **Note** > Connect with a database client of your choice using the forwarded ports > or use phpMyAdmin which runs at http://localhost:64080 by default. Use mailpit as SMTP server for local mails testing: ```dotenv MAIL_MAILER=smtp ``` > **Note** > Runs at http://localhost:64050 by default. Use minio as an AWS S3 drop-in replacement: ```dotenv AWS_MINIO=true ``` > **Note** > In order to use S3 features you'll have to create a `local` bucket manually first. > Runs at http://localhost:64041/buckets/add-bucket by default. ### Build frontend assets ```shell pnpm install pnpm build # Using Sail: sail pnpm install sail pnpm build ``` ### Development workflow For local development with hot module replacement: ```shell pnpm dev ``` Before submitting a pull request, verify your changes pass all checks: ```shell # Frontend pnpm verify # Runs linting, TypeScript checks, and Vitest tests # Backend composer fix # Fix code style issues composer analyse # Run PHPStan static analysis composer test -- --filter=TestFileName # Run an individual test suite composer test -- --parallel # Run all back-end tests in parallel ``` To run specific frontend tests: ```shell pnpm test:run SomeComponent # Run tests matching "SomeComponent" ``` ### Create filesystem symlinks ```shell php artisan ra:storage:link --relative # Using Sail: sail artisan ra:storage:link --relative ``` ### Setup database ```shell php artisan migrate # Using Sail: sail artisan migrate ``` Seed your database with additional test data: ```shell php artisan db:seed # Using Sail: sail artisan db:seed ``` ### Open the application in your browser. Depending on the setup you chose the application should run. - Docker: http://localhost:64000 - XAMPP: depending on Apache vhost configuration - Laravel Valet: e.g. https://raweb.test - depending on link / parked location and whether you chose to secure it or not ## Usage ### Developing achievements locally Add a `host.txt` file next to `RAIntegration.dll` in your local RALibRetro's directory. The file should contain the URL to your local RAServer instance. Any of the following will work: - `http://localhost:64000` when running the server via Docker, `composer start` or `artisan serve`. - `https://raweb.test` (example) when running the server via Valet - `http://raweb.test` (example) as a configured vhost ## Security Vulnerabilities Please see our [Security Policy](docs/SECURITY.md). ## Contributing Please see our [Contribution Guidelines](docs/CONTRIBUTING.md), [Translations Guide](docs/TRANSLATIONS.md) and [Code of Conduct](docs/CODE_OF_CONDUCT.md). ## License RAWeb is open-sourced software licensed under the [GPL-3.0 License](LICENSE). Console Icons by [yspixel.jpn.org](http://yspixel.jpn.org/icon/game/index.htm) and [Tatohead](https://github.com/Tatohead/Console-Iconset). ", Assign "at most 3 tags" to the expected json: {"id":"8217","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"