AdonisJS v6 is coming soon. Get early access to the Alpha release
AdonisJS includes everything you need to create a fully functional web app or an API server. So stop wasting hours downloading and assembling hundreds of packages — Use AdonisJS and be productive from day one.
AdonisJS is not a minimalist framework. To give your projects a head start, we pack many baseline features within the core of the framework.
AdonisJS has a feature rich routing layer with support for route groups, subdomain based routing and resource resources
Controllers are first class citizens in AdonisJS. They help you remove the inline route handlers to dedicated controller files.
Along with the standard bodyparser, the support for managing file uploads is baked into the framework core.
The schema based validator of AdonisJS provides you both the runtime validations and static type safety.
Create traditional style server rendered web apps using home grown template engine of AdonisJS
// Handle GET request
Route.get('posts', async ({ view }) => {
return view.render('posts/index')
})
// Handle POST request
Route.post('posts', async ({ request }) => {
return request.body()
})
Route
.group(() => {
Route.get('users', () => {})
Route.post('users', () => {})
})
.prefix('api/v1')
.middleware('auth')
// Static subdomain
Route
.group(() => {
Route.get('articles', () => {})
})
.domain('blog.adonisjs.com')
// Dynamic subdomain
Route
.group(() => {
Route.get('/', () => {})
})
.domain(':tenant.adonisjs.com')
import Post from 'App/Models/Post'
export default class PostsController {
public async index () {
return Post.all()
}
public async store ({ request }) {
return request.body()
}
}
// Bind controller to the route
Route.get('posts', 'PostsController.index')
Route.post('posts', 'PostsController.store')
Route.post('/posts', ({ request }) => {
// Access file
const coverImage = request.file('cover_image', {
extnames: ['jpg', 'png', 'jpeg'],
size: '2mb'
})
// Check for errors
if (coverImage.hasErrors()) {
return coverImage.errors()
}
// Move to uploads directory
await coverImage.move('uploads')
})
import { schema } from '@ioc:Adonis/Core/Validator'
export default class SignupValidator {
public schema = schema.create({
email: schema.string({}, [
rules.email()
]),
password: schema.string({}, [
rules.confirmed()
]),
fullName: schema.string.optional(),
})
}
// Pass validator to the request
Route.post('users', async ({ request }) => {
await request.validate(SignupValidator)
})
{{-- Write any JavaScript expression --}}
{{ user.username }}
{{ user.username.toUpperCase() }}
{{ (2 + 2) * 3 }}
{{ (await getUser()).username }}
@if(user.fullName)
<p> Hello {{ user.fullName }}! </p>
@elseif(user.firstName)
<p> Hello {{ user.firstName }}! </p>
@else
<p> Hello Guest! </p>
@end
{{-- Loop over an array --}}
@each(user in users)
<li> {{ user.username }} </li>
@end
{{-- Maybe an object too --}}
@each((amount, ingredient) in food)
<li> Use {{ amount }} of {{ ingredient }} </li>
@end
{{-- Component markup --}}
<button type="{{ type }}">
{{{ await $slots.main() }}}
</button>
{{-- Using component --}}
@component('button', { type: 'submit' })
<i class="fa-icon-lock" />
<span> Login </span>
@end
Companies that help me work full-time on the framework and make AdonisJS awesome every single day.
A wall full of love and support from our community
AdonisJS has a rich collection of first-party packages you can use to speed up your development process. Just like the framework, they are well maintained and easy to test.
SQL ORM built on top of Active Record pattern
Build login flows using API tokens or sessions
Build your own ACL using bouncer actions and policies
A modern template engine with the simplicity of old school SSR
Store user uploaded files in S3, GCS, or within the local file system
Your command-line companion to automate mundane tasks
Code. REPL. Repeat. The simplest way to dabble with your code from the command-line
Add social auth in your apps with Ally. Github, Twitter, Google - We have drivers for all
AdonisJS gives you a delightful testing experience with its well-crafted APIs, inbuilt fakes, helpers to reset the database state, HTTP clients, and more.
import { test } from '@japa/runner'
import { TwitterService } from 'App/Services/Twitter'
test('get latest tweets from a user timeline', async ({ assert }) => {
const twitterService = new TwitterService()
const tweets = await twitterService.fetchLatest()
assert.lengthOf(tweets, 10)
})
import { test } from '@japa/runner'
import Application from '@ioc:Adonis/Core/Application'
test('create new post', async ({ client, route }) => {
const response = await client
.post(route('PostsController.store'))
.field('title', 'Hello world')
.field('content', 'This is the first blog post')
.attach('cover_image', Application.makePath('sample.jpg'))
response.assertStatus(201)
response.assertBodyContains({
title: 'Hello world',
content: 'This is the first blog post'
})
})
import { test } from '@japa/runner'
import Mail from '@ioc:Adonis/Core/Mail'
test('create user account', async ({ client, assert }) => {
const mailer = Mail.fake()
// Make request to create a new user account
await client.post('/register')
assert.exists(mailer.find({
to: [{ address: 'user@example.com' }],
subject: 'Welcome to AdonisJS!'
}))
Mail.restore()
})
import { test } from '@japa/runner'
import Database from '@ioc:Adonis/Core/Database'
test.group((group) => {
group.each.setup(async () => {
// Using hooks to wrap all database queries inside
// transactions and performing rollback after each
// test
await Database.beginGlobalTransaction()
return () => Database.rollbackGlobalTransaction()
})
test('create user with email', () => {
// test receives empty database
})
test('create user with username', () => {
// test receives empty database
})
})
Adocasts has a massive collection of free screencasts covering everything related to AdonisJS and the ecosystem around it. Start watching now
Everything else you might need