DEV Community

Cover image for Introducing AdonisJS - Part 3
Aman Virk
Aman Virk

Posted on

Introducing AdonisJS - Part 3

We got up and running with a new application in the previous post. In this post, lets will take a step ahead and learn about some of the key concepts of AdonisJS.

I think it is very important to know about your tools before you starting using them. So let's spend another post without writing any code.

Ace commands

In this last post, we start the development server by running the node ace serve --watch command, so let's start by breaking it down

  • node is the node binary installed on your computer.
  • ace is a Javascript file in the root of your project. We removed the .js extension, coz it is easier to type node ace over node ace.js
  • After the ace keyword is the command name and the arguments/flags required by the command.

Why the hell did not create a command-line binary that can be installed globally?
You might be thinking, why there isn't a command-line binary that can be installed globally and then use it as follows

adonis serve --watch
adonis make:controller <Name>

# and so on
Enter fullscreen mode Exit fullscreen mode

The answer is, you cannot have project-specific commands with a global binary and a backend server usually needs project-specific commands. For example:

  • A command to run queue workers
  • A command to migrate the database
  • Or maybe if you play fancy, then command to set up the project by creating an admin user and seeding data.

AdonisJS is not the first one to do this. Django has file. Laravel has an artisan file. However, when looking at the Node.js landscape, the concept feels a bit alien, hence requires explanation.

Directory structure

The default project structure of AdonisJS contains a bunch of files and folders by default. You may get overwhelmed at first by looking at the directory structure, especially when you are new to the framework. So, let's go ahead and talk about the important files and folders.

The .adonisrc.json file

The .adonisrc.json is one of the most important files as it is responsible for configuring your project and workspace.

Even though the file contains the bare minimum config by default. It allows overriding almost every convention used by the framework.

Run the following command to see the complete set of available options and their pre-configured defaults.

node ace dump:rcfile
Enter fullscreen mode Exit fullscreen mode

About Fx fx is a commandline utility to make the JSON output interactive

The server.ts file

The server.ts file is the entry point of your HTTP server. Running this file directly will boot your application and then starts the HTTP server.

This is a file you will run on your production server after it gets compiled to Javascript.

The app directory

The app directory contains most of your application code. HTTP controllers, middleware, models, services, and much more live inside this folder.

The config directory

The config directory is dedicated to storing all the configuration required by your app. By default, we create a handful of well-documented configuration files that are used by the framework core and first-party packages.

As your application will grow, you can also use this directory to store additional configuration files.

The start directory

The start directory contains all the files that you want to load only once during the application boot phase. We also call them preloaded files.

There is no technical limitation or hard coded rule that files inside this directory will be loaded only once. But more of a convention we follow to communicate a clear intent.

The resources directory

The resources directory is dedicated to storing edge templates inside a subdirectory called views.

It is also recommended to use this directory also for storing un-compiled frontend assets like SASS files or frontend JavaScript. After compiling the frontend assets, they must be moved to the public directory, since the resources directory is not exposed to the internet.

The public directory

The public directory is exposed to the internet and all the files can be accessed by their path.

Given the following files inside the public folder

├── app.js
├── logo.png
└── style.css
Enter fullscreen mode Exit fullscreen mode

You can access them as


The database directory

AdonisJS recommends storing the database schema migrations, seeders and factories inside the database directory.

We keep them outside of the app directory because they are usually not part of the runtime code and get executed as a separate step during development or pre-deployment.

Typescript first

AdonisJS is a Typescript first framework. Beyond using it as a marketing term, we have invested a lot in building first-class primitives for a better typescript experience. In a nutshell, it includes

If you find value in adopting Typescript, then you can also bet on AdonisJS, as we are always looking for ways to fully embrace typescript.

Fully featured, not full-stack

AdonisJS is a fully featured and not a full-stack framework. The term full-stack is generally used when someone or something is equipped with both the web frontend and the backend.

AdonisJS has zero opinions on how you create your frontend.

  • Want to server render HTML? We got your back with a pretty decent template engine.
  • Want to use React, Vue, or Svelte? Use AdonisJS to create a JSON API and then develop your frontend as an independent app consuming the API
  • Want to develop a Mobile app? Again, consume the same API and build a native mobile app

A lot of us think that if a framework is not full-stack, then it is a micro-framework. For god sake, there are a gazillion things that we do and should do on the backend. For example:

  • Managing the data layer wisely. It includes sanitizing data, hashing/encrypting values with secret keys, and a much more
  • User authentication and authorization
  • Sending emails
  • Queue jobs
  • Validations
  • Managing file uploads
  • Interacting with 3rd party APIs. No, you cannot connect with 3rd party APIs securely from your frontend app.
  • Payments & Subscriptions

A fully-featured framework like AdonisJS makes all this easy.

Top comments (8)

dawidow profile image
Dawid Owczarz • Edited

User authentication and authorization - For the authorization we have to wait because I was looking for a package for a couple of days, and I found nothing. I hope you upgrade adonis-guard package soon. That’s the only one package that I missed in the framework. Good job anyway.

kswope profile image
Kevin Swope • Edited

you cannot have project-specific commands with a global binary

make, rake, etc?

What am I not understanding?

amanvirk1 profile image
Aman Virk • Edited

They are tasks runner and not command line apps that ships with their own set of commands. Plus there are many other subtle things. For example:

The task code itself doesn't rely on (or import) anything from rake itself. Whereas with ace commands, your very first import is a BaseCommand from ace itself

kswope profile image
Kevin Swope

So the rails command is a task runner too?

rails console
rails server
rails test
rails generate
rails db:migrate
rails db:create
rails routes
rails dbconsole
rails new app_name
Enter fullscreen mode Exit fullscreen mode

None of those commands require ruby be called directly on the command line. What is ace doing that I'm missing?

Thread Thread
amanvirk1 profile image
Aman Virk

Your comments feels like "lets see if I can begin a fight". I am more than happy, if you can suggest an alternative way to have project specific commands by installing a global binary.

Once you suggest an implementation. We both can together go through the merits and de-merits of your implementation and mine and happy to choose yours if it stands out :)

Thread Thread
kswope profile image
Kevin Swope

You wrote in bold text "you cannot have project-specific commands with a global binary".

In other words: it is impossible to do this

Being a rails developer I'd been running the "rails" command for years so I was just wondering why this statement was so definitive and I was wondering if ace was doing something rails can't.

Being a developer in general I was wondering why a global node script couldn't just do a cwd and go from there.

uf4no profile image

Thanks for sharing so detailed articles. Looking forward for more of these!