TextSearch

AdonisJS - The batteries-included TypeScript framework

Everything you need in one Node.js framework. Authentication, ORM, validation, mail, file uploads, testing - all working together. Built for teams who want to ship

· archived 5/20/2026, 8:19:43 PMscreenshotcached html
New The AdonisJS roadmap is live. See what's coming The batteries-included TypeScript framework Everything you need in one Node.js framework. Authentication, ORM, validation, mail, queues, cache, testing - all working together. Built for teams who want to ship products, not assemble frameworks. Get Started Our Philosophy Ledger Renault Group Bouygues Telecom France Travail INDIEVIDUALS NISSAN ZenChef Marie Claire Leroy Merlin PAYTM Evian VolleyBall World FIVB Edmond de Rothschild Cleavr EQWIN Pappers ZEVENT Lighthouse TWN Verifiables Zakodium Cavai Knihobot Adocasts Ledger Renault Group Bouygues Telecom France Travail INDIEVIDUALS NISSAN ZenChef Marie Claire Leroy Merlin PAYTM Evian VolleyBall World FIVB Edmond de Rothschild Cleavr EQWIN Pappers ZEVENT Lighthouse TWN Verifiables Zakodium Cavai Knihobot Adocasts Code you'll actually enjoy writing AdonisJS combines expressive APIs with clear conventions and full TypeScript support. Explore the examples below to see how common tasks stay simple without sacrificing power Routing Controllers Validators Models Auth File uploads Emails Rate limiter Testing import { middleware } from '#start/kernel' import router from '@adonisjs/core/services/router' import { controllers } from '#generated/controllers' router .group(() => { router.get('login', [controllers.Session, 'create']) router.post('login', [controllers.Session, 'store']) router.get('signup', [controllers.NewAccount, 'create']) router.post('signup', [controllers.NewAccount, 'store']) }) .use(middleware.guest()) // Creates a total of 7 routes to manage posts router.resource('posts', controllers.Posts) A functional API that centralizes your route definitions in one readable file. Know exactly what endpoints exist, how they're protected, and where they lead - all without jumping between files. Lazy-loaded controllers ensure your app stays performant as it grows import Post from '#models/post' import { HttpContext } from '@adonisjs/core/http' export default class PostsController { async index({ request }: HttpContext) { const posts = await Post.query().preload('author').paginate(1, 20) return posts } async store({ request, auth, response }: HttpContext) { const data = request.validateUsing(createPostValidator) const post = await auth.user.related('posts').create(data) return response.created(post) } } Group related request handlers in a single controller - one per resource. Each method handles the request for a specific route with full access to request data, auth, and params through HttpContext. A clear organizational pattern that scales naturally as your app grows import vine from '@vinejs/vine' export const createPostValidator = vine.create({ title: vine.string().minLength(3).maxLength(255), content: vine.string().minLength(10), coverImage: vine.file({ size: '2mb', extnames: ['jpg', 'png', 'webp'] }).optional() }) export const createUserValidator = vine.create({ fullName: vine.string().nullable(), email: vine.string().email().unique({ table: 'users' }), password: vine.string().confirmed() }) Twice the speed of Zod with async validation support built in. VineJS integrates deeply with AdonisJS - unique checks query your database through the ORM, file rules validate uploads seamlessly, and error messages come from your i18n files import User from '#models/user' import Comment from '#models/comment' import { PostSchema } from '#database/schema' // ...other imports export default class Post extends PostSchema { @belongsTo(() => User) author: BelongsTo<typeof User> @hasMany(() => Comment) comments: HasMany<typeof Comment> } await Post.all() await Post.query().preload('author').where('id', 1).firstOrFail() await Post.query().withCount('comments').paginate(1, 20) Active record ORM with a powerful query builder running on Knex. Define relationships, build complex queries with a fluent API, and manage your schema with migrations. Seeders and factories for testing and development // ...imports export default class AuthController { async login({ request, auth }: HttpContext) { const user = await User.verifyCredentials(email, password) // Create session for user await auth.use('web').login(user) } async loginWithToken({ request }: HttpContext) { const user = await User.verifyCredentials(email, password) // Create token for user const token = await User.accessTokens.create(user) return { token: token.value!.release() } } } Session-based authentication for web apps, access tokens for APIs, or use both in the same application. Auth middleware protects routes, password hashing happens automatically, and credential verification is built in // ...imports export default class AssetsController { async store({ request, response }: HttpContext) { const { file } = await request.validateUsing(createFileValidator) const fileName = `${uuid()}.${file.extname}` await file.moveToDisk(fileName, 'r2') return response.created({ fileName, url: `/assets/${fileName}` }) } async show({ params, response }: HttpContext) { const stream = await drive...