filipebraida/adonisjs-starter-kit/routes
Claude Code and agent skill by filipebraida/adonisjs-starter-kit
- community
Checking that the SKILL.md file is still in the repository.
Route definitions in an AdonisJS module. Prefer `router.resource(...)` for CRUD verbs; put verb-only actions (activate, publish, finalize) as separate `router.post/get/delete(...)`. Always pin numeric params with `router.matchers.number()` — otherwise a non-numeric URL falls through to the controller and blows up on the ORM. Trigger on: "add route", "register route", "resource route", "matcher", ":id 500", "route naming".
Install
npx vskill@latest install filipebraida/adonisjs-starter-kit/routesSKILL.md
Routes
Each module owns its routes.ts. The file gets discovered by the preload wired in [[module-scaffolding]] — there is no autoloader. Routes have three loads to bear: they're the source of truth for URL generation (typed clients like Tuyau and the server-side URL builder read the named routes), for the middleware chain that guards the endpoint, and for the param typing that keeps garbage input out of the ORM.
Rules
- Numeric params get `router.matchers.number()`. Without it, a non-numeric URL reaches the controller,
Number('foo') → NaN, and Postgres throwsinvalid input syntax for type integer— the response is a 500. With the matcher the router 404s upstream, before boot. - CRUD verbs go through `router.resource()`. Custom verb actions (activate, publish, finalize) are separate
router.post(...)in the same file, not extra methods on the resource controller. - Route names follow the URL hierarchy:
parents.children.action. Named routes are the single source of truth for both the typed frontend URL client and the server-sideurlFor(...)used inside jobs and listeners. Both derive the URL from the name; the name is a contract. - Param names match across parents: for a nested resource named
parents.childrenuse.params({ parents: 'parent_id' })and pin every id:.where('parent_id', router.matchers.number()).where('id', router.matchers.number()). Snake_case, semantic, matching what the URL client expects. - Group by shared middleware. Put every route that shares the same auth/middleware stack inside one
router.group(() => {...}).middleware(...)block. Public routes live outside, guarded ones inside.
Reference shape
Choosing verb vs resource
router.resource(...)when the endpoint fits a standard CRUD verb:index,create,store,show,edit,update,destroy. Trim with.only([...])to what the controller actually exposes.router.post/get/delete(...)with.as(...)when the action does not fit a CRUD verb: activate, publish, finalize, invite, impersonate. Put them in the sameroutes.tsas the resource they belong to.
Hardcoding a route pattern
Some server-side callers need the pattern — the raw template with :params, not a filled URL. Example: transmit.authorize('/pattern/:x/...', ...) inside start/transmit.ts. Because that file executes during preload, before Server.boot() calls router.commit(), doing router.findOrFail(name).pattern there throws.
Two options, in order of preference:
- Hardcode the pattern + add a spec that guards it. Export the pattern as a constant, and write a functional test asserting the constant equals
router.findOrFail(name).pattern. If the route ever renames, the test breaks before deploy. - Defer with `app.ready(...)`. Only works when the pattern is needed at request-handling time.
app.readyfires beforerouter.commit(), so it does not rescuetransmit.authorize.
Repo refs
- Resourceful + verb routes with numeric matchers:
app/users/routes.ts. - Verb-only routes:
app/notifications/routes.ts.
Anti-patterns
- ❌ Numeric
:idwithout.where('id', router.matchers.number())— 500 on any non-numeric URL. - ❌ Verb action stuffed into the resource controller as an extra method — pollutes route naming and forces
.only([...])to grow. - ❌
router.findOrFail(...)at the top level ofstart/*.ts— the router isn't committed yet at preload time. - ❌ Renaming params to
id1/id2in nested resources — URL clients read semantic names (parent_id,child_id). - ❌ One giant middleware chain on each individual route instead of a
router.group(...).middleware(...)block.
Related skills
[[module-scaffolding]] · [[crud]] · [[actions-events]] · [[notifications]] · [[testing]]
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingpackages/skills/routes/SKILL.md
Popularity
- Repository stars
- 94
- Repository forks
- 12
- 7-day trend score
- 23
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/filipebraida/adonisjs-starter-kit/routes)