In this talk, I will show you how to avoid a monolithic codebase, how to modularize your React app and how that might even help you speed up your CI builds: thus help you scale development as your team grows. We'll be doing this in a very concrete and practical way, using Nx as our toolkit.
Scaling React Development with Nx
AI Generated Video Summary
This Talk discusses Schedule React development with NX and introduces Annex, an open-source dev tool for Monorepos. It covers topics like generating workspaces and libraries, creating public-facing Next.js applications, imposing restrictions and defining boundaries, testing with linting, speed improvements with the 'affected' command and caching, retrofitting NX into an existing Monorepo, migrating, testing, deployment, and publishing, publishable libraries in NX, Webpack 5 module federation, React context API, and managing tags, scope, and dependencies.
1. Introduction to Schedule React Development with NX
I'm super excited to talk about Schedule React development specifically with NX. I'm Jurijs Tromfloner, a Google Developer Expert in web technologies. I work at Nowll, helping teams learn, grow, and be successful. I want to talk about Annex, our open source dev tool designed for Monorepos. It leads to a better architecture with thin applications and well-defined workspace libraries. I'll show you how to work with Annex by creating a workspace and using presets.
All right, so I'm super excited to be here today and be able to talk to you about Schedule React development specifically with NX. So, before starting, let me first introduce myself. My name is Jurijs Tromfloner. I'm a Google Developer Expert in web technologies. I'm also an instructor at AgCat and Cypress Ambassador.
So, how do we scale development, especially with large teams, and specifically from a technical perspective, purely? And so I identify basically those three pillars, basically drive and automate good architecture, then also have modern tools at hand, and it's like an improved developer experience will make our developers more productive. And finally, speed in general. And I would like to talk to you mostly about Annex today, which is our open source dev tool, designed for Monorepos, but it also works without Monorepos, actually, pretty well.
So, this is basically the structure which you usually get when you generate a new project, right? So, what I call this is like, kind of, monolithic structure, so you have that application, you have the different types of folders, where each of those folders kind of represent a functionality and a feature boundary, usually. Now, with Annex it's a bit different, so there we have the building blocks of apps and libraries. Now, the application, as you can see here, sits at the very top, and then there are the single libraries down there. And the reason for that is it leads to a better architecture in general, because like, libraries represent a much stronger boundary than just folders. With folders, it's very difficult to actually control what can be exported and also signal what can be exported by other developers. And so in Annex, what you have usually is a very thin application at the very top, and then you have like a lot of those well-defined like workspace libraries, where the actual logic sits. And those workspace libraries don't really need to be published anywhere, they can, but they can just like live within the workspace and the application just links it. And so in the end, the application, if you want, is really just like the deployable. And then the logic is actually down in those libraries. And what often happens out of that situation, is that people start creating multiple of those applications and just like pick the libraries they actually need. And this, for instance, allows you to deploy the same kind of infrastructure multiple times and even scale it in different ways. Like we might want to scale the public phasing part much more than maybe that administrative part, which is just like used by copy users. But really today, I would like to go more hands-on and actually show you what it is like to work with Annex. And so to get started, of course, like you just installed Annex workspace and this is done by create Annex workspace, you give it a name, let's say react-summit. And I also pass here a package manager, which in this case is Yarn, but it could also be pnpm or npm. And so this now installs the Annex workspace basically set up and there we get a couple of questions asked. So we can just start with an empty workspace, but we can also use one of those presets which are pretty handy as they are already pre-configured. And so we choose react and we can give it a name demo app, for instance.
2. Generated Workspace and Library
And now we have a couple more questions, but I've already addressed them to save time. In the generated workspace, we have the courses app, which is a React application, and an end-to-end test set up with Cypress. The libraries folder is empty. NX has generators that allow us to easily create libraries. I've generated the 'course item' library with its structure and components. The tsconfig-base path mapping makes it easy to import libraries into our applications. We can import the 'course item' library with a prefix, as if it were a publishable library.
And now we have like a couple of more questions like which styling type we want to use and so on. Now, I'm going to interrupt this here because I have already done this and I want to save us some npm install time.
So this is what a generated workspace looks like. So you can see that apps and libs folder, which I mentioned before. So actually, if I open this, we already have that courses app generated for us when we did set up that workspace. It is a react application. And then we have also that end to end test set up for us, which in this case is cypress based and already configured to test our courses application. The libraries folder is still empty.
So in order to start this, I can actually just do yarn start or the nx equivalent would be our nx serve and courses, which is my course application. So then if I go to local host 4200, I can actually see the application being served up once it is compiled and booted. And so this is here, my welcome to courses app. Now, right now, I don't have any libraries. And that's actually another very strong point of nx is it has those generators. And so what I can do is I can write nx generate or g for generate. Now we're react, which is the plugin and then library for the library we want to execute. And let's call this course item, which is our library we want to generate. And I could provide here more options to customize the generation part. But for now, let's go with the defaults.
And so what you see now here is we get that course item library generated for us, which has this kind of structure, they are config files. Then there's a source folder, which has the index TS file here, which is kind of the public API. And here's actually what you want to export for others to consume while everything that lives inside that libfolder here is just private to that library. And we also have here kind of handy components already generated for us. Now, the very interesting part here is that in the tsconfig-base path down here in the config file, we got already like a type to path mapping set up for us. And so this allows us to very easily import a library into our applications without actually using that fixed path of the relative path to them. So let me go to the courses here. Let's open up here to apt TSX file. And let's remove all that part here, which we don't really need for now. And so what I want to do here is actually import our course item. And so you can see, I can import it with that prefix here, which we just saw before. So it really looks like if this was a publishable library, but rather it got actually just linked from within the workspace.
3. Creating a Public-Facing Next.js Application
We reference it here and see our course item rendered inside the app. NX internally tracks dependencies and visualizes them with the depth graph command. We can create a public-facing Next.js application using the novel Next plugin. After installation, we generate the application using the NX Console Visual Studio Code plugin. The generated application includes the public app, which is a Next.js application with pages. We can insert the course item in the index page of the public app.
And then we reference it here. And obviously, if I start it again, I will now see how that is being linked into our application. So if I go here and refresh, we now see our course item has been rendered directly inside the app.
The other interesting part is also that NX internally tracks the dependencies and how things relate to each other. So I can use the depth graph here command to actually visualize those dependencies which NX internally has. And so here, for instance, this is the current situation which we have. We have the courses app, then we have kind of an implicit dependency to that end-to-end testing part which tests our course app, and then we have the course item library which the course app uses. This is very handy especially as our workspace grows, so let's explore that.
What we could do, for instance, is create a public-facing Next.js application. So in order to do that, we can install a novel Next plugin. And by the way, these are plugins we provide already, but there are tons of community plugins for a variety of use cases, so definitely check out those as well. So now we got novel Next installed, and we could generate now the application. Now, again, I could use the comment line, but it's much more handy sometimes to use the NX Console Visual Studio Code plugin. That allows me to run the generate here, and we see all the possible generators here. And so I want to go with novel Next for generating a Next application. Let's give it a name public. And here the styling can remain the same. We still want a Cypress test. JS runner, ESLint, and also JS for testing. And down here, you can see a preview of what would actually be executed whenever I execute a command. So we can also learn about the new commands down here. So let's just run this. So it will generate my new application, and while this installs, let's go over here and actually explore what gets generated. So we have the courses app, and now you can see we also have that public app. So this is a Next.js application. We see here are the pages. Let's, for instance, go to the index page here. And again, let's remove here all those things which you don't really need. And we will do the same here to insert basically our course item. So again, I imported the same way as a reference within a Next.js app.
4. Boot Next.js App and Generate Libraries
Let's boot our Next.js application and explore the dependency graph. We generate additional libraries to observe the evolution of the graph. The libraries include 'core', 'coupons', and 'sales'. We connect the libraries within the application, creating actual connections between all the libraries.
So now let's boot our Next.js application. So I do yarn serve public, which is our Next app. And you can also see the uniformity of the commands. They are always the same regardless of whether you use like a React setup, back-end node setup, or here a Next.js application, which is also very important in terms of like the learning that the team has to do as you scale.
And so now you see here the public application of being served. So this is our Next app, which also use that course item. And in fact, we could explore the dependency graph again. So if I use a Next.dev graph, we can boot it up here. And now the situation looks quite different because now we have the course application and the public application. Both have their end-to-end test and both reference here the course item.
So let's generate a couple more libraries just like to see how that dependency graph evolves. So again, I'm using here the NX console. I don't want to, for instance, just like generate a workspace library. Let's call it core, which isn't really specific to any framework. So this could even be shared between frameworks or even between a back-end and a front-end. And so now we got that course core library generated. I also want to generate a new library, which next time is a React library, and I call it coupons. This time I want to structure that under an admin directory because this will be a library which I want to use from within my admin part of the application. And then I want to have another one, which is sales, which is the one I want to use, again, within the admin directory. All right, and so if we close this and I reduce here the window a bit, so we can now see that we have in the libraries folder that admin coupons and sales, which are both libraries and the core library. If we use the dependency graph again, we'll see that the structure changed a bit again because like now we have the libraries, the applications that reference that course item library down here, but then we have those three libraries, which sit there, but are not really connected yet.
So let's do that. Let's go and here into the application. So let's first go into the coupons part actually and reference our core library in here. So we'll import a core and just like call it in here and the same for the sales, we will reference it here as well. And then finally we go up here into the courses app and we reference it from within our application. And so now they are connected. We can actually go here and again, start the dependency graph. And now we should see actual connections between all those libraries. So we see now the course app references, admin coupons, admin sales, and the core and the public part and the course part share that course item down there.
5. Imposing Restrictions and Defining Boundaries
As your workspace grows, it becomes important to impose restrictions on imports. Assigning types and scopes to libraries and applications helps in defining the boundaries. Linting rules can be used to enforce these boundaries. For example, a utility library can only reference other utility libraries, not feature libraries. Similarly, scopes like admin and public can only reference libraries within their respective scopes. This separation ensures a well-structured workspace.
Now this is a very nice setup already. What you might want to do at some point, however, as your workspace grows, is you might want to kind of impose restrictions. So for instance, you don't want to have the public part imports of admin sales library. And as your work space grows, this becomes really important.
And so next there's a way to actually impose those restrictions. And so first of all, what you'd need to do is you kind of need to assign texts to those libraries and applications. So we can go in here in the NxJSON configuration, we can here start assigning text. So first of all, these are just arbitrary strings. So you can really define them how you want. I usually use a prefix and a suffix here. And so what I do here, for instance, for apps, I just give them that type application. Next, I define type feature, which is for our admin coupons, sales and course item which kind of represented an encapsulated feature within our workspace. Then I have a type utility, which is that core, which is really something that can be shared across various libraries, just like general utility functionality. And then I can give also scopes. So I'd just like to find another tag, which I call scope. And in this case admin for all the admin-related parts up here. And the same for scope public for all the public part down here. And finally, we will also have something that is shared, like for instance, the course item and the core parts are really shared. So I give them the shared tag here.
Now we need to impose the restrictions and we can do that via the linting. So if we go into the eslintrc file, we have here that enforce module boundaries rules which is provided by now on NX. As we can see you can define the constraints. So we can start by saying for instance, a library from type utility can only really reference an R-type of utility. So you don't wanna have a utility library reference a feature library, but rather vice versa, right? The feature libraries might be able to import utilities. And so next we can actually define a feature once. So again, type feature can reference R-features and type utilities. Then for the scopes, we can say scope admin can only reference scope admin. And finally, scope public can only reference scope public. So in this way we separate the different scopes of our workspace. And obviously we also need to add some scopes shared here because like the course item and also the core utility in general here might be shared among those different kind of scopes within our workspace.
6. Testing with Linting
We can test the linting rules in our Next.js application by intentionally breaking them and running the NX lint command. This allows us to control the architecture of our project as it grows.
So how can we test that? With the linting actually. And so let's first break the rule. So let's go in our Next.js application up here. Let's go into the index.ts and let's import the admin sales. So now we created basically a connection from public to the admin sales which is prohibited by the linting rules. And so if I now run NX lint public which is our public Next.js app, it starts the linting. And what you will see now is an error basically on our index.ts file which says a project tagged to scope public can only really depend on libraries tagged to scope public or scope shared. You also see it directly in the editor. Sometimes Visual Studio is a bit slow to actually refresh the scopes once you define them but you also would see it directly in here. And so this is obviously a big advantage and let me actually remove that to have our linting work again. This is a big advantage because this allows you to control your architecture as it grows.
7. Speed, Dependency Graph, and Caching
The next part is about the speed of development with Nx. Nx provides the 'affected' command to rebuild and retest only the necessary parts based on the dependency graph. It also supports caching, which can be distributed using Nx Cloud for faster execution. By connecting the workspace to Nx Cloud, the cache can be shared among coworkers, resulting in immediate runs. We also discussed how apps and Libs differentiate Nx from traditional workspaces and the importance of defining boundary rules to improve architecture and avoid spaghetti referencing. Additionally, we explored the visualization of dependencies with the dependency graph and the powerful scaffolding abilities of Nx generators.
The next part is obviously speed. So definitely as you grow and as you want to scale your workspace you cannot really build everything every time, right? Like if you change something down here you cannot really just like build whatever is connected to it. So Nx has a so-called affected command but first let me commit all these parts and let's simulate we are developing a feature.
So let's check out a new branch, my feature and now in here I'm going to make a change let's say in the course item library. So let's go here to course item in here and let's actually just like say welcome to course item, like this. So we made a change and now Nx can use the dependency graph to figure out what it needs to retest and relint and rebuild. And that can be done by the so-called Nx affected commands and we can actually also apply that to the depth graph. If I say affected depth graph you can now see a subsection of the graph which would be affected by the commands. We can also see all of them. I see them colored a bit differently. So obviously Nx figures out like if this changes it doesn't need to build or test this one but just like the paths that go upwards. And so, in fact, like if we have a look here and I execute yarn Nx affected test It will only really execute these three of the libraries and execute the test for those.
The interesting part is also, if I rerun this there's another concept that improves speed which is our caching. So if I rerun this, you see it is immediate because like all the three projects got taken out of the cache. Now this cache by default just lists locally. So in a node module folders.cache.nx there's the caching actually which figures out like what it needs to rebuild. But you can distribute that and you can go directly, for instance, to Nx Cloud. If I go to Nx.app, you can connect the workspace and I just click here once I'm logged in connect workspace. I don't have Nx Cloud. So I'm just using the command here to install it since I'm using Yarn. This will be what I would be using. So let me just paste this here and then execute it. So now it installs the Nx Cloud library and then directly configures it for me. And so now if I re-run the affected test, it will now test all of the libraries which are in my workspace.
Okay, we changed some fundamental infrastructure here like some core configuration libraries. So Nx needs to test everything again because we might have installed a package, right? And so once that it has been installed, I could actually simulate as if I was a coworker, right? So some of my coworkers already executed this the day before, the cache is distributed in Nx Cloud. So I'm going to actually clear that cache and re-execute it again. And so now you can see the run is basically immediate because like all of the products got pulled down from the real-world cache. You also get a nice view, some more information based on Nx Cloud about the view, what got built, whether that was a cache hit or not, and much more. So what we covered basically is how apps and Libs basically differentiate Nx from traditional workspaces, how you can define boundary rules to improve that architecture and basically guard against some spaghetti referencing, also how you can visualize dependencies with the dependency graph, the scaffolding abilities via the generators, which are super powerful, it's like you have already generators which you couldn't show due to the time limitation, like setups for Cypress, like setups for Cypress for Just, for Storybook which automatically generates your stories out of your components and much more.
8. Exploring Speed Improvements and Getting Started
Your speed improvements via the affected commands and distributed caching by Nx Cloud. More to explore. Core information: nx.dev website, Nx app for Nx Cloud, Nowrl YouTube channel, Acai course. Get started with NPX CreateNx Workspace or NPX add Nx to Monorepo. Connect on Twitter for questions. Yuri asked about Monorepo usage, with interesting results.
And then finally, obviously, your speed improvements via the affected commands and also the distributed caching by Nx Cloud. But as I mentioned, we really just like scratched the surface, right? There's much more to explore. So these are some of the core information which you can use like our nx.dev website, Nx app for Nx Cloud part. And by the way, for Nx Cloud, you can always get started with it. Like it's completely free, you don't have to use any credit card so you get five hours per month save for free. And then obviously you can opt in to actually pay for more as you like the product. There's also our Nowrl YouTube channel, the official videos of our Nowrl YouTube channel and also an Acai course which is completely free, which you can use to dive in more into details of how Nx works.
So to get started, again, like use NPX, CreateNx Workspace to get a new fresh workspace setup. That obviously gives you the most benefits, but if you would like just to try it out, especially if you're interested in the whole caching capabilities of Nx, you can also use the NPX add Nx to Monorepo to get started. And it will convert, for instance, an existing Yarn workspace and enhance it with Nx capabilities. And here are a couple of links which explain basically how it works. And we also, for instance, convert a Storybook repository and also the Reemotion repository. So definitely check those out.
So thanks for your attention. And if you have any questions, definitely connect with me on Twitter. Shoot your questions to me on Twitter and let's connect there. Thanks. Yuri asked the people if they are using a Monorepo right now at their project. So let's look at the results. I have to switch screens here. Yes, and I'm happy with it. It has one with 32%. And no, and I don't think I need one, is second with 19%. And the third one is Monorepo with 19%. So Yuri, was this what you were expecting? Yeah, it's pretty interesting to see. And I think the contribution is pretty what I expected. Yeah, I'm myself also using a Monorepo, but I'm also working just on a tiny one project. So it's still a Monorepo, right? Does it count? Yeah, absolutely. That's also why I asked this kind of question. Because sometimes people kind of think like a Monorepo is just like a super large, big enterprise Monorepos, but it's not necessarily that the case, right? Like you can even have like your open-source project with a couple of libraries and a demo app like it's also a Monorepo, right? Depending on how you want to structure it.
9. Retrofitting NX into an Existing Monorepo
Retrofitting NX into an existing Monorepo is possible with nx-add-to-monorepo command, which adds a minimum setup to provide some benefits of NX. However, for a richer experience with generators, it's recommended to set up a new Monorepo and migrate products one by one.
Cool. So we're gonna jump into our audience questions. And the first one is, I'm going to try to pronounce this username, Soshikropka. How straightforward is it to bake NX into an already existing huge Monorepo? So retrofitting NX into an existing Monorepo. Can we do that? Yeah, there are some possibilities to do that. As I mentioned in my talk, there's that nx-add-to-monorepo, like npx-add-to-monorepo command, where basically we're just adding, especially on the Yarn workspaces, a minimum setup, which would give you some of the benefits of NX, which is like, for instance, like your computation cache, the execution of parallel tasks and things like that. So basically the organization of the execution of the Node scripts, which you might have in that Yarn workspace. But obviously, if you want to have like a bigger experience, like with the generators, and that may kinda make up what the NX experience is about, then obviously, it's better to set up a new Monorepo and migrate products over one by one.
Migrating, Testing, Deployment, and Publishing
We have npx scripts to migrate create React app to an NX Monorepo. Integrating end-to-end tests with OAuth usage depends on Cypress and mocking capabilities. NX allows independent deployment of multiple apps in a Monorepo. NX doesn't have specific CI/CD integration but can be customized and extended. NX allows publishing versions and libraries.
Okay. We are definitely also, just to add to that, we also have like some npx scripts, for instance, like to migrate create React app to an NX Monorepo, so that will help you like do some code modifications and merge them over to an NX repo. So there are definitely some possibilities and we are working obviously, of course, to make that even more easier.
Cool. And maybe, Suresh Kropak, I can give some input on what she needs in your spatial chat. Next question is from Thiago elfs. How hard is it to integrate end-to-end tests with other structures like Oauth usage? What was that last one? I missed the last piece, like end-to-end test? OAuth usage. Oh, well that depends how your OAuth calls go. Like, what we have, like the default setup where you generate a new application within NX is you get a Cypress test and a Cypress setup together with your application. And so it really depends like how Cypress handles that. Like Cypress has some mocking capabilities where you can kind of mock those calls or let them go through in a kind of a dev setup where you know the kind of users which you have and you can therefore assimilate like more end-to-end scenarios. But that said, like many of the scenarios we see when we work on monorepos is also to mock those. So it's not really like full end-to-end in the sense of you go to some database and back again, because those tend to be flaky. So our users usually have like a Cypress setup mocking out some of those APIs, which are critical, like authentication, for instance. And then basically have some more kind of local integration tests on their front-end setup. But Cypress has some pretty good guides on how to integrate with OAuth scenarios and like in general with authentication scenarios. So that's not really dependent on NX, it's more trying to find out how to work with OAuth and Cypress, yeah.
All right, next question is from Vasily Shalkov. You have these multiple apps created by NX. Typically our apps deployment and development are independent. Doesn't NX have tools to help with CI, CD to still have the benefit of delivering apps independently? Yeah, sure, like in the end, like every of those applications in Monorepo kind of lives on their own, on its own basically. It's just that the libraries allow it to share some code with others. And so you can always deploy the single application. Now we don't really have any specific integration with like CI or CD deployment. We have some deploy scripts for instance to deploy to Vercel, which we kind of try to help and optimize there. But in the end, NX is kind of a CLI which like issues commands. And so in the end, you can kind of customize it and tailor it down to what you need and even extend it in the end, like with your custom commands, like add your custom deployment script to actually be able to build the app, test it, whatever, and then deploy it to the environment you need to.
Okay, cool. We have a question from Arik. Are there abilities to publish versions slash libraries? Yeah.
Publishable Libraries in NX
In NX, you can convert workspace libraries into publishable ones or generate libraries with a publishable flag and NPM scope. These libraries behave like apps and can be built and published to an NPM registry.
So if I understand the question properly, like you imagine, like publishable libraries, like in NX, usually what you have is the default setup just generates so-called workspace libraries. They are not intended to be published to any NPM, but you can decide what type of library you want. Like you might want one that integrates just with apps you have, but is also publishable for other people to consume outside the monorepo, right? And so in that case, you either convert an existing one. There are basically such generators that allow you to convert libraries into a publishable one or when you generate the library you already passed like a publishable flag, an NPM scope, and then it will be conferred in a way that you can publish it as well. And so in the end, that library will behave the very same way as an app. Like you can build that library. It has a build target. So it will end up in a disk folder. And then you just like do your NPM publish there and publish it out to some registry.
NX and Webpack 5 Module Federation
We are looking into introducing a module federation feature from Webpack 5 in NX. Although we don't currently support Webpack 5 due to dependency constraints, it is on our list of future improvements. Some community examples already exist, where small applications in a MonoRepo share code and are deployed as micro-frontends, federating the code using Webpack 5.
Cool, okay. Next question is from Marvin. When do you think NX will introduce a module federation feature from Webpack 5? We are looking into it. Right now, we don't support Webpack 5. There are due to some like dependency constraints, but that's definitely something on our list to go into Webpack 5 and then support as well. There are some people that have that already implemented. So you can kind of switch out of dependency, obviously enforce it to Webpack 5. It's just that we don't kind of support it out of the box and that we guarantee everything will work perfectly. But we have some community examples that has already been used. And also, like with small applications in there are kind of micro-frontends that share-code in the MonoRepo, but are then deployed as micro-frontends and federate the code among them with Webpack 5.
React Context API and the Lib Folder
The React context API works the same way with the lib folder as it does within the app folder. Moving something to the lib folder encapsulates the logic that you want to expose to the application. It follows a composition pattern, where the app consumes the logic from the lib folder, which is not pre-compiled but consumed directly from the source.
Cool, that sounds powerful. And really cool that it's like, I don't want to say extensible, just changeable, yeah, nice. And the next question from Mark C. How would the React context API work with the lib folder? Well, in the end, it would work the same way as you would have basically, when you have like that specific functionality within the app folder itself. The only distinction, like when you move something in the lib folder is that you kind of expose or you kind of encapsulate more the logic that you want to expose to the application itself. So it's kind of more a composition pattern. It's not that lib in some way is pre-compiled and you just like consume the compiled sources, but actually the app is a Webpack built and just like consumes from that position, like from that location in the libs folder. So in the end, it doesn't really change whenever you have it within a folder of your app, but within the folder of your lib, it's always kind of consuming that from the source.
Managing Tags, Scope, and Dependencies
There are different approaches to managing tags, scope, and dependencies for large projects. Distinguishing between scopes and types helps establish restrictions among applications. Scopes can be defined at a granular or higher level, depending on the architecture. Some use a domain-driven approach, with libraries representing well-defined domains and dedicated libs serving as public APIs. It's best to start using tags from the beginning and gradually extend them. The deployment and CI pipeline in NX involve building the changed parts and identifying the libraries. The deployment process is similar, with the built app being packaged and deployed as usual.
All right. Next question from Ryan Burr, is there a good way to manage all of your tags, scope and dependencies for large projects? How do you go about that? Yeah, it depends. Like there are different approaches to manage that. Usually we, as I talked, also showed it in talk, we distinguish between like scopes and types, right? Like with that, you can also already kind of get a good feeling and restrictions among your applications. But you can obviously also go deeper, right? Like the scopes can be defined, like they're arbitrary strings in the end. So you can really like tailor them down to a granular level, or keep them more coarse-grained, like at a more higher level. The approach there really depends on your architecture set up. Like there are a lot of people, for instance, doing more of the kind of domain driven assigned approach, where they have every lib, instruction, subfolders, basically encompassing a well-defined domain of your whole workspace. And then you have dedicated libs, which are kind of the public API for that domain, which then have kind of facets, or something that enters or basically exposes the functionality of that domain to other domains. And so you can really go like in super detail. I usually encourage people to use text from the very beginning. And adding them later is really hard, because you have to do a lot of perfecting, of course. But then like start simple, and just extend the text as you go.
Yeah. All right. I think this is the last question we have time for, and it's from Imagine Wagons, nice name. What is the flow of deployment and CI pipeline? So yeah, the deployment, so let's start from a CI pipeline, maybe the CI pipeline just builds whatever has been changed. And so that's one of the main like powerful parts of an ax, obviously as your repository grows, the build times would go up and the test times would go up. And so an access that affect the command. And so you can basically submit your pull request or merge requests. And based on the comment you submitted there, it will compare what comments have been created with like the base branch, which is main master, however you want to use that. And then it calculates what changed, it identifies the libraries and then basically just executes the tasks, builds and cleans off those libraries. And then the deployment pipeline really like looks very similar. So, if you built the app in that specific CI run, you just like get a distributed, like a package or compile package into this folder, and from there you pick it up and then deploy it as you would usually do. So there doesn't need to be any change there.
All right, Command Center, do we have time for one more question? Ah, sorry, Yuri, I have to cut you short. Sorry. Yuri, thanks a lot for sharing this with us. If anyone watching still wants to ask Yuri some questions, I know there's a lot of questions in the Discord that we did not get a chance to answer. Yuri will be hanging out in his special chat speaker room. So be sure to go there if you want to join the conversation, continue the conversation with Yuri. Yuri, once again, thanks a lot and hope to see you again soon. Yeah, thanks. Thanks for having me. Bye.