Exploring AdonisJS

MMaximilian Schwarzmüller
컴퓨터/소프트웨어창업/스타트업AI/미래기술

Transcript

00:00:00Thank you.
00:00:30Okay. Hi, everybody. Welcome to this stream today about Adonis.js, which should be fun. Should be an interesting framework and library, which I never used before. I always wanted to try it out, so I figured why not today in this stream.
00:01:00Let me just get settled here real quick.
00:01:07So, I hope you're all doing well. Thanks for joining.
00:01:16And let's dive in. Yeah. Hi. Hi, everybody. So, today I want to dive into Adonis and explore it a bit. Just for the fun of it, because Adonis.js is a JavaScript framework that's quite different from the other frameworks.
00:01:38And, of course, we're not in the 2019 anymore. So, you could argue how important are JavaScript frameworks these days, right? The days of the framework wars are over. The days where we had a new framework every day.
00:01:54And today it's all about AI. But because it's all about AI these days, I figured why not have a live stream where we take a look at something that is totally not related to AI.
00:02:08And Adonis is a pretty interesting framework and library. As I mentioned, I never worked with it, but I know it. I have kind of loosely followed it for many, many years.
00:02:20And it is, in the end, Laravel for JavaScript. That is my understanding of it. That is my understanding of Adonis. It's a full-stack framework and it already existed before all the React frameworks became full-stack.
00:02:40So, before we had... I'm not sure if it was released before we had Next.js, but I would say before Next.js got super popular and so on.
00:02:51And, yeah, it comes with lots of interesting stuff built in. And my idea for today is really just to go through this official introduction guide here and take a look at what's inside and play around with it and find out what it is and how it works.
00:03:10So, yeah, I got a comment there about the new computer-based quota on Google AI plans. I think I read something about it. Haven't really had a closer look, so I can't really comment on that.
00:03:24So, whoa, that is quite big. Let's see. What is Adonis? It's a back-and-first type-safe framework. Now, it's back-and-first, but I know that it comes with full-stack capabilities.
00:03:37You can render views with it just as you can with Laravel, if you know that.
00:03:42For building web applications with Node.js and TypeScript provides the core building blocks for writing and maintaining complete backends, eliminating the need for third-party services.
00:03:52Yeah, because as I mentioned here, just like Laravel, it's not just a full-stack framework like Next.js, which essentially gives you the capabilities to render React components on the server.
00:04:06Which is kind of a rough summary, but yeah, that's kind of the main idea behind Next.js, you could say.
00:04:12They have routing and so on, but Adonis, like Laravel, gives you more.
00:04:16It comes with built-in authentication so that you don't need an extra library for that.
00:04:21It comes with built-in support for file uploads, caching, rate limiting, and way more.
00:04:26It comes with its own ORM, so its own object-relational mapping, I think is what it stands for.
00:04:33It's its own wrapper around a SQL database and so on.
00:04:35So pretty powerful, pretty capable.
00:04:38And the idea really is that you only have Adonis.js if you want to build a full-stack application and you don't need too many other dependencies,
00:04:47which of course, especially today with all those supply chain attacks, is quite interesting, having a limited set of dependencies.
00:04:55Obviously, if Adonis gets compromised, you're still in trouble, but it's less extra dependencies you need.
00:05:03And hey, Daki, I'm finishing your famous React course.
00:05:07What do you suggest to learn after plain TypeScript or React plus TypeScript?
00:05:11Yeah, React plus TypeScript is a good idea.
00:05:12Next.js is a good idea.
00:05:14Or you dive into React Native after learning React so that you can build mobile apps with it if you want to.
00:05:20So that will be all reasonable next steps, I think.
00:05:24So without further ado, without going through all that text here, let's dive in.
00:05:28Let's pick our path.
00:05:31You will learn over here.
00:05:33I want to get started, actually.
00:05:36Now, one thing, the three approaches.
00:05:40Adonis.js supports three primary approaches to building your frontend.
00:05:44Okay, so that sounds important.
00:05:47Each approach represents a different way of thinking about the view layer.
00:05:52Hypermedia.
00:05:52Hypermedia applications generate complete HTML pages on the server and send them to the browser.
00:05:57You build your interface using a template engine.
00:06:00And Adonis.js comes with its own template engine, which is Edge.
00:06:05And add interactivity using lightweight JavaScript libraries like Alpine.js.
00:06:10Or HTMX on Poly when needed.
00:06:12And I think I want to use this approach here, actually.
00:06:16You could, however, also use Adonis with React as a frontend using Inertior.js,
00:06:25which I think is from Laravel, from the Laravel world,
00:06:28which kind of is like a bridge between the frontend single-page application
00:06:32and the backend of the full-stake application.
00:06:38And, yeah, you can also just build a REST API, of course, just a backend if you want to.
00:06:46And the same controller, three different returns.
00:06:49Okay, so let's see.
00:06:50We can register a route with the router that comes with Adonis.
00:06:56And the controller's post, so that is the controller here.
00:07:02And in there, we can call viewRender and render a view, which we defined before.
00:07:06And this special syntax here, that is essentially this Edge template language that ships with Adonis.
00:07:16The alternative would be to use Inertia, where we also have our controller.
00:07:20But in the controller, we call render, still on a view, and we can pass some props.
00:07:28Yes, that's props into it.
00:07:30And then we can have our JavaScript, our React code here.
00:07:34And it will be, as I understand it, server-side rendered.
00:07:37And basically, we don't have to fetch data in that React component.
00:07:42That will all be handled for us.
00:07:44So that's nice, too.
00:07:45But I think I'll, well, we'll see what I'll use.
00:07:47One of the two, obviously, I want to build a little full-stack app here.
00:07:50But we'll see.
00:07:51I will probably get started with the Edge template engine and build a good old multi-page application
00:07:57where we render the HTML on the server-side.
00:07:59Because not all applications need React on the client-side.
00:08:03I think that's really important to understand.
00:08:05It depends on what you're building.
00:08:07And not every application needs a super reactive, interactive front-end.
00:08:12If you're building something like a blog, for example, you most likely don't need that.
00:08:16But also for many more complex applications, you might not need it.
00:08:20Let me quickly catch up with the chat.
00:08:22Hi, Max.
00:08:23AI engineering course.
00:08:24Maybe at some point right now, things are changing so quickly that any course I would
00:08:28release on that would be outdated pretty much the moment I release it.
00:08:32So I don't want that.
00:08:32So not today.
00:08:35I will rather create some courses on software fundamentals and stuff like that first.
00:08:39But at some point, I want to, of course, share how I work with AI.
00:08:44But I want to do that at a point where it doesn't change every week, which it does right now.
00:08:48Hi, Max.
00:08:48I know Adonis has been maintained for, I think, more than a decade.
00:08:51Do you think it's a business risk to bet on it, given its relative niche market?
00:08:55Yeah, that is a really good question.
00:08:57So I know it has been maintained for a very long time.
00:09:01I didn't know that it was a decade.
00:09:02But yeah, definitely a long time.
00:09:05And I also don't know how big the team behind Adonis is.
00:09:09I know that it is well-maintained right now.
00:09:13I see a lot of activity on X by the lead maintainer, the owner of the Adonis project.
00:09:20Obviously, there always is a bit of a risk attached to a project that is not used by the entire world, to put it like this.
00:09:30That being said, since it is maintained for such a long period, that kind of proves the dedication of the lead maintainer.
00:09:38But yeah, obviously, something like Next.js, which is backed by Vercel, will very likely, I would say, have a higher guarantee of being maintained for a long time.
00:09:50But you never know, obviously.
00:09:52And Adonis has certain advantages, of course, which Next.js doesn't have.
00:09:57But yeah, definitely a valid concern.
00:10:00Nice that you are live.
00:10:01I really like your approach on programming languages, frameworks, and Adonis looks quite interesting on the first look.
00:10:05So I'm curious what we get today.
00:10:07Yeah, I'm curious too.
00:10:08Thanks for joining.
00:10:09It should be fun.
00:10:10What tool are you using to box highlight areas?
00:10:12That is an application called DemoPro.
00:10:15It's an application that only exists for Mac.
00:10:17I think I bought it like many, many years ago.
00:10:21It's great.
00:10:21It gives you all that stuff here where you can draw on the screen.
00:10:25Yeah.
00:10:27I still don't get why it hasn't been embraced by the JavaScript community.
00:10:30I think opinionated frameworks are great.
00:10:33People like Svelte and View, so why not Adonis?
00:10:35Yeah.
00:10:36I always wondered about this too.
00:10:37I know that I looked at Adonis, I don't know, the first time maybe seven, eight years ago.
00:10:44And I wondered back then too why it isn't more popular.
00:10:48And I personally never found the time to dive deeper into it.
00:10:52And it was never that popular.
00:10:54So it never came up as a course topic or anything like that.
00:10:59But yeah, I don't know.
00:11:00I really don't know because it looks good.
00:11:02But I guess we'll find out how good it is, at least when we get started.
00:11:07And therefore, let's get started.
00:11:09Yeah.
00:11:10We need Node, of course, create a new application, npm create.
00:11:16So let me copy that.
00:11:19I already created a little folder here.
00:11:21I'll not use npm but bun because it's faster and a bit more secure.
00:11:25Can I create it in this folder?
00:11:27Does this work?
00:11:29Yeah.
00:11:29Okay.
00:11:30Now I have to choose.
00:11:31Do I want to use the Hypermedia app?
00:11:33So the template engine, React, the view app.
00:11:38I'll go Hypermedia here.
00:11:39It's downloading the starter kit, installing the dependencies, migrating the database.
00:11:45So it seems to give me some basic starter application here.
00:11:53Command failed.
00:11:55Node ace migration run.
00:11:58Huh.
00:11:59It's not a good start.
00:12:01Is that because I used bun?
00:12:04Or because I use...
00:12:05It could also be because I have the latest version of Node.js, Node 26.
00:12:12Maybe there is a problem with that because I tried to run it with Node.
00:12:20Let me see.
00:12:21Can I run this like this?
00:12:24Okay.
00:12:25I've got an error, a new exception.
00:12:28Oh, boy.
00:12:29There is this tendency that whenever I try something on the live stream, it fails.
00:12:35Cannot find module startenv from Adonis bin console TS.
00:12:45Let me check.
00:12:47Is that a Node?
00:12:48Let's use an older Node version here.
00:13:01Nah.
00:13:02It's a different error now.
00:13:08Could not locate the bindings file.
00:13:14So, okay.
00:13:14Whoops.
00:13:15One thing I'll try, since maybe it was the Node version, I'll quickly clear everything in this folder.
00:13:24And I'll recreate it now with NPM and I'll just hope that I don't get pawned by some supply chain attack right now.
00:13:34I'm really paranoid about using NPM these days.
00:13:38I prefer BUN or PNPM.
00:13:42Okay.
00:13:43Let's try again.
00:13:44Let's see if that works better.
00:13:52I mean, at this point, there shouldn't be too much I can get wrong.
00:14:11Command failed.
00:14:12That is really not off to a good start here.
00:14:19Is that something that is, do we have that issue here?
00:14:23Something that's known?
00:14:27Doesn't look like it.
00:14:36Okay.
00:14:37Let's see.
00:14:38One thing we can try is feed this to AI.
00:14:43And see if it can figure it out.
00:14:46So, I'll spin up Pi, my favorite coding agent at the moment.
00:14:57Trying to get started with Adonis in this project.
00:15:02Ran.
00:15:03What was the command?
00:15:04And NPM create this.
00:15:09Okay.
00:15:10NPM create.
00:15:13Adonis.js at latest dot.
00:15:17It failed when trying to run the migrations.
00:15:22Running manually also failed.
00:15:24So, let's paste in that error log and let's see what we get here.
00:15:29Good morning.
00:15:30Or good evening.
00:15:32Good afternoon from my side.
00:15:34Let's see if the AI can help us here.
00:15:38If it can crunch through that error message.
00:15:41What's Adonis.js?
00:15:42Adonis.js is a JavaScript framework.
00:15:44A full stack framework.
00:15:47That is like Laravel for JavaScript.
00:15:50If you know Laravel.
00:15:51So, it's a batteries included framework.
00:15:53Not like Next.
00:15:54Not like Next.js or Tanstack start, which is mostly about routing and rendering on the server.
00:15:59But instead, it comes with authentication.
00:16:01It comes with its own ORM.
00:16:03And that's the idea.
00:16:04Right now, I'm just facing some problems here with the initial setup fixed.
00:16:10Oh, okay.
00:16:11So, it's not.
00:16:14Okay.
00:16:15I get it.
00:16:16It's not Adonis.
00:16:18Probably.
00:16:19But the problem seems to be that this setup command wanted to run some lifecycle script.
00:16:28So, some script attached to a dependency.
00:16:31And I have ignore scripts set to true because of supply chain attacks.
00:16:35And Bun also doesn't run them by default as I know.
00:16:38So, it looks like it needed some script to be executed.
00:16:45So, the AI temporarily disabled this.
00:16:49Now, ran the migrations.
00:16:54Okay.
00:16:57So, hopefully, there's now nothing missing from the initial setup step.
00:17:05I guess we'll see.
00:17:07Because we can, of course, try to now run the development server.
00:17:15So, let's.
00:17:19Yeah, I don't want to use that browser here.
00:17:22Let's see.
00:17:24Okay.
00:17:25So, we got something on the screen.
00:17:31Looks a bit weird.
00:17:37Is that how it should look?
00:17:41Huh.
00:17:43Okay.
00:17:45Anyway.
00:17:50So, now, let's see.
00:17:51I can sign up here.
00:18:05And now, I'm logged in.
00:18:07I can log out.
00:18:08And we got all that built in out of the box.
00:18:12Classic problems always pop up when they don't have to.
00:18:15Yeah.
00:18:16It's really classic.
00:18:17I think that's like the third time that I want to dive in some technology on the live stream.
00:18:22And it just fails.
00:18:23But, yeah.
00:18:23It's working now.
00:18:25It seems to be working without problems now.
00:18:31Not sure about this temp folder.
00:18:33Is that where my production database is stored?
00:18:36Or my development database?
00:18:37Schema.
00:18:38Users.
00:18:39Yeah.
00:18:39Okay.
00:18:40So, it's using SQLite, which I like, because that's all lightweight and simple.
00:18:45And we'll explore what we have here in just a second.
00:18:48Udemy needs to add the ability to follow instructors to see when they have new content come out.
00:18:53You tell me.
00:18:54I mean, together with other instructors, we've been telling Udemy for so long how many cool features they could add.
00:19:01But, yeah.
00:19:02They just don't want to, I guess.
00:19:05I like how you tried to figure out the issue before using AI.
00:19:08For me, first thing I would do is copy-paste to AI.
00:19:11Looks like I'm doomed.
00:19:12Well, as you see, AI figured it out when I didn't.
00:19:15But I also didn't want to go through that entire error stack because I don't want to make this stream, hopefully, about debugging, but instead about Adonis.
00:19:25So, especially when it comes to parsing, like, long error messages and reasoning about them, AI is really good.
00:19:31I just think it makes sense to at least briefly look at the error message yourself before you send it off to AI.
00:19:38Because, A, sometimes it is super easy to solve.
00:19:42It might just be like a use port or something like this.
00:19:45Not in this case, but in other problems.
00:19:47And, B, it's never bad to see or to have at least an idea of what's going on and what's breaking, which part is breaking, and so on.
00:19:58So, anyways, let's take a look at what we have here.
00:20:01In this project, obviously, package.json file in there.
00:20:08Get some mappings, basically, for the files that make up this project.
00:20:14Then we get some dependencies from Adonis.
00:20:19What is Vine?
00:20:24A validation library, okay.
00:20:25Got a validation library, better SQLite3, edge.js, that's the template language, as I understand it.
00:20:34What's Luxon?
00:20:39What's that?
00:20:41A library for working with dates and times.
00:20:44Okay, so we got that, and then we got some, where is assertion, test runner types, Alpine.
00:20:54Alpine is essentially all the JavaScript library for adding lightweight client-side JavaScript code, so that you don't have to write vanilla JavaScript code, but you also don't need a full, big library like React.
00:21:05Okay, Adonis R-CTS looks like the config file, and it is experimental flags, commands, list of ace commands to register.
00:21:15Yeah, so it's been a long time since I last worked with Laravel.
00:21:20I used to do a lot of Laravel development in 2015, 2014, and 16, I think, and as I remember, Laravel had, like, lots of features, like Adonis, as it seems, and it also allowed you to register your own commands.
00:21:38So the idea is that in Laravel, I think it was, like, the artisan command, and here it seems to be the ace command, which you execute with Node.
00:21:49So that's a command or a tool given to you by Adonis, and you can register your own subcommands, basically, as I understand it, which I guess you register in, no, these are built-in commands, and you could basically import your own files here.
00:22:05So my file TS, something like this, probably, and that could register your own commands, so that you had your own utility commands.
00:22:15Service providers to import and register, so my understanding here is that this is about dependency injection and about registering various services that spin up as the web server spins up.
00:22:26So what do we have here?
00:22:28So what do we have here?
00:22:28We've got a database provider, off provider, so we've got the different providers for the different features, so to say.
00:22:34Preload, so, okay, so essentially, this is our configuration file, got it.
00:22:40What else do we have?
00:22:41We've got an env file where we configure the port and so on, log level, got an app key here for,
00:22:50I don't know, I don't know, for what is that used for, for also, for, for hashing our passwords or stuff, I don't know.
00:23:01Session driver cookie, okay, so that we use cookies for authentication, get our database in here, that should be.
00:23:12Get ignored.
00:23:14Temp, yeah.
00:23:16Tests, got our unit tests set up here.
00:23:23Resources, yeah, that's just like in Laravel, I think.
00:23:27In Laravel, we also had a resources folder with essentially the client-side resources, so here we got our client-side CSS code, client-side JavaScript code, using Alpine, as I mentioned.
00:23:40And views, and that is basically the front-end pages, or the templates that will be rendered into pages, and, as it seems, all the components.
00:23:49But I don't know yet how this templating system works.
00:23:53Now, let me quickly see if I can install some extension and hopefully not get a supply chain attacked for this edge templating language.
00:24:02Edge template support, here, the official one, edge template syntax highlighter by Adonis.js.
00:24:09Let's install that.
00:24:12Oh, God, don't hack me.
00:24:16Okay, looks better.
00:24:18So now we got some syntax highlighting.
00:24:20So, the idea behind the templating language, I mean, in the old days, it was pretty common to use template languages, also in other JavaScript frameworks.
00:24:32And the idea really is that you render your HTML pages on the server, and then the finished HTML code is sent to the client.
00:24:39But in order to make it a bit more convenient and more dynamic, you would compose your HTML file from different templates and have placeholders in those templates, which can be replaced with dynamic values.
00:24:51And what we have here, for example, as it seems, is that we are saying, okay, this home page, so we're in the pages folder, this home page here should be based on a layout.
00:25:02And I would assume you can define different layouts, but if you don't specify anything here, it's using a default layout, which is registered somewhere.
00:25:09And then this part here is injected into that layout.
00:25:12So, in that layout, we probably have some placeholders.
00:25:14So, let's see, where is the layout defined components layout here.
00:25:20So, that is a layout file.
00:25:22So, here we see the general HTML skeleton.
00:25:24We also see that in the body, we got this main slot.
00:25:29So, that seems to be the edge template language syntax for defining a slot where the actual page content is rendered into.
00:25:39So, again, I don't know how that language works.
00:25:42I'm just trying to understand it from reading it.
00:25:44So, it looks like maybe that's a name we can assign.
00:25:47Maybe it's a reserved name.
00:25:49I don't know.
00:25:50And it's async.
00:25:51That's interesting.
00:25:52We awaited.
00:25:53So, we only finished rendering the layout until this has been rendered here.
00:25:57Slots main.
00:25:59So, that seems to be a reserved name, essentially.
00:26:01And besides that, we also have the concept of partials, which I also know from Laravel, which is also pretty typical, so that you don't just have a layout, which has like a slot for the main content, but that you also have other components, essentially, which you can bring into the layout, but also potentially into other pages.
00:26:18So, here we've got a partial for the header, partial for flash alerts, a little extra alert messages you want to show on the screen, maybe.
00:26:26And, for example, the partials header thing here can be found in the partial folder header.
00:26:33And in here, we now got the header.
00:26:35And in there, we got more template syntax for rendering a link.
00:26:40And links are rendered like this because they're also dynamic.
00:26:43They depend on the routes you registered, if they're internal links.
00:26:47So, here we're setting up a link to the home route with a text of home.
00:26:52And we can see that.
00:26:54Where can we see that?
00:26:55Can we see that at the bottom?
00:26:58Or, oh, no.
00:26:59It's this.
00:26:59This is a SVG here.
00:27:01So, that is essentially this SVG, I assume.
00:27:04It has a fallback name of home.
00:27:06And if we click it, we're taken to the home route.
00:27:13Okay, then we got some conditional rendering here, depending on whether we have a locked-in user or not.
00:27:19Makes sense.
00:27:20That's all in the header still.
00:27:23Okay.
00:27:23And then here, for example, that at VIT thing.
00:27:26So, we seem to be using VIT for the front-end assets, for bundling and managing the front-end CSS and JavaScript assets, as it seems.
00:27:35And we're injecting the, I assume, optimized and bundled app.js and app.css files into here.
00:27:45Or, specifically, we find that in the resources folder under JS and CSS.
00:27:49So, that is this JavaScript into CSS file.
00:27:53So, I don't know if it's even processed.
00:27:57Got it.
00:27:58And all the VIT servers spun up automatically when we start the main dev server, I assume.
00:28:05So, okay.
00:28:06Makes sense.
00:28:06I don't understand everything here.
00:28:08This stack thing here is probably some debugging stuff.
00:28:11I don't know.
00:28:12And then we got more components here.
00:28:15And, yeah.
00:28:16I'll have to dig into that.
00:28:17What exactly is going on here.
00:28:19But we'll do that in due time.
00:28:21Let me get back to the chat.
00:28:22Some questions.
00:28:24Max's LLM models get more expensive to run, use, and no longer subsidized.
00:28:28Will open source or self-hosted models become more important?
00:28:31And, as a result, should devs learn DevOps for that shift?
00:28:35So, I think that open models will become more important in the future in general.
00:28:42But, of course, if you want to run them on your own, that will also cost you money.
00:28:45Because either you need a pretty beefed up local machine.
00:28:48So, like a Mac Studio for 10K or something like this.
00:28:52Or you'll need to rent it again.
00:28:53So, it'll always cost you some money.
00:28:56But, of course, depending on how expensive the frontier models get, the open models may be interesting alternatives.
00:29:03There aren't too many super capable open models, depending on what you're trying to do.
00:29:10But, I'm sure we'll get there.
00:29:12I don't think you should learn DevOps for that, though.
00:29:16You should learn it if that's, in general, something that's interesting to you.
00:29:19But deploying and running your own open model is something you may, if you have the hardware,
00:29:25or if you rent a VPS, do once or so.
00:29:28But you then just need to learn how to get it right this one time.
00:29:32You don't need to, like, in general, learn a lot about DevOps, I would say.
00:29:36And, hi, thanks for taking my Flutter course.
00:29:41Thank you for the nice shout-out, Don Solid.
00:29:47And, why would I use this tool, please, and not directly using any AI service?
00:29:51I'm not sure which tool you mean.
00:29:54Is there any chance you guys might publish your new courses on Udemy?
00:29:57Do you still do Udemy courses?
00:30:01Occasionally, we do.
00:30:02But, Udemy is not taking the best developments right now.
00:30:07So, we'll have to see how that all works out with the Coursera acquisition and so on.
00:30:14And, regarding the content security policy, I mean, you can go to that layout, I assume,
00:30:22and just add whatever you need to add in the head section here.
00:30:25It's just HTML in the end, so you can just add that here.
00:30:32So, that should work.
00:30:34But, I am, of course, just getting started with Adonis here.
00:30:42Okay, so, we got that.
00:30:44Let's skip, or let's, for now, leave the front end, the resources.
00:30:48Let's take a look at the start folder.
00:30:50That must be the server side part, because we explored, no, we didn't explore everything else.
00:30:56There is more.
00:30:57We got database, which contains our migration.
00:31:00So, the idea here, just like in many other frameworks, is that we define our database tables
00:31:08in migration files, which seem to have this format.
00:31:12And, I would assume there also are some commands we can run to automatically create those migration files.
00:31:17And, we then also run those migrations to apply them to the database to basically plan out our tables and their schemas.
00:31:24So, we have that, schema TS.
00:31:28Okay, so, we set up a schema, a database table as a class, essentially, as it seems.
00:31:33And then, we probably create the migration programmatically through a certain command.
00:31:40Config, oh, there's a lot of stuff to configure.
00:31:43Okay, so, we can configure a bunch of stuff there.
00:31:50Okay, we'll get to that when we need it, I guess.
00:31:53Bin, server TS, HTTP server, enter point.
00:31:57The server TS file is the entry point for starting the Adonis.js HTTP server.
00:32:02Either you can run this file directly or use the serve command.
00:32:05So, that was executed for us when we started the development server with the serve command here.
00:32:13What are we doing in there?
00:32:18Importer, igniter.
00:32:23Basically, booting up the server, starting to list on the port.
00:32:27Registering the route somewhere, for sure.
00:32:34What's console is the entry point for booting the Adonis.js command line framework.
00:32:38So, that is if we register custom commands or execute one of some of the built-in commands, I assume, with the ace command.
00:32:45And app, okay.
00:32:46So, in here, we register start stuff.
00:32:49And start seems interesting.
00:32:51So, in start, we have the routes TS file, for example.
00:32:54And in here, we clearly register the routes of our application.
00:33:00Like that for slash nothing.
00:33:02So, domain slash nothing.
00:33:04We render the home page.
00:33:06So, here we refer to paths in our resources views folder.
00:33:12So, in resources views.
00:33:15So, if we have like render pages home, that goes to the pages folder here.
00:33:20And then in there, it renders home.
00:33:23That is essentially what is happening here.
00:33:28And we can group routes.
00:33:31So, why would we group?
00:33:33To apply some shared middleware, right?
00:33:35Guest middleware.
00:33:38Whatever it does.
00:33:40And then we get sign up and log in routes here.
00:33:44Yeah, probably that's some middleware that only unauthenticated users can reach those routes.
00:33:49And on the other hand, we get the auth middleware to protect routes that should only be reachable by authenticated users.
00:33:56Like the logout route, which only makes sense if we, well, do log out.
00:34:00And then every route either is registered like this, where we directly render something or, and I know that from Laravel too, probably more common or more in line with the official philosophy, to put it like this, is to connect a controller and a certain controller method to a route.
00:34:21So, here for sign up, we have two routes, one get and one post route, and it's in the same controller's file, but we target different controllers to create and to store controller.
00:34:35If we take a look at that, our controllers in the controllers.ts file here, which are in adonis.js server, dot adonis.js server.
00:34:47Yeah, but that's, that's created dynamically, isn't it?
00:34:51Did we create that?
00:34:53Aren't we not?
00:34:55No, we register our controllers here.
00:34:59I assume this is generated dynamically.
00:35:01So, here, new account controller.
00:35:04We have our class, new account controller.
00:35:08And then in there, we have a create method and a store method.
00:35:12And these are responsible for these names in the end.
00:35:15And again, we'll see, but I assume this is somehow created dynamically or automatically.
00:35:21And then in create, which is for the get route, we just render another view.
00:35:25So, of course, in theory, we could also not use this, but instead we could, I guess, also do get.
00:35:41Yeah, we could, no, we cannot, can we not directly render here?
00:35:46Do we have to use a controller?
00:35:50Looks like, okay.
00:35:51But in the end, we're rendering it just as we did here.
00:35:56And for the post route here, we are validating the user input with the built-in validator.
00:36:04And then we create a new instance of a user using our user model, to which I'll get back.
00:36:11And then we authenticate that user for the web.
00:36:15So, session-based, cookie-based authentication, I assume.
00:36:18And then we redirect to the home route again.
00:36:21So, let's see.
00:36:24We have the models folder.
00:36:26In there, the user model is defined.
00:36:28And I assume the, I mentioned before that we have those database tables, we have those schemas.
00:36:40And probably we just define the model and the rest is generated automatically, but we'll see that.
00:36:47So, in the end here, we define that we want to have a user or users in our application.
00:36:53And then we extend some stuff that is coming from Adonis.
00:36:57And then we have a little getter here, initials.
00:37:03Okay, that's simply some helper function for retrieving the full name of the user by combining first and last name.
00:37:10Simply to show off how you can basically create computed values like this.
00:37:15Okay, got it.
00:37:17Validators for the user.
00:37:19Little validation file where we use this wine library, which I didn't know before, for basically ensuring that we got a non-empty email address with a certain max length.
00:37:31Excuse me.
00:37:36And then we seem to be able to create certain validator reusables, which we can use in all the places where we want to validate for sign up, where we then enforce certain values.
00:37:49Okay, middleware, auth middleware is simply a class with a handle method where we check something and return next if we want to grant access to whatever route the user was on its way to.
00:38:07And I assume that this frozen error if authentication fails to prevent that on next navigation.
00:38:14Guest middleware, I assume, does the opposite.
00:38:21Yeah, we check if the user is authenticated and then redirect if they are.
00:38:28And we only grant access to wherever they were going if they were not authenticated.
00:38:32Okay.
00:38:33Exceptions allows us to define our own errors, our own exceptions.
00:38:38Okay.
00:38:40Okay.
00:38:42So.
00:38:45What new courses are you planning to release in the near future?
00:38:52Maybe something on BUN.
00:38:55I'm still figuring out if that is a course I'm happy with.
00:38:58So I already recorded something, but I want to check if I'm happy with the quality and so on and if I'm happy with the direction.
00:39:06Some software engineering fundamentals, systems design or courses I would want to build this year.
00:39:12And regarding agentic AI, I know that this would probably sell well, but I answered it earlier.
00:39:20The problem is I would love to create a course where I share how I do agentic engineering and work with AI.
00:39:26The problem just is that it's still changing way too frequently.
00:39:30So I don't believe it would be super useful right now.
00:39:33As soon as I have the feeling that it's a bit more stable, I would love to create such agentic engineering or AI engineering or whatever you want to call it course.
00:39:42It looks like puck.js.
00:39:44Yeah.
00:39:45Why would someone use it in 2026?
00:39:48So I don't think anybody will use Vue.
00:39:51It's all about SPA.
00:39:53I don't agree here.
00:39:56I think we're so used to single page applications and React everywhere.
00:40:01And React is great.
00:40:02And I mean, there definitely also is truth to it that AI loves React.
00:40:07And Adonis in general is pretty niche.
00:40:10But I think it's the wrong assumption to say we need to use React everywhere.
00:40:17Being able to just render templates on the server is often enough.
00:40:23Is often enough.
00:40:24And often adding React can just add more complexity, a bigger bundle size.
00:40:30Think about some security vulnerabilities we got over the last weeks.
00:40:35So there is merit to not introducing something you don't need just because you're used to it.
00:40:41We're so used to using React for everything that we just take it as a given, as a standard option we have to use.
00:40:47And I don't think that's the case.
00:40:49Now, I do agree.
00:40:50This definitely looks a bit dated.
00:40:53And as I said, I wrote my pages like this many, many years ago.
00:41:00I still wouldn't say that it's wrong today, though.
00:41:03It's definitely unusual and not something that feels native or like it would make a lot of sense.
00:41:12But I would say it can make sense.
00:41:14Now, all that said, as I said before, Adonis does support different ways of rendering views.
00:41:23It does support React as a frontend and then uses Inertia.js as a bridge.
00:41:29So you can absolutely build Adonis.js full stack applications without this views-based approach.
00:41:38But I wanted to check it out first because I wanted to see how that looks like.
00:41:43Kind of looks like Hano.
00:41:45Yeah, I think Hano is a bit, is way slimmer, right?
00:41:48So Hano doesn't have all these features like authentication and ORM and so on built in.
00:41:56How are you finding Adonis.js?
00:42:00I find it interesting, but I haven't used it at all before.
00:42:03So I'm just exploring it today.
00:42:05And I just got started with it.
00:42:07I like the idea of having all included in one framework, especially now in the days,
00:42:13of all those supply chain attacks.
00:42:16And I think in a JavaScript ecosystem, we tend to reach for overly complex solutions.
00:42:21And we stitch together dozens of libraries, which also, besides supply chain attacks,
00:42:26has the issue that not all these libraries are always well-maintained.
00:42:31So having just one batteries included framework definitely has its merits, I would say.
00:42:39How do you recommend current computer science students who has basic knowledge to learn programming?
00:42:44What is the next step?
00:42:45Build project or explore AI?
00:42:46I would use AI for learning.
00:42:48I would build projects also with help of AI, but I would not just use AI because obviously
00:42:53you don't learn anything from that.
00:42:54I would try to learn software engineering fundamentals.
00:42:57I would try to write some code here and there from hand.
00:43:01I would definitely review and really understand all the code AI may generate.
00:43:05I may critically question it.
00:43:07Maybe also use AI for discussing the code.
00:43:10But I'll be honest, I'm also still trying to figure out how to best teach and, of course,
00:43:15also learn stuff with AI these days.
00:43:20How do you build a project today so that you learn if I ask AI?
00:43:27Yeah.
00:43:27So I would really use AI as a sparring partner, essentially.
00:43:32Okay.
00:43:32So let's see.
00:43:34Now, I also want to see the alternatives since we just talked about it.
00:43:38And then we'll also get into editing the code.
00:43:40But I want to see the alternative.
00:43:42What if I used.
00:43:47Let me recreate this.
00:43:49Want to start from scratch.
00:43:51Let me recreate this.
00:43:52Stop the server.
00:43:53And use the alternative approach here with the React Kit.
00:44:01Now, it will probably crash again.
00:44:08So, let me quickly check.
00:44:15Which command did it run to make it work?
00:44:19Permanent.
00:44:20I don't want a permanent.
00:44:27So that here will probably do it.
00:44:32Let's see.
00:44:36Let's see.
00:44:37Oops.
00:44:38I did not want to do that.
00:44:39One dot is enough.
00:44:42Okay.
00:44:44Let's see if that works.
00:44:55Schwarzmullering your pants.
00:44:57Not sure if that's good or bad.
00:45:09Have I designed my Flutter course from scratch?
00:45:11Yeah.
00:45:12All my work.
00:45:14So, now let's start it again.
00:45:21Let's see if that looks the same.
00:45:24Yeah.
00:45:25Same app.
00:45:26But now, of course, the file structure should be different.
00:45:29Let's see.
00:45:32App folder.
00:45:36Now, I've got a transformer.
00:45:38But that, I assume that's just some back and stuff.
00:45:42No.
00:45:42That is for transmitting the data from the server to the client, I think.
00:45:46So, to the front end, let's see.
00:45:48Bin, config database, inertia.
00:45:53Okay.
00:45:53Inertia is now the front end folder, I assume.
00:45:56CSS.
00:45:57Yeah.
00:45:57Okay.
00:45:58So, what do we have here?
00:45:59Get an app.tsx file.
00:46:11I have no idea what that is, but I assume it's there for basically hydrating the front end and connecting it to the back end.
00:46:18Create inertia app.
00:46:20Set the page title as it seems.
00:46:22App.
00:46:23Okay.
00:46:24Where is the script's config file, which shows me an error, but that's just because that's deprecated.
00:46:29That's okay.
00:46:32Server-side rendering TSX.
00:46:34So, that's for the server-side rendering entry point, client entry point.
00:46:39Okay.
00:46:39I have no idea how inertia works and what this two-hour thing is.
00:46:46Got my homepage here.
00:46:47So, that is a regular React component now.
00:46:51Nothing too fancy.
00:46:52Do we have a layout or something?
00:46:53Yeah, we have a layout.
00:46:54Default TSX.
00:46:55Where is this set up?
00:46:56Is this set up an app?
00:46:59Resolve page component.
00:47:00Look in the pages folder.
00:47:03Where layout, layout, layout, layout.
00:47:05Layout is imported.
00:47:07Okay.
00:47:08So, that's how that works.
00:47:10Got our layout here.
00:47:12And then got the default layout.
00:47:16Okay.
00:47:16So, we got, ooh, use effect.
00:47:19That's forbidden.
00:47:24Okay.
00:47:25Yeah.
00:47:26So, that's really just React.
00:47:27As we know it, the link component is coming from inertia.
00:47:30Or from Adonis.js and it's inertia package.
00:47:35Okay.
00:47:37And as I understand it, let's see.
00:47:47Yeah.
00:47:47Children is obviously for the...
00:47:51Okay.
00:47:52Okay.
00:47:53Okay.
00:47:54Interesting.
00:47:54Children is, of course, like always React, the component between the tags.
00:48:05But children also has a props object with a user property.
00:48:13And I assume that is populated somewhere in our controllers.
00:48:20First, new session, new account controller of sign up or inertia render.
00:48:29But there we don't pass any props.
00:48:32Session controller.
00:48:35Where is this populated?
00:48:36Because we got this transformer thing here, which I thought would be for transforming server-side to client-side data.
00:48:46I'm not sure.
00:48:50Return this pick, this resource, whatever.
00:48:56Maybe it's also just there for retrieving data from the database.
00:48:59I'm not sure.
00:49:01Okay.
00:49:02So, we got this set up.
00:49:03Let's continue with the official guide.
00:49:05I just really like to dive into the code base myself first.
00:49:08And then take a look at it to try to understand it before I follow the guide.
00:49:12Because I feel like I learn a bit more doing it like this.
00:49:16And who reads code these days anyways, right?
00:49:18So, why not use the stream to do it?
00:49:22Just joking.
00:49:23I do read code.
00:49:26Folder structure.
00:49:28Okay.
00:49:28I just explored the folder structure.
00:49:31App folder.
00:49:32The app directory organizes code for the domain logic of your application.
00:49:36For example, controllers, models, mails.
00:49:39So, yeah, like Laravel, it also helps with sending mails, which can, of course, be super convenient.
00:49:44The bin directory contains the entry point files used to start your Adonis.js application, console, server, TS.
00:49:50You usually won't need to modify these files unless you want to customize how the app boots.
00:49:56Okay.
00:49:56Config all application and third-party configuration files live inside the config directory.
00:50:01You can also store config local to your application inside this directory.
00:50:05Yeah, so in the config folder, we already saw there is stuff like, I don't know, database that we use SQLite.
00:50:13I assume you could also probably connect to a Postgres database or stuff like that.
00:50:20We can choose the client.
00:50:21So, maybe we could use something like Buns SQLite client here.
00:50:24I don't know.
00:50:25Define the database path, the temp path.
00:50:28So, in that temp folder here, migrations, what else do we have?
00:50:34Config, inertia, server-side rendering, toggle server-side rendering mode.
00:50:39Yeah, I want server-side rendering, so let's turn this to true.
00:50:47Logger, yeah.
00:50:48So, it makes sense.
00:50:50I just quickly want to check.
00:50:52If I set this to false, my assumption would be that if I take a look at the page source here, that has a div app with some data that's passed to it.
00:51:06Yeah, but the main HTML content is missing because it's client-side rendered.
00:51:10We're importing some scripts, which then do the client-side rendering.
00:51:15That's not great for search engine optimization.
00:51:18So, if I set this to true, now we can see there's way more in there, right?
00:51:26There is the actual, all inline, so a bit hard to read, but the actual HTML content is there.
00:51:31So, I'll keep that set to true.
00:51:34Okay, the database.
00:51:35The database directory holds artifacts related to the database layer.
00:51:39By default, it honors JS chips with Lucid ORM, so its own ORM.
00:51:43And the idea behind ORM is that you express your database tables essentially as models, as classes, you could say, in your code.
00:51:51And then the underlying schemas and migrations are generated for you.
00:51:57And, yeah, this is the first time of me exploring this framework, so I'm just figuring out how it all works right now.
00:52:03Switching databases does not require reorganizing this folder, migrations, versions, schema changes, seeders, if you want to have seed data, like some initial admin users or stuff.
00:52:15Okay, providers.
00:52:16Providers directory is used to store the service providers used by your application.
00:52:20What are service providers?
00:52:22Service providers.
00:52:22This guide covers service providers.
00:52:24Well, I will probably not go through entirely.
00:52:27Service providers are JavaScript classes with lifecycle hooks that execute at specific points during application startup and shutdown.
00:52:35This allows you to register bindings to the inversion of control container, extend framework classes using macros, perform initialization at precise moments, clean up resources during shutdown.
00:52:53So, that is where we have some built-in providers.
00:52:58Where is it?
00:53:02I saw it before.
00:53:04Where are the built-in providers?
00:53:09Providers.
00:53:09Here's API provider.
00:53:12Custom serializer for API responses.
00:53:17Okay, so here we got a provider for serializing data, as it seems.
00:53:22And I would assume there are more built-in providers that help with auth, so that register a bunch of default middleware or anything like that.
00:53:30Would be my assumption.
00:53:33Let's not save this.
00:53:35Okay, public, the public directory contains raw static assets.
00:53:39Did I overlook this folder?
00:53:40Public.
00:53:46I don't have a public folder.
00:53:48But I guess I don't have any public assets then.
00:53:51I could add a public folder probably to have raw assets that won't be optimized.
00:54:05I see almost no jobs in Adonis.
00:54:07Then why exploring such things which are not in demand?
00:54:10Just for fun?
00:54:10Yo, if you're, of course, looking for a job, then Adonis.js.
00:54:15Oh, that's such a difficult question.
00:54:17I mean, yeah, Adonis.js doesn't help you if you're just looking for a job.
00:54:22But, for one, exploring alternatives always broadens your horizon.
00:54:27You might learn about new concepts here, which do apply to other applications with other tech stacks as well.
00:54:33For fun is a very valid reason.
00:54:36And, of course, you just may, if you're not looking for a job, if you're looking to, like, build your own SaaS, your own business, whatever,
00:54:48then, of course, that might be a valid option.
00:54:52If you are looking for a job, depending on where you are, of course, it may be very niche.
00:54:58And, to be honest, it's so niche it will be very hard to find a job.
00:55:01But, of course, you wouldn't have a lot of competition if you were in an area where there would be some jobs for it.
00:55:07But that's very theoretical, of course.
00:55:08But, yeah, for me, it's just the fun now.
00:55:10I just want to explore it because I read about it, like, eight years ago already.
00:55:15And I finally want to understand how it works.
00:55:19A resource directory stores edge templates and uncompiled fronted assets such as CSS and JavaScript files in an inertia app.
00:55:30Do I have resources?
00:55:32I do.
00:55:33Inertial layout.
00:55:35Oh.
00:55:35So that's like the raw HTML skeleton into which this React app is rendered.
00:55:41So we could set up our content security policy here.
00:55:44We could bring in some static assets here, I guess.
00:55:48Register some metadata in addition to what we already have.
00:55:51Okay.
00:55:52Inertia, the inertia directory exists only in projects using the inertia starter kit.
00:55:56Makes sense.
00:55:57It represents a sub-application containing the frontend source code.
00:56:01You're free to create additional folders such as components, layouts, utils to organize.
00:56:06So essentially, you're building your view or your React app in there.
00:56:09Clear separation between frontend and backend.
00:56:11Adonis.js maintains a clear boundary between the backend and the frontend.
00:56:14You should never import backend code into your frontend application to not expose anything there or to have it crash because obviously backend APIs or server-side Node.js APIs won't run on the client in the browser.
00:56:30In practice, your frontend communicates with the backend through HTTP requests and receives plain JSON data.
00:56:35Adonis.js encourages you to model this reality explicitly.
00:56:39Data is fetched and transformed via API responses.
00:56:43I wonder, that's interesting, how exactly are we communicating here when using inertia?
00:56:49So let's say we're logging in.
00:56:52So we have a form here.
00:56:54Yeah.
00:56:54And that's interesting.
00:56:56That is a component coming from the Adonis.js framework.
00:57:01It takes a route and I assume we don't send a HTTP request like we would do in a normal React app to some REST API we built ourselves, right?
00:57:12Instead, we built this just as if it were an old school multi-page application where our form is connected to some route.
00:57:19And when we submit that form, I assume that behind the scenes, inertia and Adonis will create that request, send it to that route.
00:57:28And everything will be handled for us, essentially.
00:57:31So we don't need to send the request ourselves, wait for the response, manage some state.
00:57:37We don't need to do that here.
00:57:42Yeah.
00:57:44What is your thought process when you learn a new framework?
00:57:48Do you like compare it with other frameworks?
00:57:51Or do you treat it as an absolutely new thing?
00:57:53I think you automatically always compare it a bit to what you already know.
00:57:57But of course, Adonis is so different, for example, from Next.js and so on that I don't compare it too much.
00:58:03The main comparison that I made initially is that I understand or need to understand that it's a totally different philosophy.
00:58:10So it's not just about routing and rendering some components, but instead it's about having this full-fledged batteries included framework.
00:58:18So I'm not really comparing it too much.
00:58:19I see it as a pretty new thing.
00:58:21I do compare it to Laravel a bit because it is Laravel for JavaScript.
00:58:25And thank you, Bleem, for the very nice comment here.
00:58:29Happy you're liking the content.
00:58:32Okay.
00:58:34Shared types.
00:58:35The frontend can still rely on shared TypeScript types, automatically generated by Adonis.js.
00:58:40These are stored in this .adonis.js client directory and include type definitions for routes, props, and so on, so that we can leverage TypeScript.
00:58:48Start.
00:58:49The start directory contains the files you want to import during the boot lifecycle of the application.
00:58:55For example, the files to register routes and define event listeners should live within this directory.
00:59:00Adonis.js does not auto-import files from start.
00:59:03Adonis.js is merely used as a convention to group similar files.
00:59:06Okay.
00:59:07So in that start folder, I have the kernel TS file.
00:59:12Oh, yeah, I already saw that.
00:59:14Right, right, right, right, right, right.
00:59:16So we could register new middleware here, I assume, and we'll see if we have to do that as part of the guide.
00:59:24We got a test folder.
00:59:25We got the temp folder for temporary files like the database.
00:59:28Ace.js is the entry point for executing ace commands.
00:59:33Do we have that here?
00:59:35Ace.
00:59:36Ace, yeah.
00:59:37Okay.
00:59:38Do not modify this file.
00:59:39Okay.
00:59:41Yeah.
00:59:44Is the project manifest?
00:59:46Use lint package.
00:59:48Use config.
00:59:49Okay, got it.
00:59:51Development environment setup.
00:59:54Adonis applications come with a fully configured development environment.
00:59:57So, yeah, code editor.
01:00:01Yeah, I installed the Edge extension already, but we won't need it if I use Inertia and React.
01:00:09TypeScript.
01:00:10So that should all be configured as I understand it.
01:00:12So I don't really want to waste time on that.
01:00:14Configuration and environment.
01:00:18Configuration and Adonis is organized into three distinct systems, each serving a specific purpose.
01:00:23Config files contain your application settings in the config folder.
01:00:28Environment variables in .env hold runtime secrets and values that change between environments.
01:00:33Makes sense.
01:00:34By the way, regarding secrets, especially with all those supply chain attacks, my recommendation would be to not store them in .env files.
01:00:41I might do that for a course or something because it's quick and I delete it thereafter anyways.
01:00:47But for secrets you really continuously use, I would use a service like InPhysical.
01:00:53I know I'm not paid by them.
01:00:54You can also use Doppler or anything like that.
01:00:57These are cloud services.
01:00:58In Physical, you can get started for free.
01:01:01Yeah.
01:01:02And then you can store your secret in the cloud and pull it in via CLI.
01:01:06And if your machine gets compromised, your secrets will not be extracted or not, at least not as easily be extracted.
01:01:14So that's just a little side note.
01:01:17Adonis R-CTS file configures the framework itself.
01:01:20Okay.
01:01:20So the config files are for the application and that is for the framework itself.
01:01:26So here we could change probably the folder names in which it looks by default and so on.
01:01:33Configuration lives in a config directory.
01:01:35Typical Adonis project includes several config files.
01:01:38I saw that.
01:01:39Here's what a database config file looks like.
01:01:42Mail config.
01:01:43Notice how this config file references environment variables.
01:01:46This is the correct way to use environment variables.
01:01:49Yeah.
01:01:49So that makes sense.
01:01:50So for example, if we have an application that sends email, we can configure how emails are being sent.
01:01:55But regarding some values, we're putting them into .end files to not have them hardcoded here in the config files.
01:02:02That's just for the general configuration for tweaking the settings, but for the concrete values, then for the secrets, where we're loading those in as environment variables.
01:02:12Configuration files are loaded during the application boot cycle.
01:02:16So we're not using edge templates, we're not using edge templates environment variables, .env is probably loaded automatically.
01:02:25The app key is a special environment variable that Adonis.js uses for encrypting cookies, signing sessions, and other cryptographic operations.
01:02:35So we're going to run generate key to create an app key, but we already have one.
01:02:41Okay, we get that.
01:02:46So I just assume the defaults will be fine here.
01:02:49I don't want to spend this stream just tweaking config files.
01:02:53So let's continue deployment.
01:02:58Yeah, okay, but I don't want to deploy.
01:03:00I want to build FAQ, yeah, and now build a fully functional, building dev show, a community showcase website.
01:03:11In this tutorial, you will build dev show.
01:03:14Yeah, I want to do that.
01:03:17But questions first.
01:03:21Do you think GitHub Actions are the main culprit behind TanStack security issue, or is it a fault of TanStack?
01:03:27So technically, it is a fault of TanStack, because they could have configured stuff such that this wouldn't have happened, if I recall it correctly.
01:03:38But, of course, if you have a system like GitHub Actions, which made this specific error so likely to happen, that's, of course, also not great.
01:03:50Now, I will say, I'm not a huge CICD expert.
01:03:55I always used GitHub Actions for many, many years for all kinds of automations.
01:04:00But then again, I'm not working in a large enterprise where we got five teams pushing to the same repo all the time with all different edge cases and complex workflows.
01:04:12So I'm happy with GitHub Actions.
01:04:14But again, I'm using it in different forms.
01:04:18Not all super, super simple, but definitely not the most sophisticated workflows you ever saw.
01:04:29I want to ask about your JavaScript course.
01:04:31Is it wrong to watch more than 90 videos and still not understand?
01:04:33If you understand nothing, that is not a good sign.
01:04:38Probably for me then, I guess.
01:04:39But hard to answer like this.
01:04:43But something, I guess, should be clicking if you watch the orders, the videos in order.
01:04:51But yeah, I find it hard because I use Windows and you used Apple.
01:04:54But that should make a difference.
01:04:56JavaScript is JavaScript.
01:04:57So I, but again, I don't know what's, what's, if you say not understand, if you're not understanding the JavaScript syntax, that's the same, actually.
01:05:07So there, Windows, Apple shouldn't be the problem.
01:05:10Hello, Max.
01:05:11Thanks for your huge contribution to community.
01:05:13Hello, and thank you so much for, for the very nice words.
01:05:16Do you prefer working with React or Angular or does it depend on the project?
01:05:20Depends on the project.
01:05:21But nowadays, I use mostly React also because, of course, it's AI's favorite.
01:05:26And I use a lot of AI for, for coding, for the better or worse of it.
01:05:33Before AI, I didn't have a strong preference.
01:05:36If anything, I probably preferred Vue from the syntax and the ease of use, especially Vue too.
01:05:42But yeah, these days are long gone.
01:05:44So whatever.
01:05:46What do you think is important when learning new framework paradigm concepts?
01:05:51So really diving deep is important for me.
01:05:54I want to understand how stuff works under the hood.
01:05:57I don't want just, I don't want to just get the, the basic superficial answer.
01:06:03I want to understand how things are connected, why we do certain things in a certain way, when to use a certain approach.
01:06:10I really try to question the things and dive a bit deeper if you want to put it like this.
01:06:16But now let's build this.
01:06:19We're starting with the Adonis.js Hypermedia.
01:06:22So I'm using Inertia.
01:06:23We'll see if we can still make it work.
01:06:27Yeah, we have those routes.
01:06:29I have them here too, I believe.
01:06:34Where are we?
01:06:35We are in the start.
01:06:36Yeah, it's the start folder routes.
01:06:39Yeah, we got that here as well.
01:06:40So that looks the same.
01:06:43The story kit gives us signup, login, logout routes.
01:06:45Notice how middleware guest ensures only logged out users can access signup, login, while middleware auth protects the logout route.
01:06:53We already figured that out.
01:06:55How controllers work.
01:06:56Let's look at the signup controller to see how requests flow through the application.
01:07:07Yeah, let's take a look at this new account controller in app controllers.
01:07:12So I'm using Inertia, of course, not Edge, but still.
01:07:19Each controller method receives an HTTP context object as its first parameter.
01:07:26This one here.
01:07:28The context contains everything about the current request, the request data, response object, off state, view renderer, and more.
01:07:34We destructure just the properties we need.
01:07:39The create method simply shows the signup form.
01:07:42Yeah, so I understood that.
01:07:44We here, in our case, since we're using Inertia, we're getting this Inertia thing.
01:07:48There is more stuff in here.
01:07:50We could get the request to find out, I don't know, the URL and stuff like that.
01:07:57But here, we're using this Inertia object to render a view.
01:08:01And here, for this post route, I'm using, as it seems, yeah, we're pulling out the request to use the validate using method to validate the request body.
01:08:12Yeah.
01:08:17You might notice the controller references a user model and a signup validator.
01:08:21The starter kit already includes these.
01:08:23We'll explore that in a later chapter.
01:08:27Okay.
01:08:30When a controller calls view renderer, looks for the template file and renders it.
01:08:34So, yeah, we get that.
01:08:35Views live in the resources folder.
01:08:38Try creating an account.
01:08:39Yeah, I already did that.
01:08:40Command line in REPL.
01:08:42You might be wondering why we're covering CLI and REPL instead of jumping straight into building features.
01:08:46Here's why.
01:08:46Throughout this tutorial, you'll constantly use ACE commands to generate controllers, models, and other files.
01:08:51Getting familiar with the CLI now prevents us from interrupting us flow later.
01:08:54Okay.
01:08:55We can see available commands with node ace list.
01:08:59Let's do that.
01:09:02Hello.
01:09:05Okay.
01:09:06So, we got a bunch of commands, bunch of built-in commands that we can run.
01:09:11Install and configure one or more Adonis packages.
01:09:14Build, eject, database commands for running the seeders.
01:09:19Generate a key.
01:09:21List our routes.
01:09:23Make stuff like make an event for which we want to set up a listener.
01:09:29Or create a new middle bear or a model.
01:09:32Okay.
01:09:32Yeah.
01:09:38REPL.
01:09:39Yeah.
01:09:40I will actually jump ahead.
01:09:42I feel risky.
01:09:54In this chapter, you will create models and migrations for the post and comment resources.
01:09:59Establish relationships.
01:10:01Generate dummy data.
01:10:01Okay.
01:10:02This chapter introduces Lucid, Adonis, JS, SQL, ORM.
01:10:06Instead of writing raw SQL queries, you'll work with JavaScript classes called models to represent your database tables.
01:10:11So, I already said that before.
01:10:14An important distinction.
01:10:15Models define how you interact with data, but they don't modify the database structure.
01:10:20That's the job of migrations.
01:10:21Yeah.
01:10:21So, we have a model.
01:10:22We'll use the model in our code.
01:10:24To interact with the data.
01:10:25But in order to do that, we need a database table.
01:10:27And in order to create that, we need a so-called migration.
01:10:31Which is like a little script, you could say.
01:10:33Or a blueprint for adjusting the database to have the right table that we need.
01:10:37And the migration is derived from the model.
01:10:40From the model class.
01:10:42That's how it works in Laravel.
01:10:43And I understand that it works like this in Adonis.
01:10:49So, let's add a post model.
01:10:54With node ace make colon model post.
01:11:01And this gives us a model's post TS file.
01:11:05And it also already creates a new migration file.
01:11:09Because as I said, we need both model and migration.
01:11:11So, we now got to the post model here.
01:11:13An empty class right now.
01:11:19That might just be a TypeScript error in my IDE.
01:11:26Or, no.
01:11:27I think we don't have one.
01:11:28Because I haven't set up the migration.
01:11:33The schema.
01:11:34The shape of the table yet.
01:11:41Define the table structure in the migration.
01:11:43Right.
01:11:43So, we need to do that.
01:11:45So, let me copy that.
01:11:48And let's go to this post.
01:11:53Migrations file.
01:11:54Base schema.
01:11:56Yeah.
01:11:56That's the right one.
01:11:59So, initially, what it does here is it sets up a basic table with a table name of posts.
01:12:07And it just gives it an ID and some timestamps.
01:12:10And what we're adding now is these three lines here.
01:12:14So, I can just copy those actually.
01:12:16Paste them in here.
01:12:18To give every post a title, a URL, and a summary.
01:12:24As it seems.
01:12:25And we set it to not nullable so that we need values in there.
01:12:28They must not be null.
01:12:30Okay.
01:12:31So, now we probably need to run that.
01:12:34Yeah.
01:12:34The up part runs to create it.
01:12:36The down part runs to drop the table.
01:12:39Creating the comment model.
01:12:40Let's create the comment model.
01:12:43So, let's.
01:12:45Actually, let me stop the dev server.
01:12:47Because we'll need to restart it anyways for it to pick up those changes, I assume.
01:12:51So, let's again create another model.
01:12:53The comment model.
01:12:54Just like before.
01:12:56Got a new migration file.
01:12:57Got a new.
01:13:01Where is it?
01:13:02The new model.
01:13:03Comment model here.
01:13:04And in the migration file.
01:13:06Again, basic skeleton.
01:13:09And what are we adding here?
01:13:10Just one line as it seems for.
01:13:13The content.
01:13:18Okay.
01:13:21And now we can run them to apply them to the database to add those tables.
01:13:27Looking good.
01:13:29And now let's see.
01:13:31Starting the dev server again works.
01:13:35And now that error here is gone too.
01:13:36Because now that we applied the migrations behind the scenes, it probably created these types.
01:13:47Yeah.
01:13:48Database schema TS has been updated with that.
01:13:51So, that is here in this database folder schema TS.
01:13:56So, that file is basically managed for us.
01:13:58It now has the schemas which were created for us by Adonis.
01:14:02By this ace command in the end.
01:14:04So, thank you for your answer, Max.
01:14:11I bought several of your courses.
01:14:12It helped me a lot through my career as a software developer.
01:14:16Yeah.
01:14:17Thank you so much.
01:14:18Thank you so much for being part of the courses and for the very nice words.
01:14:21I'm super happy to hear that the content was helpful.
01:14:24And that I could be a small part of your career.
01:14:27Thank you so, so much.
01:14:31So, now let's see how we can add relationships.
01:14:33Because obviously, we want a relationship between our comments and our posts.
01:14:37We want every post to have potentially one or more comments.
01:14:44And every comment belongs to exactly one post.
01:14:47So, it's a one-to-many relationship.
01:14:54Comments belong to posts and posts belong to users.
01:14:57Yeah, right.
01:14:57We need that too.
01:14:58So, create a migration for foreign keys.
01:15:01The following command will create a new migration file that will modify our existing tables.
01:15:04Okay, let's see.
01:15:06What does this do?
01:15:09Make migration add foreign keys.
01:15:11Okay, so that's just an extra migration file.
01:15:13Before, we had models which come with a migration file.
01:15:16Now, we use just a migration file.
01:15:22Because we don't need a model and we don't need a class.
01:15:25But we want a migration so that allows us to tweak the database setup, essentially, and add some, excuse me, add some new columns to some of the tables.
01:15:40And what we want to do is we want to add columns for setting up those relations because relations in a SQL database, of course, are simply expressed by adding columns where you say this comment has this user ID and this post ID and so on.
01:15:53So, let me copy that.
01:15:55So, let me copy that.
01:15:56This is the foreign keys to posts.
01:16:00Is that what I created?
01:16:05Add foreign keys.
01:16:11Wait a second.
01:16:22Oh, now it will.
01:16:23Didn't I run it?
01:16:25No, it's this one.
01:16:28Okay, so it has a different file name just.
01:16:31Well, that's okay.
01:16:34So, let's paste it in.
01:16:35What are we doing?
01:16:37We are saying in a post table, we add a user ID column, which is of type integer, unsigned, only positive values.
01:16:45It's not null.
01:16:45And we set up that foreign key relationship.
01:16:48And if the user were deleted, we also delete the posts.
01:16:51For the comment, we also link it to users, but also to posts because every comment, of course, belongs to a post.
01:16:58And then we have the down migrations to revert them, essentially.
01:17:01Okay.
01:17:03Run them.
01:17:07Run them.
01:17:11Dev server starts.
01:17:13And define relationship in the post model.
01:17:15Now that the database has foreign key columns, let's update the model to define these relationships.
01:17:20So, I'll copy that.
01:17:22Go to my post model, which is currently basically empty, and paste that in.
01:17:27And now in there, in that class, we are declaring that relationship by adding essentially a comments property, which doesn't have any value, but we add that decorator.
01:17:43So, we just add the property to be able to add a decorator, because it looks like in Adonis, we set up relationships through decorators provided by Adonis and say, a post has many comments and belongs to a user.
01:17:57And that's something, I think it's kind of the same wording in Laravel.
01:18:02So, pretty easy to read and understand.
01:18:05That part might be a bit weird, that we just declare a variable, just declare a property.
01:18:11And we need declare, because without it, we get some problems from TypeScript, that it doesn't have an initial value.
01:18:18With declare, we don't get this.
01:18:20So, that's that.
01:18:22And we also need relationships in the comments model.
01:18:26So, let's paste it in there.
01:18:28And here, we basically say a comment belongs to a post, it belongs to a user.
01:18:31So, you have has and belong, depending from which side you look at it.
01:18:36And you always set up both.
01:18:39Okay.
01:18:40So, now we get that.
01:18:41We haven't added the inverse has many to the user model, because we don't need them in this tutorial.
01:18:46You could add them later, if your application needs to query posts or comments from the user side.
01:18:51Okay.
01:18:52So, looks like we will never look for all the posts by a user in this tutorial.
01:18:58So, we don't need to set up the relationships, but we would need to set them up if we would want to query for all the posts by a user.
01:19:04But, looks like here, we'll just query for all the posts, and we just want to display to which user they belong.
01:19:16Man, that framework looks like Angular and Nest had a baby.
01:19:20I guess big and complex frameworks are still relevant these days.
01:19:24So, I think this framework, in theory, could be pretty, pretty great, because it has so much stuff built in.
01:19:30And it definitely looks a bit overwhelming initially, I guess.
01:19:33But, the huge advantage is that you essentially don't have to add anything.
01:19:39Not anything, but you don't have to add a lot of stuff, and for many apps, you probably don't have to add anything to make this work for a broad variety of applications.
01:19:48I mean, I'm a big fan of Next.js, Tanstack, Start, and I never used Adonis.js before.
01:19:54So, I can't tell you, hey, it's awesome, please use it, right?
01:19:56I didn't use it myself.
01:19:58But, of course, whenever you're using Next.js or Tanstack or whatever it is, Angular stuff, you always have to add, for authentication, an extra library.
01:20:07For database stuff, you have to add extra libraries, potentially an ORM, Prisma, whatever.
01:20:14So, you have to, like, stitch together all these libraries, and especially nowadays with supply chain attacks, that can be annoying.
01:20:21And even before that, with maintenance and stuff.
01:20:23So, in theory, that should be great, yeah.
01:20:26You're working without AI, feeling good and nostalgic at the same time.
01:20:30Oh, yeah.
01:20:31Has a nostalgic feeling to it.
01:20:33Now, obviously, I'm not using AI here because I want to understand how it works and what's going on here.
01:20:38And I find that important if you're learning something new, even in these days.
01:20:42It also wouldn't make for a fun live stream if it would just Vibe code away.
01:20:47And, yeah, there is only so far you can get with Vibe coding anyways.
01:20:52Now that our models and database tables are ready, we need to populate them with dummy data for development and testing.
01:20:57Factories act as blueprints for creating model instances filled with realistic fake data.
01:21:03You define blueprint once.
01:21:04Okay.
01:21:05So, we want to make a post factory to pump out some fake posts.
01:21:10So, we run the make factory command.
01:21:14This gives us a post factory file where we now basically define how we want to generate posts, I guess.
01:21:21So, let's copy that in here and let's take a look.
01:21:25So, we're saying we want to build a fake post.
01:21:30We have a bunch of titles from which this faker tool can choose when it generates posts.
01:21:37And some made up URL and some made up lorem ipsum paragraphs it should add.
01:21:45So, just a programmatic way of quickly adding some fake data.
01:21:48Obviously, these days we could also use AI for that.
01:21:51But let's go old school and cheaper because no tokens.
01:21:56Let's also create a common factory.
01:22:02Here we are.
01:22:03And let's copy in that code here.
01:22:06And here we just spit out some lorem ipsum dummy paragraph.
01:22:11And now we need a seeder.
01:22:12So, now we got the factory that can pump out fake data.
01:22:15But what do we want to do with the fake data?
01:22:17We want to get it into the database.
01:22:19And that's where a seeder comes in.
01:22:23So, we want to create one.
01:22:24And these are general concepts.
01:22:26Factory seeders.
01:22:27You don't just know them from Adonis.
01:22:28You know them from Laravel.
01:22:29Or you could use these concepts in any setup.
01:22:37Also, in an XJS application, you might have a database which you want to seed with some data there.
01:22:41Obviously, the node ace commands are Adonis specific though.
01:22:45But now we create a seeder.
01:22:47And let's take a look at the post seeder.
01:22:49So, that's now a file which we can run to push some initial data into the database.
01:22:54And therefore, we need to define what we want to do in here.
01:22:57And I would guess what we want to do in here is create some dummy posts and comments, connect them, and then run something to get it into the database.
01:23:07However, that looks like in Adonis.
01:23:10So, let's paste it in and take a look.
01:23:13So, we are finding or failing.
01:23:17So, we are trying to find a user.
01:23:19And that should fail.
01:23:21Because it doesn't say that it creates one and we don't have that user.
01:23:25So, we try to find that user.
01:23:26We will have to create it.
01:23:28Then we merge this user.
01:23:33And we create many new posts and basically link them to that user with this command.
01:23:37And then for each of these posts, we create some dummy comments, which we also then connect to that post and to that user.
01:23:46And we create some random number of comments plus three.
01:23:51So, at least three comments, but up to six comments in total for each post.
01:24:02So, between three and six comments.
01:24:06First, we fetch a user with this email.
01:24:09This is the user we created in the previous chapter with the O.
01:24:12So, I will create that user myself.
01:24:15Let me quickly do that.
01:24:19Let's serve this.
01:24:23Well, I haven't tried to running the Cedar yet.
01:24:26So, that should work.
01:24:27But that's wrong.
01:24:28Let me quickly sign up.
01:24:34Yeah, yeah, yeah.
01:24:36No, not this.
01:24:37Let's.
01:24:39I will use.
01:24:44Okay.
01:24:45So, I will use a different email address.
01:24:47Obviously, I will use.
01:24:50Test at example.com.
01:24:52Okay.
01:24:53So, we get that.
01:25:02Yes, please keep going.
01:25:03Such streams.
01:25:03We like them.
01:25:04Yeah, I definitely want to keep them going.
01:25:06And, by the way, my plan is to have a stream like this every Thursday.
01:25:13Next week, I won't be able to do it.
01:25:16I got some other appointments there.
01:25:18But, in general, every Thursday this time, so starting at 5 p.m. Central European summertime, that is my plan.
01:25:26So, to me, it looks like Anthropic really wants to push their own tools.
01:25:40They want to push Claude code and nothing else.
01:25:42They want to lock people in there.
01:25:43So, we'll see.
01:25:45I'm not too confident that we'll be able to use Claude in all kinds of other tools.
01:25:51At least not with the subscription paying for tokens.
01:25:55That will probably be possible because you're just using the API then.
01:25:58But, that's, of course, also super expensive.
01:26:02So, let's now run the seeder.
01:26:06Cancel this server.
01:26:09Run it.
01:26:10And, that now created the dummy data.
01:26:12And, we should be able to see it already, even without the app being ready.
01:26:17In the database, we can see posts and comments tables.
01:26:21In the users table, I got my user.
01:26:23And, in the posts table, we get some dummy posts here.
01:26:27And, in the comments table, we get some dummy comments.
01:26:33And, each comment is linked to a certain user and post ID.
01:26:36Obviously, we only have one user here.
01:26:38So, they're all linked to that one user.
01:26:40That was what we wrote in the seeder.
01:26:41And, then for the posts, we see here we got a post with, what is that, five comments.
01:26:47Here, we got one with three comments and so on.
01:26:50So, that's in line with what we wrote.
01:26:52Okay.
01:26:53So, I understand what we did here.
01:26:55Querying data with the REPL will not do that.
01:26:57We already saw that it's there.
01:27:00But, yeah.
01:27:01But, we'll take a look at the code here.
01:27:02So, the interesting thing, of course, is that with that model-based approach, you don't write SQL queries or anything like that.
01:27:10Instead, what you do is you use your model or you access all the models.
01:27:17Then, your model, and this exists because we registered a model with that name.
01:27:20And, then you can use methods like all to get all posts.
01:27:24Or, as we see here, you can write queries where you have some where clause to limit the number of posts.
01:27:30And, that is how an ORM works.
01:27:32You programmatically query your data and you don't write SQL statements.
01:27:37Now, to be very honest, I'm not a huge fan of ORMs or I have nothing against them, but I'm not using them typically.
01:27:46And, especially nowadays with AI, I find writing raw SQL queries easier than ever.
01:27:52So, for me, I typically use raw SQL queries in my applications.
01:27:58I don't use ORMs.
01:28:00Because, of course, you've got the full power if you write raw queries.
01:28:06And, even before AI, many, many queries weren't that difficult, to be honest.
01:28:10Even with joins, that's not that hard.
01:28:13And, of course, SQL queries can get quite complex and AI can get it wrong.
01:28:18But, in my experience, it's pretty decent at most queries, including more complex ones.
01:28:22So, that's just my two cents.
01:28:24But, here, we're using the ORM, so I'll stick with it.
01:28:29Routes, controllers, and views.
01:28:32In the previous chapter, we created the post and comment models with their database tables and relationships.
01:28:37Now, we'll bring those models to life by building pages where users can actually see posts.
01:28:46Your posts and comments exist only in the database.
01:28:49The server is already up.
01:28:52So, now, we want to create a new controller.
01:28:54And, the idea with this framework, as I understand it, is that you have a route, you have a controller, and you have a view.
01:29:02So, good old MVC, if some of you remember.
01:29:07Model view controller.
01:29:09It's quite an old way of structuring your applications, not just web applications.
01:29:18But, old doesn't mean bad, just to be very clear about this.
01:29:24But, you don't see it, really, in all those Next.js applications and so on, I guess.
01:29:30So, yeah.
01:29:31In a different tab, let me run this, create a new post controller.
01:29:38Here it is, an empty file, and in there we now register methods, which then define what will happen in four different routes.
01:29:44Again, I'll copy this in to save some time.
01:29:47And, what we have here is an index method.
01:29:52We get some HTTP context here, which, again, is that thing that gives us all kinds of data.
01:29:57And, actually, we have to tweak this, because this here is for, I need to use inertia.
01:30:05I need to use inertia, and, of course, we'll need to add this component.
01:30:09But, what we're doing here is, we're using our post class, so, from our models file, right?
01:30:16So, here, the post class, which we defined before.
01:30:20And, then, again, this is the ORM in action, where we're creating a query.
01:30:24Preloading user is probably there, so that we load it once, and then not again for every post we're fetching, I assume.
01:30:32And, then, we order the posts, obviously, by creation date, descending.
01:30:38So, the first post is the youngest, the most recent one.
01:30:45So, then, we render, and, therefore, we will need to add this.
01:30:53Defining the route.
01:30:56So, now, we have to, yeah, well, the route is that we go to start routes.
01:31:03And, here, we added here.
01:31:07We could add it anywhere, of course.
01:31:10And, why is this not working?
01:31:12Why is this not working?
01:31:13Do I need to restart the dev server, or something like this?
01:31:16Whoops, that's wrong.
01:31:18Oh, I didn't have the dev server up and running.
01:31:21That's my bad.
01:31:22So, now, let's bring it up, and then, hopefully, yeah.
01:31:25Now, this is auto-created.
01:31:26So, basically, Adonis is creating a bunch of type definitions on the fly.
01:31:31So, now, this is here.
01:31:34We tell Adonis that for requests, get requests to slash posts.
01:31:40We want to trigger the index method in the posts controller.
01:31:43And, that, of course, is this method.
01:31:47Now, we will need the view.
01:31:50And, we can make a new view.
01:31:53I don't know if this is the right command, if I want to have an inertia view.
01:31:56So, let's see.
01:31:59I can run node as list to see what I can make.
01:32:04So, I can make a view, but that's an edge.js template file.
01:32:08I don't want that.
01:32:11Maybe I do have to create it by hand.
01:32:20Looks like I have to create it by hand, but that shouldn't be too difficult.
01:32:24So, let's go to inertia pages.
01:32:29So, in there, I would now add posts.
01:32:31And, in there, add an index.js file, right?
01:32:34And, then, I export a default function.
01:32:38And, I'll name it posts.
01:32:41And, I'll say something like my posts.
01:32:44So, just a regular React component.
01:32:50Now, this error here is gone.
01:32:51Because, now, I did add that thing, right?
01:32:55So, I did add a posts folder with an index.js file.
01:32:58And, that is exactly what I said here.
01:32:59So, this is how this is linked up.
01:33:02And, there, for now, of course, with the development server up and running,
01:33:05I can go here, enter /posts, and I see my posts here.
01:33:09So, that's working.
01:33:10And, now, of course, we just need to get the data from the controller into that component.
01:33:20And, actually, we're already doing that here, I assume, as props.
01:33:23So, the question is, if, in here, we get this.
01:33:30Now, how do I...
01:33:33Oh, no, I think we have to do children.
01:33:36How does this work in the other file here?
01:33:40Do we have any file where we transmit data?
01:33:45We don't.
01:33:46We don't, we don't, we don't, we don't.
01:33:50In the layout, right?
01:33:52Children.
01:33:54So, I assume this is what I need.
01:33:58But, I never did this before.
01:34:00So, we'll have to figure this out.
01:34:19Is this not what we have here?
01:34:23Oh, yeah, my bad, my bad, my bad.
01:34:25This is not valid TypeScript code, of course.
01:34:27This should be like this.
01:34:30Okay.
01:34:30So, now, we need to add those at import.
01:34:36At import.
01:34:38So, I assume this is correct.
01:34:40Is that what we have here?
01:34:41Data generated data.
01:34:42Yeah.
01:34:43Okay.
01:34:45Okay.
01:34:45So, now, let's see.
01:34:46Can we add like a fragment here?
01:34:50And then do something like.
01:34:54Children.
01:34:57Props.
01:34:59Hmm.
01:35:02User.
01:35:03Yeah, maybe it's not the share props.
01:35:04How do I get the.
01:35:06I probably have to dive into the.
01:35:10Let's see.
01:35:11I probably have to dive into the docs for inertia here.
01:35:15Guides.
01:35:17Where is here inertia?
01:35:19How do I get props into my components?
01:35:24I need.
01:35:25Do I need a transformer?
01:35:29Use a transformer to serialize model instances into plain objects.
01:35:33Got it.
01:35:34Got it.
01:35:35Got it.
01:35:37Okay.
01:35:37So, what I'll do here is I'll cheat a little.
01:35:40Bring in some AI here.
01:35:44Um.
01:35:48Building an Adonis.
01:35:51JS app.
01:35:53I need to get my posts.
01:35:56See.
01:35:57Post controller.
01:36:02Into my posts inertia.
01:36:04Whoops.
01:36:05I see that this is not readable for you.
01:36:10Okay.
01:36:10Okay.
01:36:10Wait a second.
01:36:18Okay.
01:36:18Building an Adonis.
01:36:20JS app.
01:36:21I need to get my posts.
01:36:24From my posts controller.
01:36:27Add.
01:36:28Oops.
01:36:28Add posts.
01:36:30Controller.
01:36:32Into my posts.
01:36:35View.
01:36:35Inertia.
01:36:37View.
01:36:39So, that is index in the posts folder here.
01:36:45And I'll just link to these pages.
01:36:48Please check out.
01:36:50And.
01:36:56To help me do that.
01:36:59And let's see if it can figure that out.
01:37:03Um.
01:37:03Orms are good for schema transformations and collaboration.
01:37:07Um.
01:37:08Yeah.
01:37:09And again.
01:37:09I don't say.
01:37:10Orms are bad.
01:37:11Just.
01:37:11Just not what I personally need for my project.
01:37:14But then again.
01:37:14I'm not working in any large teams or anything like that.
01:37:18Um.
01:37:18I.
01:37:19I definitely.
01:37:20Do say.
01:37:21That I use migrations though.
01:37:23So.
01:37:23It's not like.
01:37:24I don't.
01:37:25Use migrations.
01:37:26Or anything like this.
01:37:27Um.
01:37:28I just also.
01:37:29Write them myself.
01:37:30Or have.
01:37:31LLMs write them.
01:37:32So migrations are very useful.
01:37:34I just don't need the ORM part.
01:37:36I was wondering.
01:37:36To ask you about.
01:37:37Wipe coding.
01:37:38Is good or not.
01:37:39I don't think.
01:37:40Wipe coding.
01:37:41Is good for.
01:37:42Anything serious.
01:37:43But.
01:37:44Wipe coding.
01:37:44Definitely is very good.
01:37:45If you just need.
01:37:46A quick.
01:37:47Utility tool.
01:37:48Or if you just need.
01:37:48To get a job done.
01:37:50Right.
01:37:50If you're building some software.
01:37:51You're selling.
01:37:52If you're.
01:37:53Working on anything serious.
01:37:55Which you plan on distributing.
01:37:56Or in your job.
01:37:57Wipe coding.
01:37:58Just lets you lose.
01:37:59All track.
01:38:00You don't understand.
01:38:01What's going on in the code base.
01:38:02And eventually.
01:38:03You'll hit a wall.
01:38:04And you won't.
01:38:04Know how to continue.
01:38:06So.
01:38:07Not caring about the code.
01:38:08Is not a good solution.
01:38:09For.
01:38:09For such situations.
01:38:11But again.
01:38:11If you just need.
01:38:13Um.
01:38:13A quick.
01:38:15Tool.
01:38:16Which you run on your machine.
01:38:17Or anything like that.
01:38:18You may not care about.
01:38:19Um.
01:38:20About the.
01:38:21All the details.
01:38:23And stuff.
01:38:24So yeah.
01:38:25Vipe coding can be good there.
01:38:26And yeah.
01:38:26Live coding is always.
01:38:28Always challenging.
01:38:29But we'll see if the AI can figure it out.
01:38:31It seems to be fighting some linting errors here.
01:38:36But yeah.
01:38:38I am just using AI.
01:38:40By the way.
01:38:40Normally I would dive in here.
01:38:41And build it myself.
01:38:44But I have to go in 20 minutes.
01:38:47And I rather get the finished code now.
01:38:49And work my way through that.
01:38:51And now.
01:38:52So that we can also thereafter continue here.
01:38:54That's the main reason.
01:38:56So okay.
01:38:56Now it did something here.
01:38:58And let's first see if it works.
01:39:00Before I start explaining it.
01:39:02And then we'll see what it did.
01:39:04But it looks good.
01:39:05Styling is totally awful.
01:39:07But as we can see.
01:39:10I got a bunch of posts being rendered here.
01:39:12And I can see that they are linked to my user.
01:39:16So.
01:39:17Sending the data from the controller.
01:39:19Seems to work.
01:39:19So let's now see.
01:39:20How it works.
01:39:22And again.
01:39:22I gave it the links to the official docs.
01:39:24So that is just.
01:39:28That is just.
01:39:31What the docs would have taught us to.
01:39:34So in a post controller.
01:39:36We're getting the posts.
01:39:38The only thing that changed here.
01:39:39Is essentially.
01:39:40That we.
01:39:41Pass our posts.
01:39:42But not raw like this.
01:39:43But instead.
01:39:44With help of a post transformer.
01:39:45That is a new thing it added.
01:39:47So this file is new.
01:39:48Post transformer.
01:39:50And that is a class.
01:39:51Which extends base transformer.
01:39:53Okay.
01:39:53And in there.
01:39:54We just describe.
01:39:55How to serialize a post.
01:39:56So we're saying.
01:39:57Hey.
01:39:58Pick all these properties.
01:40:01And.
01:40:02For the user.
01:40:03Also transform the user.
01:40:04So essentially.
01:40:05I mean in this case.
01:40:06Transforming should be pretty simple.
01:40:08It just probably takes.
01:40:11The ISO.
01:40:12Format.
01:40:13Dates here.
01:40:14And the other raw data.
01:40:15Can be packed.
01:40:16Into a javascript object.
01:40:17Like this.
01:40:18So it basically.
01:40:19Describes.
01:40:20How to convert.
01:40:21The class.
01:40:21Which may contain stuff.
01:40:23That can't be easily converted.
01:40:25To json.
01:40:26How to convert.
01:40:27That to json.
01:40:28That is.
01:40:28The job of the transformer.
01:40:30As I understand it.
01:40:33Okay.
01:40:33So then we set the posts here.
01:40:34And now.
01:40:35In the view.
01:40:40In the view.
01:40:41We get page.
01:40:42Okay.
01:40:43We just set up.
01:40:43Page props like this.
01:40:44Okay.
01:40:45We just set up.
01:40:46A props type.
01:40:47Type script type.
01:40:48Using inertia props.
01:40:51Instead.
01:40:51Some generated types.
01:40:54Or did.
01:40:55DAI.
01:40:56Add that.
01:40:57I assume.
01:40:58It's some.
01:40:58Some standard types.
01:41:00Not.
01:41:00Not generated by the AI.
01:41:02And.
01:41:02We just say.
01:41:03Okay.
01:41:03Hey.
01:41:04Here.
01:41:04We'll have a post key.
01:41:06And.
01:41:06That is.
01:41:07Of type.
01:41:08Yeah.
01:41:08So that's.
01:41:09An auto generated.
01:41:10Type here.
01:41:10For.
01:41:11For our posts.
01:41:12And I assume.
01:41:13This type.
01:41:14Is generated.
01:41:15Based on how.
01:41:15We transform.
01:41:16The posts.
01:41:17So post here.
01:41:20This thing.
01:41:23Yeah.
01:41:24Is coming from the post transformer.
01:41:25Exactly.
01:41:27Okay.
01:41:28And then we can just.
01:41:29Render them here.
01:41:30It's not too difficult.
01:41:32Got it.
01:41:35Okay.
01:41:36Now again.
01:41:36The official tutorial here.
01:41:38Uses the edge view.
01:41:39So.
01:41:39I'm using inertia.
01:41:40And.
01:41:41As you see.
01:41:41It's just a react app.
01:41:43In the end.
01:41:44Where we also then.
01:41:46Transform and.
01:41:46And send our.
01:41:48Props.
01:41:50Okay.
01:41:53Displaying a single.
01:41:54Post.
01:41:55Yeah.
01:41:55Sure.
01:41:55So now.
01:41:56We can add.
01:41:56Another.
01:41:58Method here.
01:42:00In our.
01:42:00Controller.
01:42:01Because.
01:42:02In our.
01:42:02Post.
01:42:03Controller.
01:42:03At the moment.
01:42:04We have one.
01:42:05Index.
01:42:05Method.
01:42:05For.
01:42:06Displaying.
01:42:07All the posts.
01:42:08But now.
01:42:08We want to.
01:42:08Also.
01:42:09Add a method.
01:42:09For.
01:42:10Displaying.
01:42:10A single.
01:42:10Post.
01:42:11So.
01:42:11We are adding.
01:42:12A show.
01:42:12Method.
01:42:12Here.
01:42:13As it seems.
01:42:14And again.
01:42:14These names.
01:42:16Are up to you.
01:42:16And later.
01:42:17When you connect.
01:42:18Them.
01:42:18In the.
01:42:19Routes.
01:42:19File.
01:42:19You.
01:42:20Must make sure.
01:42:20That they match.
01:42:21But we'll see.
01:42:21That in a second.
01:42:23So here.
01:42:23We're getting some.
01:42:24Params.
01:42:25Because now.
01:42:25We have.
01:42:26A dynamic.
01:42:26Route.
01:42:26And again.
01:42:27You may know.
01:42:28That from.
01:42:28React.
01:42:28Or so on.
01:42:29That's the.
01:42:29Routes.
01:42:30With the.
01:42:30With the.
01:42:31Colon.
01:42:31Parameters.
01:42:32In the.
01:42:32Route.
01:42:33Name.
01:42:33For example.
01:42:34Or the.
01:42:34Dollar.
01:42:35Signs.
01:42:35In the.
01:42:35File.
01:42:36Name.
01:42:37So here.
01:42:38We are also.
01:42:38Getting some.
01:42:39Dynamic.
01:42:39Parameters.
01:42:40And we'll see.
01:42:40How we register.
01:42:41Those routes.
01:42:42In just a second.
01:42:43And then.
01:42:43We expect.
01:42:44To have.
01:42:44An ID.
01:42:45Parameter.
01:42:46So we're.
01:42:46Looking for.
01:42:46A post.
01:42:47With a specific.
01:42:48ID.
01:42:49We want.
01:42:49To fail.
01:42:50If we don't.
01:42:50Find it.
01:42:51So that we can.
01:42:52Show a 404 error.
01:42:53Or any other error.
01:42:54I assume.
01:42:55We want.
01:42:55To render.
01:42:57Not a view.
01:42:58Instead.
01:42:58We want.
01:42:59To render.
01:43:05We want.
01:43:05To get.
01:43:06Inertia here.
01:43:09And we reuse.
01:43:10Our post.
01:43:11Transformer.
01:43:12To pass.
01:43:13Our post.
01:43:14To.
01:43:17To a show.
01:43:18Component.
01:43:18For example.
01:43:19So.
01:43:20Now.
01:43:20In the inertia.
01:43:21Folder.
01:43:21In the post.
01:43:22Folder.
01:43:22We need.
01:43:23To have.
01:43:23Show.
01:43:24TSX.
01:43:24Or.
01:43:25Detail.
01:43:26TSX.
01:43:26Or.
01:43:26Anything.
01:43:27Like that.
01:43:28And.
01:43:29Now.
01:43:29In there.
01:43:31We have.
01:43:35Our.
01:43:35Our.
01:43:35Post.
01:43:36Component.
01:43:36Here.
01:43:38Actually.
01:43:40Let's name it.
01:43:42Post.
01:43:45Post.
01:43:47Like this.
01:43:48And then.
01:43:49Just as before.
01:43:50I'll.
01:43:50Quickly.
01:43:51Steal that.
01:43:55We get.
01:43:55A single post.
01:43:56Here.
01:43:56No array.
01:44:00Select this.
01:44:01And then.
01:44:01We can.
01:44:02Return.
01:44:05Yeah.
01:44:05Sure.
01:44:06The post.
01:44:06Title.
01:44:07Like this.
01:44:11Hello.
01:44:12Yeah.
01:44:12Like this.
01:44:13Okay.
01:44:16What are we doing here?
01:44:17So.
01:44:19And then.
01:44:19Of course.
01:44:19Also.
01:44:20The.
01:44:21The post.
01:44:21Summary.
01:44:21For example.
01:44:22Sure.
01:44:23Okay.
01:44:23So we get this.
01:44:24Uh.
01:44:25Should work.
01:44:26Now.
01:44:27We need to register it.
01:44:28In the routes folder.
01:44:30So now.
01:44:30We can add a new.
01:44:31Whoops.
01:44:32A get route.
01:44:33For slash.
01:44:34For slash.
01:44:35Posts.
01:44:35And then.
01:44:36I assume.
01:44:37That is how we register.
01:44:38Dynamic routes.
01:44:39Let's see.
01:44:41Yeah.
01:44:42With colon ID.
01:44:44Pretty typical.
01:44:45And now.
01:44:46We're saying.
01:44:46Hey.
01:44:47In our post controller.
01:44:48It's the show method.
01:44:49We're interested in.
01:44:51Because.
01:44:52In that controller.
01:44:53We named this method.
01:44:54Show.
01:44:54If you pick the different name here.
01:44:56We have to pick a different name here too.
01:44:58But show is the name I'm using.
01:44:59So that should work.
01:45:02So.
01:45:05Which links do we have here?
01:45:08Oh.
01:45:08That's not a link to a detail.
01:45:10But if I add posts one.
01:45:13Yeah.
01:45:14I do load.
01:45:15The styling is totally off.
01:45:16But here at the very bottom.
01:45:17We can see the.
01:45:18The content.
01:45:19So.
01:45:20And.
01:45:21The title.
01:45:22Markdown blog engine.
01:45:24Is also here.
01:45:25So it's just totally broken styling.
01:45:26But.
01:45:27It works.
01:45:28We can see that route.
01:45:31And we could of course fix the styling.
01:45:32But that's not the most important thing right now.
01:45:35So yeah.
01:45:36We got the view.
01:45:37We already got all of that.
01:45:39Using the named routes.
01:45:40Oh that's interesting.
01:45:40Yeah.
01:45:41Right now we're hard coding URLs.
01:45:44And I am actually not setting up any links at all.
01:45:47So.
01:45:49When you use a controller in your route definition.
01:45:51Adonis.js automatically generates a route name.
01:45:54Based on the controller and method names.
01:45:56So if we have controllers dot posts index.
01:45:58That is.
01:45:59That gets the name posts dot index automatically.
01:46:02So I assume we could go to the.
01:46:05Posts index page where we have all those posts.
01:46:08And instead of using an anchor tag like this.
01:46:11We could use.
01:46:12The link component.
01:46:13Which comes from inertia.js react.
01:46:17Also here.
01:46:18And then I'm not sure.
01:46:19Has it a to prop.
01:46:21Or is it.
01:46:21Is it ref.
01:46:23And then we could say something like.
01:46:26Routes.
01:46:29Posts show.
01:46:34Doesn't seem to work like this.
01:46:42Posts show.
01:46:49Yeah.
01:46:49I'm using a different approach.
01:46:50I want to use this link component.
01:46:53Again.
01:46:55Do we have that in here somewhere?
01:46:57Link route.
01:46:59Oh okay.
01:46:59It's just.
01:47:01Okay.
01:47:02So it's link.
01:47:04Route.
01:47:08Why am I getting an error here for a route?
01:47:11Creating links.
01:47:12The link component creates navigation links.
01:47:14Oh.
01:47:15The import is wrong.
01:47:16I need to import that from.
01:47:20Here.
01:47:20From the Adonis package.
01:47:22Now we have support for the route.
01:47:24Now it's just posts.
01:47:33It's just a string.
01:47:34It's just a string.
01:47:35Okay.
01:47:35So it's just.
01:47:37Route.
01:47:38Okay.
01:47:38Now we get some auto completion here.
01:47:40And now I need to set the params.
01:47:43Route params.
01:47:45Posts dot id.
01:47:48No.
01:47:49Post dot id.
01:47:53So that must be an object.
01:47:57Id is set to post dot id.
01:48:00And that will now dynamically generate a different route for every post.
01:48:03And populate that dynamic placeholder with the post id I assume.
01:48:07So if I now reload here.
01:48:09Not here.
01:48:10But here.
01:48:14Why was this not updated?
01:48:16Do I need to restart the development server?
01:48:20Oh.
01:48:21Saving the file also probably helps.
01:48:24Yeah.
01:48:24Now I can click here and navigate to these posts.
01:48:28Styling is still awful of course.
01:48:30But that works.
01:48:33And of course.
01:48:34The advantage of using route names here is that if we ever change the path.
01:48:38We don't need to change the links.
01:48:40As long as the route name didn't change.
01:48:42So that's of course nice to have.
01:48:44Now.
01:48:45You might not change the path all too often.
01:48:47But still.
01:48:48Pretty nice.
01:48:52Hi.
01:48:52It's kiddie me.
01:48:53And yeah.
01:48:55It is inspired by by laravel.
01:48:57It's absolutely.
01:48:58It's I think they themselves brand themselves as laravel for javascript.
01:49:07Do you have to write software with your hands?
01:49:09That's like a baby's toy.
01:49:12Well.
01:49:17So.
01:49:18When you learn something.
01:49:19I would definitely do stuff.
01:49:21I would definitely write code with hands.
01:49:23because just by reading.
01:49:26I'd do a mixture.
01:49:28But of course for a live stream.
01:49:29I don't find it too interesting.
01:49:30If I just let the AI rip through it.
01:49:33But I did use it just a couple of minutes ago.
01:49:36But yeah.
01:49:37For learning you should definitely.
01:49:39Get in there.
01:49:40And reading alone.
01:49:44Reading alone doesn't teach stuff that well.
01:49:46Now.
01:49:47I will not say that you will write all the code.
01:49:50Like you did maybe four years ago.
01:49:52Not even close to it.
01:49:54But at least some basics.
01:49:56To get a feeling.
01:49:56I mean here.
01:49:57You just joined right.
01:49:58But I was just copying.
01:49:59What I wrote basically no.
01:50:01Um.
01:50:03Code.
01:50:03Yeah.
01:50:03Yeah.
01:50:03I know.
01:50:04I got you.
01:50:05No offense taken.
01:50:06It's just.
01:50:07I think writing code.
01:50:09It's just in general a good point.
01:50:10That's why I'm just commenting on it.
01:50:12I think.
01:50:14Writing code is still good for for learning.
01:50:18But.
01:50:19Even though that was a joke.
01:50:21Or a quote.
01:50:24It's.
01:50:26It's.
01:50:26It's obviously changing.
01:50:28And I got asked earlier.
01:50:32About new courses.
01:50:33And one problem.
01:50:34Or what I'm trying to figure out.
01:50:35is how you.
01:50:37Best learn technologies right now.
01:50:41And if it still matters.
01:50:42And I would say yes.
01:50:43It definitely still matters.
01:50:45But yeah.
01:50:46Exactly that point.
01:50:47How much do you write by hand?
01:50:48How much do you copy in?
01:50:50How much do you let AI explain or generate that?
01:50:52That's.
01:50:53I'm just rambling on.
01:50:54I'm just rambling on.
01:50:54But that is definitely something which is changing.
01:50:57And this is Adonis JS.
01:51:00So it's.
01:51:00It's basically Laravel for JavaScript.
01:51:09Okay.
01:51:09So.
01:51:14Yeah.
01:51:15Comments.
01:51:16I don't think I'll do that.
01:51:18And I got to go in 10 minutes.
01:51:20So we'll probably leave it as is here.
01:51:22And just take a brief look at the remaining few.
01:51:28Pages here.
01:51:29It's not much left in this guide anyway.
01:51:31So we went through it pretty well.
01:51:33Forms and validation.
01:51:35So here the idea is.
01:51:37That of course we can also have controller func.
01:51:40Controller methods that are invoked.
01:51:43Upon post requests.
01:51:45And we can see that in the.
01:51:48Do we not have a user controller?
01:51:52User.
01:51:54This.
01:51:54The new account controller.
01:51:56Here.
01:51:57Store.
01:51:57That is.
01:51:59A controller method.
01:52:00That is invoked.
01:52:02Upon a post request.
01:52:04This one.
01:52:05And.
01:52:06Therefore.
01:52:07It's just a regular method.
01:52:08But in there we can already see.
01:52:10You can use the validate using.
01:52:13Method.
01:52:13And define a validator.
01:52:14Which is in the end.
01:52:16Just a little utility object.
01:52:18Created with that vine tool here.
01:52:21Where you can define some rules.
01:52:22For which kind of data you want to accept.
01:52:24And then.
01:52:24Errors will be generated automatically.
01:52:26For you if.
01:52:27If the validation criteria is not met.
01:52:29So the entire idea.
01:52:30Behind Laravel.
01:52:30And Adonis.
01:52:31Is that they do a lot of work for you.
01:52:33And you can.
01:52:33Define your logic.
01:52:34On a pretty high level.
01:52:36Whereas.
01:52:37In next.
01:52:37JS.
01:52:37And so on.
01:52:38You often have to really become specific.
01:52:41And obviously.
01:52:41You have to bring your own validation library.
01:52:43And all that fun stuff.
01:52:52So what we're doing here.
01:52:54Is registering the routes.
01:52:56We already saw that.
01:52:59Creating a new view in this case.
01:53:00And here they're creating a forum.
01:53:02Now these are all some edge specific.
01:53:05Code snippets.
01:53:06But of course.
01:53:08We have that here as well.
01:53:12Where is it?
01:53:13Log in.
01:53:14Yeah.
01:53:14We can see that if we're using inertia.
01:53:17We have this form component here.
01:53:19Which is coming from the Adonis.js inertia package.
01:53:22Which is also linked to a route.
01:53:24That should be triggered.
01:53:25If the form is submitted.
01:53:26Which is that store route.
01:53:27We just saw.
01:53:28Or that store controller action.
01:53:30That's in the end.
01:53:31Invoked by that route.
01:53:33And the data.
01:53:34I assume is.
01:53:36Packed into the request.
01:53:37And submitted to the backend automatically.
01:53:39Which is of course convenient.
01:53:40That you don't have to write the code for that yourself.
01:53:42Or ask the AI to write it for you.
01:53:45If you're using edge.
01:53:46You can render your form inputs like this.
01:53:48And arguably.
01:53:50This is a bit easier to reason about.
01:53:51And read I would say.
01:53:56And then we can create validators.
01:53:57We saw one already before.
01:53:58With that wine thing.
01:54:00Where you simply define.
01:54:01For the data.
01:54:02You're about to receive.
01:54:04What are your rules.
01:54:05So min length.
01:54:06Max length.
01:54:07Data type.
01:54:08And so on.
01:54:10Get the store method.
01:54:11And then again.
01:54:11We can use the ORM.
01:54:13Use our class.
01:54:14Call the static create method.
01:54:16To store the data.
01:54:19Comments.
01:54:20Do the same thing.
01:54:23Also link it to a user.
01:54:24Through the ID.
01:54:26And we get the user.
01:54:28Through that auth.
01:54:30Property.
01:54:31Which we get automatically.
01:54:32And again.
01:54:33That is like.
01:54:33Adonis doing its thing.
01:54:35And doing the authentication for you.
01:54:37Thanks to the middleware.
01:54:39That is registered.
01:54:40Right.
01:54:40So in routes.
01:54:40We get some.
01:54:41Off middleware.
01:54:42For example.
01:54:43And any routes in here.
01:54:44Require authentication.
01:54:46And any routes in there.
01:54:48Therefore.
01:54:48Also.
01:54:51Also get this auth.
01:54:53Property.
01:54:54Which you can use.
01:54:55To get the data.
01:54:56About the currently.
01:54:57Authenticated user.
01:54:58Or which you can use.
01:54:59To log the user out.
01:55:00Like in this case.
01:55:01And so on.
01:55:02So that is all.
01:55:03Pretty convenient.
01:55:04Once it is set up.
01:55:06I assume at least.
01:55:07It is not like.
01:55:08I have worked with that before.
01:55:09But yeah.
01:55:11I have learned.
01:55:11View free from you.
01:55:12And forwarded the principles.
01:55:14To codecs.
01:55:14Such as codecs.
01:55:15Writes high quality.
01:55:16So your lessons.
01:55:16Are still valuable.
01:55:17For good prompting.
01:55:18Yeah.
01:55:18And one thing I am exploring.
01:55:20Is also.
01:55:20How can you.
01:55:22For future courses.
01:55:23Include stuff.
01:55:24Like agent skills.
01:55:25Or extra documents.
01:55:26That you can feed.
01:55:27To your agents.
01:55:28To help them.
01:55:31Write better code.
01:55:32Though of course.
01:55:33It will never be a guarantee.
01:55:34Because agents.
01:55:37Can always do it.
01:55:38Their own thing.
01:55:39And so on.
01:55:40But that is something.
01:55:40I am also exploring.
01:55:41Of course.
01:55:42And do I prefer.
01:55:43Adonis or View 3.
01:55:45So Adonis.
01:55:46I really just.
01:55:47Got started with.
01:55:48I haven't used it.
01:55:49At all before.
01:55:50And View 3.
01:55:52Is not really.
01:55:52An alternative.
01:55:53Because Adonis.
01:55:54Is full stack.
01:55:55And View.
01:55:55Is client side.
01:55:57Front end.
01:55:58With Nuxt.
01:55:59It would be full stack.
01:56:00Again.
01:56:00But then.
01:56:01We would still have.
01:56:02Different philosophies.
01:56:03Where Adonis.
01:56:04Is batteries included.
01:56:06So.
01:56:06All that stuff.
01:56:07Like the authentications.
01:56:08On built in.
01:56:09Whereas with Nuxt.
01:56:11Just like.
01:56:11Just like with Next.
01:56:12You have to bring.
01:56:13Your own.
01:56:14Libraries.
01:56:15And ultimately.
01:56:16I don't know.
01:56:17What I prefer.
01:56:17I like.
01:56:18The Adonis approach.
01:56:19And I definitely.
01:56:21See it.
01:56:22Being valuable.
01:56:23If you're building.
01:56:25A full stack.
01:56:27Application.
01:56:28Now.
01:56:28I'm.
01:56:29So used.
01:56:30To Next.
01:56:31JS.
01:56:31To 10.
01:56:32Stack start.
01:56:33And all that stuff.
01:56:34That I.
01:56:35I don't know.
01:56:36If I would switch.
01:56:37To Adonis.
01:56:37Just because.
01:56:38I'm probably.
01:56:39Faster.
01:56:40With those.
01:56:41Other.
01:56:41Tech stacks.
01:56:43But.
01:56:44But then again.
01:56:45There are good reasons.
01:56:46Like.
01:56:46Having.
01:56:47Less.
01:56:48External.
01:56:49Dependencies.
01:56:50Besides Adonis.
01:56:51And so on.
01:56:51So.
01:56:52I will probably.
01:56:53Continue.
01:56:54Playing around with it.
01:56:55And then.
01:56:55Evaluate.
01:56:56Where it's useful.
01:56:57For me.
01:56:58Where it isn't.
01:56:58If I want to build more.
01:57:00With it.
01:57:02Yeah.
01:57:03That's.
01:57:03That's essentially.
01:57:04The plan.
01:57:05And I think.
01:57:07Well.
01:57:07No.
01:57:08Will not.
01:57:08And yet.
01:57:09I don't care too much.
01:57:10About styling.
01:57:10That's just CSS.
01:57:12But authorization.
01:57:13I want to take a look at that.
01:57:16So there's another package.
01:57:18We can install.
01:57:19That's part of the Adonis.
01:57:20Ecosystem.
01:57:21The balancer package.
01:57:22Which is there to.
01:57:24Find a name.
01:57:25And the name of this chapter.
01:57:27I would say.
01:57:27It's.
01:57:28It's responsible.
01:57:29For blocking people.
01:57:30That are not allowed.
01:57:31To do something.
01:57:33And of course.
01:57:35Authorization.
01:57:36Unlike authentication.
01:57:37Is about.
01:57:39Blocking users.
01:57:40From doing certain things.
01:57:41They are not allowed.
01:57:42To do.
01:57:43So for example.
01:57:44A user could be logged in.
01:57:46But of course.
01:57:46Should not be able.
01:57:47To edit the posts.
01:57:48By another user.
01:57:49Makes sense.
01:57:51So.
01:57:52Authentication alone.
01:57:52Is not enough.
01:57:53Often you need.
01:57:54Authorization.
01:57:55In addition.
01:57:57And that is where.
01:57:57This bouncer package.
01:57:58Seems to be useful.
01:58:01Because then.
01:58:01You can create.
01:58:02So-called policies.
01:58:03As it seems.
01:58:04And let's take a look.
01:58:05A policy is a class.
01:58:07Which extends.
01:58:07A class.
01:58:08From Adonis.
01:58:09From the bouncer.
01:58:10Package here.
01:58:11And we can then define.
01:58:13Okay.
01:58:13So we can basically.
01:58:15Define permissions here.
01:58:16Like.
01:58:17Editing is allowed.
01:58:18If the user ID.
01:58:20Matches the ID.
01:58:21Of the user.
01:58:22Of the post.
01:58:23We're trying to edit.
01:58:24The same for deleting.
01:58:26And then we can probably.
01:58:27Apply those policies.
01:58:29Let's see.
01:58:30We.
01:58:30We have them.
01:58:34Add controller methods.
01:58:43Where are we applying.
01:58:44Oh yeah.
01:58:45Here.
01:58:45So.
01:58:46In our controller.
01:58:48We.
01:58:48Here.
01:58:49They added a new method.
01:58:50An edit method.
01:58:51Which should be triggered.
01:58:52Obviously.
01:58:52If you like.
01:58:53Try to submit a form.
01:58:54Where you want to edit a post.
01:58:56Or where you.
01:58:57Probably want to load a page.
01:58:58For editing a post here.
01:58:59Now that I look at it.
01:59:01And in this method.
01:59:02We're.
01:59:03Finding the post.
01:59:04You want to edit.
01:59:05But then.
01:59:06Before returning the view.
01:59:08This bouncer package.
01:59:09Gives us a bouncer thing.
01:59:11Where we load.
01:59:12A policy.
01:59:13We want to apply.
01:59:14And where we basically.
01:59:15Check through the policy.
01:59:16If the user.
01:59:17That is trying to edit this.
01:59:19Is allowed to do so.
01:59:23Makes sense.
01:59:25Okay.
01:59:27So let's see.
01:59:29Chat.
01:59:30AI can build an app.
01:59:31In 10 different ways.
01:59:32In the same library.
01:59:33So maybe focus on.
01:59:34Programming paradigms.
01:59:35On how to organize code.
01:59:37Yeah.
01:59:38Absolutely.
01:59:38I think that.
01:59:39These are the important skills.
01:59:41For both developers.
01:59:42And AI.
01:59:44Through documents.
01:59:45Through skills.
01:59:46That you teach.
01:59:47At certain patterns.
01:59:48That you know.
01:59:49Your fundamentals.
01:59:50And stuff.
01:59:51And that's why.
01:59:52I'm also planning.
01:59:53Courses on programming.
01:59:54Fundamentals.
01:59:55Systems design.
01:59:55And all that fun stuff.
01:59:57When there is a better bet.
01:59:58To do back-end web API.
02:00:00In strongly typed languages.
02:00:01Like C sharp.
02:00:02And.
02:00:03Not sure.
02:00:03Why it was censored here.
02:00:05Or rely on Node.js.
02:00:06With TypeScript.
02:00:07Which types are erased.
02:00:08And there are tons of vulnerabilities.
02:00:09In NPM packages.
02:00:12So ultimately.
02:00:13Regarding the back-end languages.
02:00:15I could probably talk an hour.
02:00:16About just that.
02:00:17And I don't have an hour.
02:00:18But.
02:00:20The huge advantage.
02:00:21Of Node.js.
02:00:22And the entire JavaScript.
02:00:23Ecosystem.
02:00:24Is of course.
02:00:24That AI knows it really well.
02:00:26If you plan on using AI.
02:00:28For development.
02:00:28That there are tons of packages.
02:00:30But of course.
02:00:31There is the huge downside.
02:00:32Of supply chain attacks.
02:00:33And so on.
02:00:34Definitely.
02:00:35And other languages.
02:00:36Can also give you better performance.
02:00:38I would absolutely.
02:00:39Look into using.
02:00:41Go.
02:00:41Rust.
02:00:42C sharp.
02:00:42Whatever you're interested in.
02:00:44For back-end development too.
02:00:45But I will say.
02:00:46That my experience.
02:00:47Is that.
02:00:48You have a high velocity.
02:00:49When using.
02:00:50TypeScript.
02:00:51Because with AI.
02:00:52It's.
02:00:53It knows it so well.
02:00:55And of course.
02:00:56For me.
02:00:56I know it so well.
02:00:57So.
02:00:58I can quickly see the parts.
02:00:59Where AI.
02:01:01Takes a wrong direction.
02:01:02And so on.
02:01:02So.
02:01:04There is that.
02:01:05But.
02:01:06Yeah.
02:01:06Definitely.
02:01:06There is.
02:01:07A lot of merit.
02:01:08In using.
02:01:09Other back-end languages.
02:01:10As well.
02:01:11It doesn't have to be.
02:01:12JavaScript for everything.
02:01:14Why is NestJS more popular?
02:01:16I honestly don't know.
02:01:17I never fully understood.
02:01:19Why not.
02:01:19Why Adonis.
02:01:22It was.
02:01:23And is so niche.
02:01:24I.
02:01:24I.
02:01:25I have no great explanation.
02:01:26For that.
02:01:28But.
02:01:29I now.
02:01:30Have to leave.
02:01:31So.
02:01:32That was interesting.
02:01:32That was fun.
02:01:34Definitely was interesting.
02:01:35To dive into Adonis.
02:01:36And take a look at it.
02:01:37I hope you liked it too.
02:01:39Thanks for joining.
02:01:40Again.
02:01:40I try to be back.
02:01:41Every Thursday.
02:01:42Next week.
02:01:43I won't be able to make it.
02:01:45The week thereafter.
02:01:46I'll have to see.
02:01:47But yeah.
02:01:48I always announce it.
02:01:48In my Discord.
02:01:49So if you're not.
02:01:50Part of it yet.
02:01:51You can head over.
02:01:51To akadamind.com.
02:01:53Slash community.
02:01:54Join the Discord.
02:01:54I announce it there.
02:01:56Or of course.
02:01:56Simply subscribe.
02:01:57Follow me.
02:01:58And then you'll see it.
02:01:59But yeah.
02:02:00Thursday.
02:02:015 p.m.
02:02:03Central European.
02:02:04Summertime.
02:02:05And I typically end.
02:02:06At the time.
02:02:07Where I end now.
02:02:09And yeah.
02:02:09So thank you all.
02:02:11And have a great day.
02:02:13Evening.
02:02:13Morning.
02:02:14Whatever it is for you.
02:02:15And hopefully see you in the future.
02:02:17And yeah.
02:02:17Thank you all for joining.

