Contributing

Contributing

Contributions to externa-core should match the existing Laravel + Inertia React stack, keep enums as the source of truth for permissions/field types/roles, and leave tests green.

Work in the externa-core directory unless you are editing these docs (externa-docs).

Tooling

PHP — Pint

Laravel Pint formats PHP. Composer scripts:

composer lint          # pint --parallel
composer lint:check    # pint --parallel --test

composer test runs lint:check before Pest.

Frontend — ESLint & Prettier

From externa-core:

npm run lint           # eslint . --fix
npm run lint:check     # eslint .
npm run format         # prettier --write resources/
npm run format:check   # prettier --check resources/
npm run types:check    # tsc --noEmit

CI-style gate:

composer ci:check

(runs npm lint/format/types checks + composer test).

Wayfinder

Laravel Wayfinder + @laravel/vite-plugin-wayfinder generates typed route/action helpers under resources/js during Vite build/dev.

  • Prefer Wayfinder helpers over hard-coded URL strings in React.
  • After adding/renaming named routes, run Vite (npm run dev or build) so generated clients refresh.
  • Do not hand-edit generated route trees as a long-term source of truth.

Pest

Feature and browser tests use Pest 4. See Testing for layout and how to run suites.

composer test
# or focused:
php artisan test --filter=SomeTestName

Coding conventions

Enums are the source of truth

ConcernEnumSync / mirror
PermissionsApp\Enums\PermissionEnumphp artisan permissions:sync → DB + resources/js/enums/permission-enum.ts
Roles (built-in names)App\Enums\RoleEnumSeeded in RoleSeeder
Field typesApp\Enums\FieldTypeEnumValidation, normalizer, UI catalog, AI instructions
File kindsApp\Enums\FileTypeEnumFile manager / storage helpers

Do not invent permission or field-type strings in controllers or React without updating the enum first. Extension recipes: Extending Externa.

Actions & Services

  • app/Services/ — domain orchestration used by controllers, jobs, and AI tools (FileService, Authorization\EffectivePermissionResolver, Collections services, …).
  • app/Actions/ — single-purpose actions (Fortify actions live under app/Actions/Fortify). Prefer a small Action class when a use-case is reused or would bloat a controller.
  • Controllers stay thin: Form Requests validate/authorize; Services/Actions mutate state; Jobs handle async work.

HTTP & auth

  • Admin/files/AI routes: enforce permissions with middleware or Form Requests (AuthorizesWithPermission / EffectivePermissionResolver).
  • Collections HTTP currently relies on UI + AI checks — if you harden that, document it and add tests (Collections API).
  • AI tools must use ChecksAiPermissions for mutating/domain operations.

Frontend

  • Pages under resources/js/pages/… matching Inertia names.
  • Gate UI with useCan() + PermissionEnum from the generated TS enum.
  • Follow existing shadcn/Radix + Tailwind patterns; avoid one-off design systems.

Jobs & schedule

New async work should use the queue (not dispatchSync in request paths for heavy I/O). If you add a scheduled command, register it in routes/console.php and document it under Operations.

Graphify knowledge graph

This monorepo maintains a graphify index under graphify-out/ at the Externa workspace root.

After you change code (PHP/TS that affects architecture or APIs):

cd /path/to/Externa
graphify update .

Use graphify query "…" when exploring relationships before large refactors. Skip graphify update for docs-only or pure config-comment edits that do not change behaviour.

Docs

Product docs live in externa-docs (Markdoc). Match existing frontmatter, {% .lead %}, and callout style. Keep statements accurate to externa-core source — no placeholder lorem.

PR expectations

  1. Pint / ESLint / Prettier / tsc clean.
  2. Pest coverage for new behaviour (see Testing).
  3. Enum + permissions:sync when permissions change; commit regenerated TS enum.
  4. Update Markdoc pages when you change public routes or config contracts.
  5. graphify update . when the code graph should reflect your changes.
Previous
Security checklist