# Contributing

Thanks for your interest in FFR. This is a small self-hosted project, issues and
pull requests are both welcome.

## Reporting issues

Use [Issues](https://forge.lvl0.xyz/lvl0/fedi-feed-router/issues).

For bugs, include what you expected, what happened, and enough detail to
reproduce it. If a feed is behaving unexpectedly, the feed URL matters most
because differences in how providers structure their RSS or Atom output are the
usual cause. Relevant log output helps; `dev-logs` follows the application log.

## Development setup

Requires PHP 8.2+ and Docker. The development environment runs in containers
defined by `docker/dev/docker-compose.yml`.

On NixOS, or anywhere with Nix installed:

```bash
git clone https://forge.lvl0.xyz/lvl0/fedi-feed-router.git
cd fedi-feed-router
nix-shell
```

The shell prints the available commands on entry and can start the containers
for you:

| Command | Description |
|---------|-------------|
| `dev-up` | Start the development environment |
| `dev-down` | Stop the development environment |
| `dev-restart` | Restart the containers |
| `dev-rebuild` | Rebuild the images |
| `dev-shell` | Enter the app container |
| `dev-artisan <cmd>` | Run an artisan command |
| `dev-logs` | Follow the application log |
| `dev-logs-db` | Follow the database log |

Once running:

| Service | URL |
|---------|-----|
| App | http://localhost:8000 |
| Vite | http://localhost:5173 |
| MariaDB | localhost:3307 |
| Redis | localhost:6380 |

Without Nix, start the same containers directly from
`docker/dev/docker-compose.yml`. Contributions improving the setup instructions
for other platforms are welcome.

## Before opening a pull request

Three checks run in CI, and all three must pass. Run them locally first, from
inside the app container or anywhere the project's dependencies are available:

```bash
vendor/bin/pint --test        # code style, Laravel preset
vendor/bin/phpstan analyse    # static analysis, level 7
php artisan test              # PHPUnit, Unit and Feature suites
```

Some conventions:

- **Static analysis.** PHPStan runs at level 7 with a baseline
  (`phpstan-baseline.neon`) covering pre-existing findings. Don't add baseline
  entries to silence errors in code you're writing. Fix the cause instead.
  Inline `@phpstan-ignore` comments aren't used in this project. The baseline is
  for cases where the analyser or an upstream docblock is wrong, not real bugs.
- **Tests.** New behaviour needs a test. Tests must run offline, so use fixtures
  or fakes rather than reaching for the network.
- **Dependencies.** `composer.lock` is committed. If you change dependencies,
  commit the updated lockfile alongside `composer.json`.

## Commits

One commit does one thing. Keep each commit passing all three checks so history
stays bisectable. Separate renames from behaviour changes, and mechanical edits
from logic.

Commit messages are a single line, referencing the issue they belong to:

```
141 - Add channel deletion to the Channels page
```

No body, no trailers.

## License

By contributing, you agree that your contributions are licensed under the
[GNU AGPL-3.0](LICENSE), the same license as the project.
