In this tutorial we'll build a simple CRM app utilizing an awesome tech stack consisting of:
- React - React really needs no introduction, since it's the most popular front-end framework around.
- Inertia.js - Inertia allows you to create fully client-side rendered, single-page apps, without much of the complexity that comes with modern SPAs.
- Typescript - A strongly typed superset of ECMAScript.
- AdonisJS - A fully featured web framework focused on productivity and developer ergonomics.
If I were inclined to name things, I might call it the RITA stack.
Prerequisites
- You should have the latest stable version of Node.js installed.
- Some kind of code editor or IDE (if you're not sure, Visual Studio Code is a great option).
Now, let's build this thing...
Scaffolding a New App
Let's create a new Adonis project, by running the following from the terminal:
npm init adonis-ts-app@latest simple-crm
When prompted for the type of application you would like to scaffold select web
:
We'll leave all options as their default values except Configure webpack encore for compiling frontend assets?
which we'll set to true
.
Let's cd
into our project directory and continue.
Install Lucid ORM and Create Our User Model
We will use SQLite and LucidORM to store and retrieve our user data.
To install and set up LucidORM run the following in the terminal:
npm i @adonisjs/lucid
node ace configure @adonisjs/lucid
When prompted for the database driver you would like to use, choose SQLite
.
Next, we will create our users schema.
Create the User Schema Migration
Run the following in your terminal to create the User
schema migration:
node ace make:migration users
We will edit the migration script that was created for us and make a simple user schema consisting of a first name, last name and email:
import BaseSchema from '@ioc:Adonis/Lucid/Schema'
export default class Users extends BaseSchema {
protected tableName = 'users'
public async up() {
this.schema.createTable(this.tableName, (table) => {
table.increments('id').primary()
table.string('first_name').notNullable()
table.string('last_name').notNullable()
table.string('email').unique().notNullable()
table.timestamps(true, true)
})
}
public async down() {
this.schema.dropTable(this.tableName)
}
}
Now, let's run our migration to create the user table:
node ace migration:run
With that out of the way, let's focus on our front end.
Configure Webpack-Encore for Typescript and React
By default Encore
(the asset bundler provided to us by Adonis) is configured for Javascript, but since we want to use the same language throughout our app, let's modify it a bit.
First, let's install ts-loader
and @babel/preset-react
so encore knows how to handle Typescript files and JSX syntax:
npm install ts-loader@^8.0.1 @babel/preset-react --save-dev
Then, let's edit webpack.config.js
by changing the following from:
Encore.addEntry('app', './resources/js/app.js')
To:
Encore.addEntry('app', './resources/js/app.tsx')
Encore.enableTypeScriptLoader()
Encore.enableReactPreset()
Also, let's rename /resources/js/app.js
to /resources/js/app.tsx
to match our previous changes.
Now, let's configure typescript for our client side code. Create a file called /resources/js/tsconfig.json
and paste this minimal config in it:
{
"include": ["**/*"],
"compilerOptions": {
"lib": ["DOM"],
"jsx": "react",
"esModuleInterop": true
}
}
Lastly, let's install react:
npm i react react-dom @types/react @types/react-dom
Now we're ready to install and configure Inertia.js
Install and Configure Inertia Adapter
To install the Inertia adapter for Adonis, run the following command:
npm i @eidellev/inertia-adonisjs
Now let's configure the adapter by running:
node ace configure @eidellev/inertia-adonisjs
When prompted, please select to install the inertia adapter for react.
Setting Up the Client-Side Inertia Adapter
With everything installed, let's set up our root view. Open /resources/views/app.edge
and add this script
tag to the <head>
section:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="/favicon.ico">
<!-- This -->
<script src="{{ asset('assets/app.js') }}" defer></script>
<!-- -->
<title>simple-crm</title>
</head>
<body>
@inertia()
</body>
</html>
Now, let's configure our app's entrypoint. Open resources/js/app.tsx
and replace the code with:
import { InertiaApp } from '@inertiajs/inertia-react'
import React from 'react'
import { render } from 'react-dom'
import '../css/app.css'
const el = document.getElementById('app')
render(
<InertiaApp
// Pass props from the server down to the client app
initialPage={JSON.parse(el.dataset.page)}
// Dynamically load the required page component
resolveComponent={(name) => import(`./Pages/${name}`).then((module) => module.default)}
/>,
el
)
Next, let's add our first page component. Create a new react component in resources/js/Pages/Test.tsx
:
import React from 'react'
const Test = () => <div>hello from inertia</div>
// All pages need to be exported as default
export default Test
Finally, let's configure a route for our new page. Open start/routes.ts
and replace whatever is currently there with:
import Route from '@ioc:Adonis/Core/Route'
Route.get('/test', async ({ inertia }) => {
return inertia.render('Test')
})
Now that we're all set, let's run our app and watch the magic happen:
node ace serve --watch # this will start both adonis and webpack dev server
When you visit http//localhost:3333/test
you should see something like this:
Awesome!
To Be Continued
In the next posts in this series we will continue to flesh out our app and see some of the cool features of both Adonis and Inertia in action.
Top comments (8)
Hi, Lev! Thanks so much for this tutorial! I followed the steps but I got an error when I try to install this: npm install @inertiajs/inertia @inertiajs/inertia-react. it's just me or this doesn't work with new react version? Thanks again! 🙏🏼
Thanks! Can you share the error you are getting?
Thanks for answering! It was something about my React version and I think I found the answer 🤔 github.com/inertiajs/inertia/issue...
Hi, this is a great tutorial, but sadly, I've fallen in love with svelte. Can you make another tutorial that integrates adonis and svelte with inertiajs.. Thanks in advance..
Thank you! In this tutorial I'm focusing a bit more on Inertia and Adonis (I have at least two more blog posts planned).
However, the procedure for using svelte instead of react shouldn't be too different. I'd be happy to give it a shot later on since I'm curious about svelte.
Hi, I've create video tutorial (Indonesian language) on Inertia and Adonis+Svelte - youtube.com/watch?v=D0lzC3Kn9gQ . But I'm still failed to activate typescript (by set strict=true on tsconfig.json). I think there is a problem/error with inertia-svelte library. But there is no problem when I activate typecript when following your article (with adonis+react). I'm not pretty sure about that. Maybe you can help point me the right direction. This is my repo: github.com/danangponorogo/adonisve...
Great guide, was working perfectly until recently, where I loaded my application and I noticed that when trying to load the /assets/app.js, it's enforcing a https protocol on the localhost:8080 port. Which of course doesn't work and thus does not load the app entirely. Any ideas on how to fix this?
would you please share with me how to link between adonisjs inertiajs and svelte?
What next steps should I take after I complete the steps like the capture below?
Making an Inertia Response