| name | adonisjs-best-practices |
|---|---|
| description | Apply this skill whenever writing, reviewing, or refactoring AdonisJS v7 code. This includes controllers, Lucid models, migrations, VineJS validators, policies and abilities, middleware, transformers, jobs, Ace commands, service classes, and Edge templates, layouts, components, forms, and view rendering. Triggers for N+1 and query performance issues, eager loading, transactions, authentication and authorization patterns, validation, exception handling, queue and job configuration, route definitions, dependency injection, security, and architectural decisions. Also use for AdonisJS code reviews and refactoring. |
| license | MIT |
Best practices for AdonisJS, organized as an index of rule files. Each rule file teaches what to do and why.
AdonisJS is a TypeScript-first, ESM-only Node.js framework. It borrows a great deal of vocabulary from Laravel (controllers, middleware, providers, policies, migrations, factories), but the implementations differ. Do not translate Laravel APIs into AdonisJS by analogy — the names match far more often than the signatures do.
This project is AdonisJS v7. Never write v5 or v6 APIs.
Your training data contains far more v5 and v6 AdonisJS than v7, so the APIs you reach for by reflex — vine.compile(), router.makeUrl(), .middleware() on routes, hand-declared model columns, anything with an @ioc: prefix — are frequently the outdated ones. Read rules/version-traps.md before writing your first line of AdonisJS code in a session. Of every file here, it is the one most likely to prevent a broken change.
Before applying any rule, check what the application already does. AdonisJS offers multiple valid approaches, and the best choice is usually the one the codebase already uses, even when another pattern is theoretically better. Inconsistency is worse than a suboptimal pattern.
Check sibling files — nearby controllers, models, validators, or tests — for established patterns. If one exists, follow it. Don't introduce a second way to do the same job. These rules are defaults for when no pattern exists yet, not overrides for decisions the project has already made.
- Assume v7 (
@adonisjs/core7.x,@adonisjs/lucid22.x,@vinejs/vine4.x). Readpackage.jsonwhen a minor version matters — experimental packages like@adonisjs/queuestill shift between releases. - Check the changed files, nearby code, config files, and relevant tests for established patterns. Deviate only for a correctness or security defect, and call the deviation out.
- Map every affected concern to the rule index below. Read each mapped rule file before editing. Skip unrelated rule files.
- Prefer
node ace make:*generators over hand-writing files, so scaffolding matches the installed version's conventions.node ace listshows what is available. - Make the smallest coherent change. Keep the application's architecture and naming instead of introducing a second pattern for the same job.
- Run the narrowest relevant tests first, then type-checking (
npm run typecheck, usuallytsc --noEmit) and the project's lint/format commands when the change warrants them. - Re-read the diff against every mapped rule before finishing.
Cross-cutting changes often need more than one rule file.
| Concern | Read |
|---|---|
| Any AdonisJS work — version-specific API traps | rules/version-traps.md |
| Layer boundaries, when to extract a service, when not to abstract | rules/architecture.md |
| Routes, params, matchers, resource routes, URL generation | rules/routing.md |
| Controllers, actions, HttpContext, response shaping | rules/controllers.md |
| Edge templates, view state, layouts, components, forms, helpers | rules/edge.md |
| Middleware stacks, named middleware, request pipeline | rules/middleware.md |
| VineJS schemas, request validation, custom messages | rules/validation.md |
| Lucid models, schema classes, relationships, hooks, serialization | rules/lucid-models.md |
| Query count, eager loading, indexes, pagination, large datasets | rules/db-performance.md |
| Schema changes, columns, foreign keys, indexes, rollbacks | rules/migrations.md |
| Transactions, atomicity, locks, multi-step writes | rules/transactions.md |
| API response shaping, serialization, generated frontend types | rules/transformers.md |
| Guards, credential verification, sessions, access tokens | rules/authentication.md |
| Bouncer abilities, policies, ownership checks | rules/authorization.md |
| Exceptions, the global handler, reporting, status pages | rules/error-handling.md |
Services, IoC container, @inject, providers, application structure |
rules/services-di.md |
Config files, environment variables, APP_KEY, secrets |
rules/config.md |
| Background jobs, queues, retries, scheduling | rules/queues-jobs.md |
| Japa tests, suites, factories, database state, API client | rules/testing.md |
| Input safety, hashing, CSRF, uploads, rate limiting, secrets | rules/security.md |
| Naming, file layout, subpath imports, TypeScript style | rules/style.md |
- Prefer framework features and existing application abstractions over new helpers or dependencies.
- Validate at the edge, then trust. Once
request.validateUsing()returns, the payload is trustworthy — don't re-check it in services or models. - Authorize before you validate, and both before you write. A user who cannot perform an action should not learn about your validation rules.
- Avoid speculative abstractions. Extract code when it creates a clear domain boundary, removes meaningful duplication, or makes behavior independently testable.
- Keep database access out of Edge templates and Inertia props, and prevent hidden N+1 queries across controllers, transformers, jobs, and serialization.
- Never edit generated files (
database/schema.ts, anything under.adonisjs/). Change the source of truth — a migration, a transformer, a route — and regenerate.
These rules capture judgment and defaults; they are not an API reference. When you need exact signatures, options, or rules that changed between versions, consult the official documentation, which is published in agent-readable Markdown:
- Any docs page, as raw Markdown: append
.mdto its URL — e.g.https://docs.adonisjs.com/guides/basics/validation.md - Indexed table of contents:
https://docs.adonisjs.com/llms.txt - Entire documentation in one file:
https://docs.adonisjs.com/llms-full.txt
A snapshot of the last two is vendored inside this skill, which is faster than a network fetch when you want to search the whole corpus at once:
Shell commands run from the project root, not from this directory, so search the installed path:
rg -n "withAuthFinder" .claude/skills/adonisjs-best-practices/references/llms-full.txtIt is a point-in-time copy, so prefer the live URLs for anything version-sensitive. See references/README.md.
- Lucid ORM (separate site, deeper than the core guide):
https://lucid.adonisjs.com - VineJS validation rules:
https://vinejs.dev - Japa test runner:
https://japa.dev