Key Takeaway

Adonis.js provides a comprehensive, batteries-included alternative to modular JavaScript stacks by integrating core features like ORM, authentication, and view rendering into a single, cohesive framework.

Highlights

  • Adonis.js functions as a full-stack, batteries-included framework for JavaScript, offering built-in authentication, ORM, caching, and rate-limiting.

  • The framework provides three distinct frontend approaches: server-side HTML rendering with Edge templates, React-based development via Inertia.js, and REST API creation.

  • Using a monolithic framework like Adonis.js reduces dependency bloat compared to stitching together numerous individual libraries for backends.

  • The Lucid ORM allows interaction with database tables through JavaScript model classes rather than raw SQL queries.

  • Development environments include built-in commands, migrations for schema changes, and factory/seeder utilities for generating and populating dummy data.

  • Adonis.js maintains a strict separation between backend and frontend, preventing the accidental exposure of server-side code to the client.

Timeline

Adonis.js Framework Philosophy

  • Adonis.js is characterized as a backend-first, type-safe framework for Node.js and TypeScript.
  • It eliminates reliance on third-party services by including essential features like authentication, file uploads, and rate limiting by default.
  • The framework architecture prioritizes a limited set of dependencies to mitigate supply chain security risks.

Adonis.js is frequently compared to Laravel due to its batteries-included approach. Unlike frameworks focused primarily on routing and server-side rendering, Adonis provides its own ORM and native support for complex backend requirements. This integrated structure is intended to improve security by minimizing the need for numerous external library dependencies.

