Let's Learn AdonisJS 6
In this series, we'll learn AdonisJS 6 step-by-step in a beginner-friendly way. Covering topics like routing, controllers, services, EdgeJS, Lucid ORM, forms, filtering, authentication, etc.
Module 1 › Introduction (5 lessons)
Introducing AdonisJS
In this lesson, we'll introduce AdonisJS by giving a brief overview of what it is and what it offers. We'll also talk about some of its first-party and framework-agnostic packages.
What We'll Need Before We Begin
In this lesson, we'll talk about some prerequisites to AdonisJS and this series. These include installing NodeJS, VS Code, a database environment, and Redis.
Creating A New AdonisJS 6 Project
In this lesson, we'll create our first AdonisJS 6 project and learn how we can boot it up and open it within VS Code.
Project Structure
In this lesson, we'll learn how AdonisJS uses our project to boot up and which folders and files within our project matter as we get started with learning AdonisJS 6
VS Code Extensions and Configuration
In this lesson, we'll install three extensions for VS Code from the AdonisJS Core Team to make our lives easier as we build applications. We'll also configure Prettier and ESLint with auto-formatting and lint fixing on save.
Module 2 › Fundamentals (18 lessons)
Routes and How To Create Them
In this lesson, we'll learn how to define routes within AdonisJS and how those routes work.
Rendering a View for a Route
In this lesson, we'll learn how we can use the EdgeJS Template Engine to render HTML views and send them back as the response for our routes. We'll also see how we can pass dynamic data into our views from our route handler.
Linking Between Routes
In this lesson, we'll learn how we can link between the routes we have defined in our application. We'll also learn about the importance of HTTP Method verbs and resources to standardize our route definitions.
Loading A Movie Using Route Parameters
In this lesson, we'll learn how we can reuse a route definition using route parameters to show any item we have for our movie resource.
Validating Route Parameters
In this lesson, we'll learn how we can return a 404 Not Found exception when someone tries to view a movie that doesn't exist. We'll then learn how we can validate our route parameters using Regular Expressions or matchers.
Vite and Our Assets
In this lesson, we'll learn how Vite is integrating into our EdgeJS views to serve our JavaScript and CSS files.
Setting Up Tailwind CSS
In this lesson, we'll learn how to install and configure PostCSS and Tailwind CSS within our AdonisJS 6 project using Vite.
Reading and Supporting Markdown Content
In this lesson, we'll learn how we can support Markdown content by switching our movies from HTML to Markdown. To do this, we'll make use of the DimerApp Markdown package.
Listing Movies from their Markdown Files
In this lesson, we'll learn how we can list movies and their details directly from our movies directory using a YAML-based declaration called frontmatter.
Extracting Reusable Code with Services
In this lesson, we'll learn about services and how we can use them to extract reusable code in a way that makes it super simple to use throughout your project.
Cleaning Up Routes with Controllers
In this lesson, we'll learn what controllers are and how they can be used to drastically simplify our route definitions by allowing us to move our route handlers off the route definition and into the controller.
Defining A Structure for our Movie using Models
In this lesson, we'll introduce the concept of models by using one to define the properties our movies should contain. We'll then stub some methods that will mock calls we'll later be able to use to load data from our database.
Singleton Services and the Idea of Caching
In this lesson, we'll learn about singleton services and how to use them as a store to hold temporary information throughout our server's life by building a simple in-memory caching service.
Environment Variables and their Validation
In this lesson, we'll learn how we can securely store sensitive and environment-based variables using our .env file. We'll also learn how AdonisJS adds type-safety to these variables using our env.ts file as validation.
Improved Caching with Redis
In this lesson, we'll install and configure the AdonisJS Redis package. We'll then swap out our singleton in-memory cache service with a Redis cache implementation.
Deleting Items and Flushing our Redis Cache
Not everyone is perfect, and one day you'll accidentally cache bad data and need a way to quickly clear it out. In this lesson, we'll learn how we can create two routes to clear a single Redis key or flush the entire database.
Quick Start Apps with Custom Starter Kits
In this lesson, we'll take a look at AdonisJS' bring your own kit feature that allows us to use Git repositories as starter kits when creating a new AdonisJS application.
Easy Imports with NodeJS Subpath Imports
In this lesson, we'll learn about NodeJs Subpath Imports and how AdonisJS leverages them to help simplify our import paths throughout our application.
Module 3 › Building Views with EdgeJS (11 lessons)
EdgeJS Templating Basics
In this lesson, we'll learn the basics of AdonisJS's homegrown template engine EdgeJS. We'll cover interpolation, conditional statements, looping, variables, state, and more!
HTML Attribute and Class Utilities
In this lesson, we'll take a look at a few powerful utilities provided by EdgeJS that make working with attributes and conditional classes a breeze.
Making A Reusable Movie Card Component
In this lesson, we'll learn how we can make a movie card component with EdgeJS that we can define once and easily use throughout our markup.
Component Tags, State, and Props
In this lesson, we'll learn how to use EdgeJS components within AdonisJS as direct tags. We'll also learn about our component's state and props
Use Slots To Make A Button Component
In this lesson, we'll learn about EdgeJS component slots by making a versatile button component that can gracefully handle both links and button types.
Extracting A Layout Component
In this lesson, we'll learn how we can create EdgeJS layouts using components so that we don't have to redefine or HTML structure for every page in our application.
State vs Share Data Flow
In this lesson, we'll learn about the difference between passing information directly into EdgeJS' state and sharing information with EdgeJS.
Share vs Global Data Flow
In this lesson, we'll compare the difference between sharing information with an EdgeJS instance and defining a Global within EdgeJS.
Form Basics and CSRF Protection
In this lesson, we'll cover the basics of working with HTML forms in AdonisJS and how they incorporate Cross-Site Request Forgery (CSRF) protection via AdonisJS Shield.
HTTP Method Spoofing HTML Forms
In this lesson, we'll learn how we can enable HTTP Method Spoofing to allow AdonisJS to spoof intended HTTP Verbs for basic HTML form POST requests.
Easy SVG Icons with Edge Iconify
In this lesson, we'll learn how we can install and use the edge-iconify package giving us super easy access within our EdgeJS files to any of the SVG icon packages available through Iconify.
Module 4 › Database and Lucid ORM Basics (18 lessons)
Configuring Lucid and our Database Connection
In this lesson, we'll learn how we can configure Lucid to use a different driver other than SQLite; PostgreSQL is shown but MySQL and MSSQL are much the same. Then, we'll set up our connection details so that we can successfully connect to our database.
Understanding our Database Schema
In this lesson, we'll walk through how to understand a database schema diagram. We'll then discuss the schema we'll be working with throughout this series; describing the tables, columns, data types, and relationships.
Introducing and Defining Database Migrations
In this lesson, we'll introduce database migrations. We'll learn what they are, why they're great to have, and how we can create and use them to define our database tables and their columns.
The Flow of Migrations
In this lesson, we'll learn about the various migration-based commands made available by the Ace CLI and how they interact with our migration files. We'll use these commands to run, rollback, and refresh our migrations against our database.
Introducing Lucid Models
In this lesson, we'll introduce models using the Lucid ORM. We'll learn how we can map database columns to our model properties and specify special behavior for our date time columns.
Defining Our Models
In this lesson, we'll walk through the process of defining all our database tables and columns as models and properties within our application.
The Basics of CRUD
In this lesson, we'll walk through the basics of creating, reading, updating, and deleting (CRUD) data from our database using our Lucid Models.
Defining Required Data with Seeders
Our database will have specific, non-changing, roles and movie statuses. In this lesson, we'll learn how we can quickly and easily create these records inside of our database using seeders.
Stubbing Fake Data with Model Factories
In this lesson, we'll learn how we can quickly and easily bulk-create dummy/fake data within our database for each of our Lucid Models using Model Factories
Querying Our Movies with the Query Builder
In this lesson, we'll introduce both the database and model query builder. We'll learn the differences between the two and the basics of how to use them.
Unmapped and Computed Model Properties
In this lesson, we'll learn how to add unmapped and computed properties to our Lucid Models. We'll discuss the differences between a model column, unmapped property, and a computed property.
Altering Tables with Migrations
In this lesson, we'll learn how to alter our database tables using migrations both while in development, where we can delete our data, and once our data has already hit production where we need to persist all data.
Adding A Profile Model, Migration, Factory, and Controller
Uh oh, a new requirement has come in and now we also need to account for user profiles! In this lesson, we'll learn how we can easily create a new model, migration, factory, and controller for an entity in one fell swoop!
SQL Parameters and Injection Protection
In this lesson, we'll learn about SQL Parameters, also called query bindings, and how using them helps safeguard our database from malicious attacks attempting to perform SQL Injection.
Reusable Query Statements with Model Query Scopes
In this lesson, we'll learn about Model Query Scopes and how we can use them to create easily reusable query statements that we can apply using the Model Query Builder.
Tapping into Model Factory States
In this lesson, we'll dive a little bit deeper into Model Factories by introducing factory states. We'll also learn how we can use the tap method to alter a factory result prior to it persisting into the database
Querying Recently Released and Coming Soon Movies
In this lesson, we'll learn how to use the Model Query Builder to query our movies that have been recently released. We'll then do a separate query to get movies that are coming soon.
Generating A Unique Movie Slug With Model Hooks
In this lesson, we'll learn how we can use Model Hooks to generate a unique URL-safe slug based on the movie's title.
Module 5 › Lucid ORM Relationships (14 lessons)
Defining One to One Relationships Within Lucid Models
In this lesson, we'll learn how to define one-to-one relationships within our Lucid Models. We'll learn about the belongs to and has one decorators, their options, and types that make this possible.
Model Factory Relationships
In this lesson, we'll learn how to use relationships with our Model Factories; easing our capabilities to quickly generate fake data with relationships.
Querying Relationships and Eager Vs Lazy Loading
In this lesson, we'll learn how we can query our relationships using our Lucid Models. We'll then learn what the difference is between eagerly loading a relationship (load) and lazily loading a relationship (preload).
Cascading and Deleting Model Relationships
In this lesson, we'll learn how to account for foreign key constraints when deleting relationships using our Lucid Models. We'll then learn how we can automatically cascade deletions through to relationships.
Defining One to Many Relationships with Lucid Models
In this lesson, we'll learn how to define one-to-many and many-to-one relationships using Lucid Models. We'll also learn how we can specify the columns that should be used for a relationship, allowing us to use one model for multiple relationships.
Seeding Movies with One to Many Model Factory Relationships
In this lesson, we'll learn how we can use Model Factory Relationships to create a pool of cineasts to bind to our movies. This will create cineasts bound to many movies as a writer, director, or both.
Listing A Director's Movies with Relationship Existence Queries
In this lesson, we'll learn how we can perform a relationship existence check to grab a list of our cineasts who have directed one or more movies. We'll then create a show page for that director, listing the movies that they directed.
Listing and Counting a Writer's Movies
In this lesson, we'll learn how we can perform multiple different relationship counts with the same relationship using the Model Query Builder. We'll count our writer's total number of released and not-released movies.
Using Eager and Lazy Loading to Load A Movie's Writer and Director
In this lesson, we'll learn how we can use eager loading to preload our writer and director onto our movie's details. We'll then, learn how we can load our writer and director onto our movie's details using lazy loading.
Defining Many-To-Many Relationships and Pivot Columns
In this lesson, we'll learn how you can define many-to-many relationships within your Lucid ORM Models. We'll also discuss the relationship options, and how you can automatically include pivot table data with all queries.
Many-To-Many Model Factory Relationships
In this lesson, we'll learn how we can define and use many-to-many relationships with Model Factories, including how we can define pivot table data when creating our fake records.
A Deep Dive Into Relationship CRUD with Models
In this lesson, we'll take a deep look at how we can perform CRUD operations with one-to-one, one-to-many, many-to-one, and many-to-many relationships using our Lucid Models.
How To Create Factory Relationships from a Pool of Data
In this lesson, we'll learn how we can refactor our fake data seeder to allow us to assign cast members and crew members to our movies via our many-to-many relationships from a single pool of cineast records.
How To Query, Sort, and Filter by Pivot Table Data
In this lesson, we'll learn how we can query pivot table data. We'll then learn how we can also sort and filter our results by those pivot table columns as well.
Module 6 › Working With Forms (7 lessons)
Accepting Form Data
In this lesson, we'll take a look at how we can create a register form and accept data from that form within our route handler.
Validating Form Data with VineJS
In this lesson, we'll learn how to validate form data using AdonisJS homegrown validation library, VineJS. With VineJS we can easily ensure our request body consists of properties we need, in the types we need them, with valid values.
Displaying Validation Errors and Validating from our Request
In this lesson, we'll learn how we can display feedback for invalid fields noted by errors from our VineJS validators. We'll also see how we can validate directly from our request using request data.
Reusing Old Form Values After A Validation Error
In this lesson, we'll learn how we can easily repopulate our form input values with their previously submitted values when our VineJS validator finds and sends back an error.
Creating An EdgeJS Form Input Component
In this lesson, we'll create a form input component with EdgeJS to simplify adding inputs throughout our application and to extract away old value and validation error logic.
Creating A Login Form and Validator
In this lesson, we'll apply what we've learned to create a login page as well as a validator for our login form.
How To Create A Custom VineJS Validation Rule
In this lesson, we'll learn how to make a custom validation rule with VineJS that requires a value to be unique for the provided table and column. We'll learn how we can register this rule for both strings and number types.
Module 7 › Authentication & Middleware (7 lessons)
The Flow of Middleware
In this lesson, we'll learn about the middleware that comes preinstalled within AdonisJS and the flow of this middleware during an HTTP Request at both a global and route-specific scale.
Authenticating A Newly Registered User
In this lesson, we'll learn how we can authenticate, or login, a new user who just registered with our application. We'll then see how we can populate the authenticated user's details on subsequent requests.
Checking For and Populating an Authenticated User
In this lesson, we'll create a silent auth middleware that will automatically check whether a request has an authenticated user attached to it, and populate that user's details if one is found.
Logging Out An Authenticated User
In this lesson, we'll learn how to logout an authenticated user using a POST request with CSRF protection.
Logging In An Existing User
In this lesson, we'll learn how we can login an existing user using just their email and password. We'll discuss how the AuthFinder mixin protects us from timing attacks, and how we can use it to verify the accuracy of a user's password.
Remembering A User's Authenticated Session
In this lesson, we'll learn how we can use AdonisJS' Remember Me Tokens feature to allow a user to specify they'd like their authentication state to be remembered for a long time across sessions.
Protecting Routes with Auth, Guest, and Admin Middleware
In this lesson, we'll learn about the auth and guest middleware included when we created our AdonisJS 6 project. Then, we'll create our own named middleware that will allow us to restrict page access to only users with the admin role.
Module 8 › Filtering and Paginating Queries (2 lessons)
Creating A Movie List Page
In this lesson, we'll create a page to list all of our movies. Since we have a lot of movies, in this module, we'll focus on adding filters and pagination to this list.
Filtering A Query By Pattern Likeness
In this lesson, we'll learn how to add a pattern filter to our movies.index page that will allow us to filter our movies list by title using a case-insensitive pattern search.