> ## Documentation Index
> Fetch the complete documentation index at: https://docs.theaitracker.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Contributing

> Branching, formatting, tests and CI conventions.

## Branching

`master` is the main branch and the usual PR target. Branch names in the history follow a
type prefix:

```
fix/prompt-response-rendering
design/single-prompt-page
design/finalize-prompt-management-module
```

Work merges into `master` through pull requests.

## Before you push

Run the same checks CI does, in this order:

```bash theme={null}
vendor/bin/pint          # PHP formatting (Laravel Pint)
npm run format           # Prettier over resources/
npm run typecheck        # tsc --noEmit
vendor/bin/pest          # test suite
```

Both formatters rewrite files, so run them before committing rather than after review
feedback. `npm run format:check` is the non-writing variant if you only want to know whether
something is off.

## CI

Two workflows live in `.github/workflows`, both triggered on pushes and pull requests
targeting `master` or `develop`:

| Workflow    | Steps                                                                                                                                      |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `lint.yml`  | PHP 8.4, `vendor/bin/pint`, `npm run format`                                                                                               |
| `tests.yml` | PHP 8.4 + Node 22, `npm ci`, `composer install`, copy `.env.example`, `key:generate`, `ziggy:generate`, `npm run build`, `vendor/bin/pest` |

<Warning>
  `lint.yml` does not currently **enforce** anything. Both steps run in write mode —
  `vendor/bin/pint` and `npm run format` rewrite files and exit `0` — and the
  `git-auto-commit-action` step that would have pushed the result is commented out. So the
  formatting is applied to a throwaway checkout and discarded.

  Neither formatter passes on the repository as it stands (`pint --test` and
  `npm run format:check` both report a large number of files), so switching the workflow to
  check mode needs a repo-wide formatting commit first. Until then, treat a green `linter`
  run as "the workflow completed", not "the code is formatted".
</Warning>

There is no frontend linting step. ESLint is not a dependency of this project — the old
`eslint.config.js` was Vue configuration inherited from the `laravel/vue-starter-kit`
skeleton and was removed once the app moved to React. Type safety comes from
`npm run typecheck` instead.

<Note>
  `develop` is kept in the trigger list but does not currently exist as a remote branch.
  `master` is the live target.
</Note>

## Code conventions

* **PHP** — Laravel Pint with the project's default preset. Formatting is not negotiable;
  let Pint decide.
* **TypeScript** — strict compilation via `npm run typecheck`. Prettier handles layout, with
  `prettier-plugin-organize-imports` sorting imports and `prettier-plugin-tailwindcss`
  ordering class names.
* **Routes** — add to the file in `routes/` that matches the concern rather than growing
  `web.php`. Always name routes; Ziggy exposes them to the frontend.
* **Provider calls** — never in the request cycle. Dispatch a job and let the UI poll.
* **New provider costs** — add the model to `config/ai.php` with `cost_per_1k_tokens`, or
  `TokenUsageTracker` will record spend as zero.

## Tests

Pest, split into `tests/Unit` and `tests/Feature`. Feature tests cover the Inertia pages and
settings flows — see `PromptsPageTest`, `VisibilityPromptAnalyticsTest` and
`OnboardingCompleteTest` for the established patterns.

The `sync` queue driver means dispatched jobs run inline, so assert against the resulting
records rather than against the queue.

<Warning>
  `phpunit.xml`'s in-memory SQLite setting is not currently taking effect — see
  [Development › Tests](/development#tests). A local run against a `.env` pointing at MySQL
  migrates your development database and fails. Verify the suite's state before treating a
  local failure as your own regression.
</Warning>
