Upgrade to Pro — share decks privately, control downloads, hide ads and more …

De zéro à votre première application web avec A...

De zéro à votre première application web avec AdonisJS

Avatar for Jaime Arias Almeida

Jaime Arias Almeida

June 24, 2026

More Decks by Jaime Arias Almeida

Other Decks in Programming

Transcript

  1. A T U TO R I E L De zéro

    à votre première application web avec AdonisJS AdonisJS Jaime Arias CNRS, Laboratoire d'Informatique de Paris Nord (LIPN) 23 juin 2026 Journées nationales du DEVeloppement logiciel (JDEV 2026) Code source du tutoriel github.com/himito/tutorial-adonisjs 1 / 59
  2. 0.1 WHO I AM Jaime Arias CNRS Research Engineer ·

    LIPN Leads the dev team at LIPN Chargé de Mission at INS2I « Software » Member · Collège Codes Sources et Logiciels Ambassador · Software Heritage [email protected] www.jaime-arias.fr A AdonisJS 7 2 / 59
  3. 0.2 ORIENTATION What we'll build Backend only — a REST

    API, built test-first. DEMAIN Le front-end sera construit dans le tutoriel « Vue.js : Développer des interfaces utilisateur réactives et modulaires » A AdonisJS 7 3 / 59
  4. 0.3 ORIENTATION The roadmap After setup we learn the test-first

    rhythm, lay the database groundwork, then build every endpoint by leading with a test. A AdonisJS 7 4 / 59
  5. 0.4 ORIENTATION What is AdonisJS? A batteries-included, TypeScript-first backend framework

    — the "Laravel of Node". The pieces are built by one team to fit together. A AdonisJS 7 5 / 59
  6. 0.5 ORIENTATION History & version 7 Created by Harminder Virk

    around 2016 to end the "assemble your stack from scratch" era in Node. Inspired by Laravel and Rails. v7 highlights: end-to-end type safety, a new migrations-first Lucid that generates your model schema, zero-config OpenTelemetry, and a reworked auth starter kit. A AdonisJS 7 6 / 59
  7. 0.6 ORIENTATION AdonisJS in the ecosystem Back-end frameworks by usage

    — Express still dominates, while AdonisJS is a smaller, dedicated player. Express 80% NestJS 32% Fastify 20% Strapi 15% Hono 15% tRPC 12% Koa 11% Nitro 9% ElysiaJS 5% Hapi 4% AdonisJS 3% Directus 3% Source : State of JS 2025 — Back-end Frameworks · usage (% des répondants ayant déjà utilisé) A AdonisJS 7 7 / 59
  8. MODULE 00 00 00 Tooling Set up your editor first

    — so AdonisJS, types and lint errors guide you the moment you start typing. 9 / 59
  9. 0.8 TOOLING Set up VS Code A handful of extensions

    turn the editor into a guide — autocomplete for AdonisJS, plus the lint/format/error trio every Node.js project wants. AdonisJS Node.js essentials A AdonisJS 7 10 / 59
  10. MODULE 01 01 01 Project setup Scaffold the API with

    a starter kit and learn how a request flows through the app. 11 / 59
  11. 1.1 CREATING THE PROJECT Scaffold from a starter kit Starter

    kits are pre-configured templates. We pick --kit=api — a headless JSON backend with the database and token auth already wired up. Open http://localhost:3333 — the backend returns: Official starter kits api NOTRE CHOIX Backend + empty frontend monorepo, end-to-end type-safe. hypermedia Server-rendered HTML with Edge templates & Alpine.js. react · vue Fullstack via Inertia.js — server-rendered or SPA. Community: slim (minimal) · mcp (MCP server). A AdonisJS 7 12 / 59
  12. 1.2 PROJECT STRUCTURE Where things live todo-api/ ├── app/ │

    ├── controllers/ # request handlers │ ├── models/ # one per table │ ├── middleware/ # HTTP middleware │ └── validators/ # VineJS schemas ├── bin/ # boot entry points ├── config/ # database, auth, hash… ├── database/ │ ├── migrations/ # schema changes │ └── schema.ts # generated models ├── providers/ # service providers ├── start/ # routes.ts, kernel.ts ├── tests/ # unit, functional (Japa) └── tmp/ # logs, uploads (git-ignored) Subpath aliases replace fragile relative paths. Configured under the "imports" field in package.json . A AdonisJS 7 13 / 59
  13. 1.3 REQUEST LIFECYCLE How a request flows Client PostgreSQL Request

    POST /todos + token Response 200 · JSON SQL The request enters the app, flows through the pipeline to the database, and the controller's return value flows back out as the JSON response. A AdonisJS 7 14 / 59
  14. MODULE 02 02 02 Working test-first Before building any feature,

    we agree on the rhythm: describe behaviour as a test, then build to green. 15 / 59
  15. 2.1 THE TDD RHYTHM Describe → make it pass →

    tidy Instead of testing afterwards, we lead with a test that states what an endpoint should do — then write just enough code to satisfy it. We keep it lighter than dogmatic TDD — not a failing test for every line, but each real feature leads with a test that states the goal. A AdonisJS 7 16 / 59
  16. 2.2 THE TEST RUNNER Meet Japa The official AdonisJS testing

    framework — a fast, TypeScript-native runner that's already wired into the API kit. No Jest, no setup. A AdonisJS 7 17 / 59
  17. 2.3 YOUR FIRST TEST Prove the harness works Before any

    feature, confirm the harness runs: generate a test with ace, then send a real HTTP request to the health route at / — no database needed. That green line is the rhythm we repeat for every feature. A AdonisJS 7 18 / 59
  18. MODULE 03 03 03 Database groundwork The plumbing endpoints need:

    a connection, a table and a model. Once it's here, every endpoint starts with a test. 19 / 59
  19. 3.1 THE ORM Meet Lucid The official AdonisJS ORM —

    a TypeScript-first Active Record with a migrations-first workflow that generates your model schema for you. A AdonisJS 7 20 / 59
  20. 3.2 CONNECTING TO THE DATABASE Point Lucid at a database

    SQLite needs zero setup — just npm i better-sqlite3 . The whole database is a single file; swap DB_CONNECTION later for Postgres in production. A AdonisJS 7 21 / 59
  21. 3.3 THE DATA MODEL The database schema Two tables, one

    relationship: a user has many todos, and each todo belongs to a user. 1 ──< ∞ hasMany belongsTo todos.user_id references users.id — delete a user and their todos cascade away. A AdonisJS 7 22 / 59
  22. 3.4 MIGRATIONS Version control for your schema A migration describes

    a database change in code — an up() to apply it and a down() to undo it. The -m flag scaffolds the model and its migration together. A AdonisJS 7 23 / 59
  23. 3.5 SCHEMA GENERATION What makes Lucid 7 special The database

    is the single source of truth. You never declare columns twice. A AdonisJS 7 24 / 59
  24. 3.6 SCHEMA GENERATION The generated schema After a migration, Lucid

    writes one typed class per table into database/schema.ts . Your models extend these — never the other way around. serializeAs: null hides the password from JSON, and userId is the foreign key to users . A AdonisJS 7 25 / 59
  25. 3.7 THE MODEL Where relationships live Columns are inherited from

    the generated schema — the model is where your code lives: the two sides of the relationship, plus hooks and computed properties. A AdonisJS 7 26 / 59
  26. 3.8 CRUD WITH LUCID Create · Read · Update ·

    Delete Active Record: the class queries the table, each instance is a row. Return one from a controller and it serializes to JSON automatically. A AdonisJS 7 27 / 59
  27. MODULE 04 04 04 Endpoints, test-first Now the rhythm kicks

    in: describe the todos endpoints with a test, watch it fail, then build the route and controller to green. 28 / 59
  28. 4.1 START WITH A TEST Describe it first Describe the

    behaviour as a test, then run it and watch it fail. Generate the test file Then run the suite It fails with a 404 — there's no route yet. A AdonisJS 7 29 / 59
  29. 4.2 MAKE IT GREEN The smallest code that passes Write

    just enough to satisfy the test — one action, one route. Scaffold it, implement one action Add one route Green! Now build out the rest the same way. A AdonisJS 7 30 / 59
  30. 4.3 DESCRIBE THE REST FIRST Four more endpoints, four more

    tests Same rhythm: write the tests for create, show, update & delete — and watch them fail before writing a line of logic. Run the suite Four reds — now build the controller actions that turn them green. A AdonisJS 7 31 / 59
  31. 4.4 THE OTHER ACTIONS Now build out the rest Scaffold

    the full resource The --resource flag scaffolds all five REST actions. Each gets an HttpContext — request, response, params, auth, bouncer — in one object. Destructure what you need. A AdonisJS 7 32 / 59
  32. 4.5 SPEAKING HTTP A method for every status code The

    response object has a named helper for each status — readable, and it sets the code for you. Success · 2xx response.ok() 200 OK response.created() 201 Created response.noContent() 204 No Content Client & server errors · 4xx / 5xx response.badRequest() 400 Bad Request response.unauthorized() 401 Unauthorized response.forbidden() 403 Forbidden response.notFound() 404 Not Found response.unprocessableEntity() 422 Invalid A thrown findOrFail() or a failed validator becomes 404 / 422 automatically. A AdonisJS 7 33 / 59
  33. 4.6 ROUTING Every verb — plus names & groups A

    helper for every HTTP verb; whatever the handler returns becomes JSON. Routes can be named for easy URL building and grouped to share a prefix or middleware. A helper for every HTTP verb Named routes (aliases) Groups — shared prefix & middleware A AdonisJS 7 34 / 59
  34. 4.7 WIRE IT UP Five routes in one line →

    green A AdonisJS 7 35 / 59
  35. 4.8 TEST DATA · FACTORIES Stop hand-writing test data Model

    factories generate realistic records on demand — so your tests read intent, not boilerplate. Define it once Use it everywhere Backed by Faker for fake titles, emails, dates — one line replaces a wall of create({ … }) . A AdonisJS 7 36 / 59
  36. 4.9 TEST DATA · IN ACTION Test the list with

    several items Seed a few rows with the factory, then assert the endpoint returns them all. Run it createMany(3) fills the table; res.body() is the parsed JSON — assert on its length and contents. A AdonisJS 7 37 / 59
  37. MODULE 05 05 05 Validation, test-first State the rule as

    a test — a bad title returns a 422 — then reach for VineJS to make it true. 38 / 59
  38. 5.1 VALIDATION Meet VineJS The official AdonisJS validation library —

    one of the fastest in the Node ecosystem, and the gatekeeper that stops bad input before it reaches your models. A AdonisJS 7 39 / 59
  39. 5.2 TEST THE RULE FIRST A 2-character title is a

    422 Run it — red It fails today — the todo saves with a 200 . To make it pass, we add a validator in front of the controller. A AdonisJS 7 40 / 59
  40. 5.3 MAKE IT GREEN · VINEJS Describe the rules Generate

    it Returns a fully typed, clean object. The test goes green. A AdonisJS 7 41 / 59
  41. MODULE 06 06 06 Auth & authorization Who are you?

    — and what may you do? We lead with a 401 test, then a 403 test, building tokens and policies to green. 42 / 59
  42. 6.1 AUTHENTICATION Three built-in guards A guard is a strategy

    for authenticating requests. AdonisJS ships three — pick per app; we use access tokens for our API. All three share one API — auth.use('api').authenticate() — so swapping strategies barely touches your code. A AdonisJS 7 43 / 59
  43. 6.2 AUTHENTICATION What is an opaque token? A long, random

    string that carries no data of its own — unlike a JWT. The server stores only its hash and looks it up on every request. If the hash matches, the request runs as that user. If it's missing or wrong, it's a 401 — and because only the hash is stored, a token can be revoked instantly. A AdonisJS 7 44 / 59
  44. 6.3 AUTHENTICATION Configuring auth It all comes together in one

    file — a named guard that uses tokens and points at your User model. What each piece does default: 'api' The guard used whenever you don't name one explicitly. tokensGuard Reads the Authorization: Bearer header and verifies the token. tokensUserProvider Resolves the user from the User model and its accessTokens . A AdonisJS 7 45 / 59
  45. 6.4 THE USER MODEL Ships with the starter kit It

    composes the generated UserSchema with the withAuthFinder mixin — which hashes passwords and adds verifyCredentials . We add the todos relationship. A AdonisJS 7 46 / 59
  46. 6.5 REGISTER & LOGIN Issue a token The controller Two

    public routes No auth middleware — reachable before you have a token. token.value!.release() reveals the plain string — the only moment you can read it. A AdonisJS 7 47 / 59
  47. 6.6 REGISTER & LOGIN Test: register returns a token Scaffold

    with node ace make:test auth --suite=functional , then describe the endpoint. A AdonisJS 7 48 / 59
  48. 6.7 REGISTER & LOGIN Test: login returns a token Seed

    with a factory UserFactory.merge({ password }) creates a real user so we can log in as them. Focus one test .pin() runs only this test — handy while iterating on a single endpoint. A AdonisJS 7 49 / 59
  49. 6.8 PROTECTING ROUTES Test the lock, then build it .loginAs(user)

    authenticates the request as that user — no real login round-trip needed. Inside, auth.getUserOrFail() scopes todos to that user. A AdonisJS 7 50 / 59
  50. 6.9 AUTHORIZATION Authentication vs authorization Deleting someone else's todo while

    logged in is a 403 , not a 401 . APIs need both layers. A AdonisJS 7 51 / 59
  51. 6.10 OWNER-ONLY WITH BOUNCER Test ownership first Two red tests

    pin the rule: the owner can delete (204), an intruder cannot (403). A AdonisJS 7 52 / 59
  52. 6.11 OWNER-ONLY WITH BOUNCER Meet Bouncer AdonisJS's official authorization layer.

    You write abilities (inline checks) and policies (a class per model), then ask bouncer "can this user do X?" — it answers true / false or throws a 403 . Install & configure One command wires the provider, the initialize_bouncer middleware, and the abilities / policies folders. Two ways to authorize A AdonisJS 7 53 / 59
  53. 6.12 OWNER-ONLY WITH BOUNCER Write the policy Generate a class

    for the resource, then encode the rule. Each method returns a boolean: true allows, false denies. Generate it Bouncer auto-discovers policies, so the class is ready to use immediately. Encode the rule A AdonisJS 7 54 / 59
  54. 6.13 OWNER-ONLY WITH BOUNCER Enforce it in the controller Call

    bouncer before the destructive action. If the policy returns false , it throws a clean 403 and the row is never touched. A AdonisJS 7 55 / 59
  55. MODULE 07 07 07 Wrap-up From an empty folder to

    an authenticated REST API — with a green suite that grew alongside it. 56 / 59
  56. 7.1 THE FINISHED API Every feature is green Because we

    led with tests, the suite tells the whole story of the API — auth, the happy path, validation and authorization. A AdonisJS 7 57 / 59
  57. 7.2 WHERE TO GO NEXT Take it further Pagination &

    filtering — add .paginate(page, limit) (write the test first!) Token abilities — issue read-only tokens with scopes Rate limiting & CORS — both first- party, a few lines each Deploy — node ace build , ship to any Node 24 host A AdonisJS 7 58 / 59
  58. T H AT ' S A W R A P

    You built it test-first. test-first. Routes, controllers, models, validators, guards and policies — each led by a test, all backed by a green suite. docs.adonisjs.com lucid.adonisjs.com 59 / 59