.claude/skills/ts-adonisjs/SKILL.md
Build full-stack web applications with AdonisJS — a batteries-included Node.js framework with ORM, auth, validation, and mailer built-in. Use when someone asks to "build a web app with Node.js", "Laravel for Node.js", "full-stack Node framework", "AdonisJS", "batteries-included backend", or "Node.js with built-in ORM and auth". Covers Lucid ORM, auth (sessions, tokens, social), VineJS validation, Edge templates, and deployment.
npx skillsauth add eliferjunior/Claude adonisjsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
AdonisJS is a full-stack Node.js framework — the "Laravel of Node.js." Unlike Express/Fastify where you assemble everything from packages, AdonisJS ships with an ORM (Lucid), authentication, validation (VineJS), mailer, queues, and testing out of the box. Opinionated, TypeScript-first, and production-ready.
npm init adonisjs@latest my-app -- --kit=web
cd my-app
node ace serve --watch
// start/routes.ts — Route definitions
import router from "@adonisjs/core/services/router";
const UsersController = () => import("#controllers/users_controller");
router.group(() => {
router.get("/users", [UsersController, "index"]);
router.get("/users/:id", [UsersController, "show"]);
router.post("/users", [UsersController, "store"]);
router.put("/users/:id", [UsersController, "update"]);
router.delete("/users/:id", [UsersController, "destroy"]);
}).prefix("/api");
// app/controllers/users_controller.ts — Controller with validation
import type { HttpContext } from "@adonisjs/core/http";
import User from "#models/user";
import { createUserValidator, updateUserValidator } from "#validators/user";
export default class UsersController {
async index({ request }: HttpContext) {
const page = request.input("page", 1);
const limit = request.input("limit", 20);
return User.query().paginate(page, limit);
}
async show({ params }: HttpContext) {
return User.findOrFail(params.id);
}
async store({ request, response }: HttpContext) {
const data = await request.validateUsing(createUserValidator);
const user = await User.create(data);
return response.created(user);
}
async update({ params, request }: HttpContext) {
const user = await User.findOrFail(params.id);
const data = await request.validateUsing(updateUserValidator);
user.merge(data);
await user.save();
return user;
}
async destroy({ params, response }: HttpContext) {
const user = await User.findOrFail(params.id);
await user.delete();
return response.noContent();
}
}
// app/models/user.ts — Lucid model with relationships
import { DateTime } from "luxon";
import { BaseModel, column, hasMany } from "@adonisjs/lucid/orm";
import type { HasMany } from "@adonisjs/lucid/types/relations";
import Post from "#models/post";
export default class User extends BaseModel {
@column({ isPrimary: true })
declare id: number;
@column()
declare email: string;
@column()
declare name: string;
@column({ serializeAs: null }) // Never include in JSON
declare password: string;
@hasMany(() => Post)
declare posts: HasMany<typeof Post>;
@column.dateTime({ autoCreate: true })
declare createdAt: DateTime;
@column.dateTime({ autoCreate: true, autoUpdate: true })
declare updatedAt: DateTime;
}
# Generate migration
node ace make:migration create_users_table
# Run migrations
node ace migration:run
# Rollback
node ace migration:rollback
// app/validators/user.ts — Request validation with VineJS
import vine from "@vinejs/vine";
export const createUserValidator = vine.compile(
vine.object({
email: vine.string().email().unique(async (db, value) => {
const user = await db.from("users").where("email", value).first();
return !user; // Must not exist
}),
name: vine.string().minLength(2).maxLength(100),
password: vine.string().minLength(8).confirmed(), // password + password_confirmation
})
);
export const updateUserValidator = vine.compile(
vine.object({
name: vine.string().minLength(2).maxLength(100).optional(),
email: vine.string().email().optional(),
})
);
// config/auth.ts — Auth config (sessions + API tokens)
import { defineConfig } from "@adonisjs/auth";
import { sessionGuard, sessionUserProvider } from "@adonisjs/auth/session";
import { tokensGuard, tokensUserProvider } from "@adonisjs/auth/access_tokens";
export default defineConfig({
default: "web",
guards: {
web: sessionGuard({ useRememberMeTokens: true, provider: sessionUserProvider({ model: () => import("#models/user") }) }),
api: tokensGuard({ provider: tokensUserProvider({ model: () => import("#models/user"), tokens: "accessTokens" }) }),
},
});
// app/controllers/auth_controller.ts
export default class AuthController {
async login({ request, auth, response }: HttpContext) {
const { email, password } = request.only(["email", "password"]);
const user = await User.verifyCredentials(email, password);
await auth.use("web").login(user);
return response.redirect("/dashboard");
}
async apiToken({ request, auth }: HttpContext) {
const { email, password } = request.only(["email", "password"]);
const user = await User.verifyCredentials(email, password);
const token = await User.accessTokens.create(user);
return { token: token.toJSON() };
}
}
User prompt: "Build a blog with AdonisJS — posts CRUD, user auth, and server-rendered pages."
The agent will scaffold an AdonisJS web app with Lucid models (User, Post), authentication middleware, VineJS validation, and Edge templates for the views.
User prompt: "Create a REST API with AdonisJS, API token authentication, and pagination."
The agent will set up API routes, access token guard, JSON responses with pagination, and Japa tests.
node ace for everything — generators, migrations, REPL, deploymentrequest.body() directlyserializeAs: null — exclude sensitive fields (password) from JSON serialization.preload() or .query().preload() to eager loadrouter.get('/dashboard').use(middleware.auth())node ace build → run build/server.js in productiondevelopment
Expert guidance for Fireworks AI, the platform for running open-source LLMs (Llama, Mixtral, Qwen, etc.) with enterprise-grade speed and reliability. Helps developers integrate Fireworks' inference API, fine-tune models, and deploy custom model endpoints with function calling and structured output support.
development
Convert any website into clean, structured data with Firecrawl — API-first web scraping service. Use when someone asks to "turn a website into markdown", "scrape website for LLM", "Firecrawl", "extract website content as clean text", "crawl and convert to structured data", or "scrape website for RAG". Covers single-page scraping, full-site crawling, structured extraction, and LLM-ready output.
tools
Expert guidance for Firebase, Google's platform for building and scaling web and mobile applications. Helps developers set up authentication, Firestore/Realtime Database, Cloud Functions, hosting, storage, and analytics using Firebase's SDK and CLI.
development
When the user needs to build file upload functionality for a web application. Use when the user mentions "file upload," "image upload," "upload endpoint," "multipart upload," "presigned URL," "S3 upload," "file validation," "upload to cloud storage," or "accept user files." Handles upload endpoints, file validation (type, size, magic bytes), cloud storage integration, and upload status tracking. For image/video processing after upload, see media-transcoder.