Frontend Integration Strategies

  • Developers can choose between Hypermedia, Inertia.js with React, or a pure REST API approach for the frontend.
  • Hypermedia applications use the Edge template engine to generate HTML on the server and lightweight libraries like Alpine.js for interactivity.
  • Inertia.js serves as a bridge, allowing React components to be server-side rendered without requiring manual data fetching or API endpoint management in the component.

Adonis.js offers flexibility in the view layer. The Hypermedia approach is suited for traditional multi-page applications, while Inertia.js enables a single-page application experience with React while maintaining the benefits of server-side rendering. The choice of frontend strategy does not change the core backend controller logic.

Project Structure and Initial Setup

  • Initialization involves using npm create for the starter kit, with sqlite3 utilized as the default lightweight database.
  • The project structure organizes logic within the app, configuration in config, and database schemas in the database directory.
  • Ace serves as the command-line interface for managing tasks, including running migrations and generating application files.

Setting up an Adonis.js project requires Node.js and the Ace CLI tool to manage life-cycle scripts. The folder structure follows a clear pattern: app for domain logic, config for environment settings, and database for migrations. This structure ensures that server-side concerns remain decoupled from frontend assets stored in the resources folder.

Database Modeling and Relationships

  • Models act as JavaScript classes for data interaction, while migrations define the physical database table structures.
  • Lucid ORM decorators, such as @hasMany and @belongsTo, define relationships between models like posts, comments, and users.
  • Factories and seeders automate the generation and insertion of fake data to facilitate rapid development and testing.

Adonis.js uses a migration-based system to track database evolution. Relationships between entities are established by defining foreign keys in migration files and mapping these associations within the model classes using specific decorators. This workflow allows developers to query complex data sets programmatically without writing manual SQL.

Authorization and Controller Logic

  • Controller methods handle incoming HTTP requests by interacting with models and returning views or serialized data.
  • The Bouncer package manages authorization through policies that verify user permissions before executing sensitive operations.
  • Validation is performed using the Vine library, which enforces data integrity rules and automatically generates error messages.

Controllers leverage the HTTP context to access requests, responses, and authentication states. For authorization, the Bouncer package allows for the creation of policy classes that encapsulate permission logic, such as ensuring only post owners can edit or delete their content. This modular approach keeps authentication and authorization concerns isolated from business logic.

Community Posts

No posts yet. Be the first to write about this video!

Write about this video