Help us to make this transcription better! If you find an error, please
submit a PR with your corrections.
Luciano: It's Friday at 4.58pm. Marketing pings. Can we ship a new landing page for Monday with a hero, a gallery, and a testimonial slider? The site is hardcoded. Every change request lands on your plate. If you're lucky, there is a Figma file, but more often than not, it's a grab bag of screenshots and Word documents. So you roll up your sleeves, open your editor, and unstitch that new landing page into pure HTML. And there goes your weekend. Yes, we have done that enough times to know it's not fun, and we know you can relate. Now, what is the alternative? Maybe we can ship a WordPress site and let marketing manage everything themselves. They can pick templates, configure plugins, and publish all the content. We have also done that enough times to know how quickly hosting and securing this kind of setup becomes a nightmare. Plus, we prefer static sites over dynamic ones, so that approach rarely excites us. There has to be a better way, right? What if there were a way to keep content separate from how you fetch and render it? Marketed leaves in the CMS, shaping pages and publishing changes without tapping on your shoulder. Then you pick the tools you love, like Astro, Next.js, SvelteKit, or even a custom Lambda power backend, and you render everything exactly the way your design system expects. You can also choose how update flows. For instance, you can run a dynamic backend that always pulls the later content at request time, or you can keep the website totally static and wired up using something like a web book. When marketing eats publish, that triggers a CI build. Everything is rebuilt and published almost on the fly. On one of our recent projects, we did exactly that, using a tool called Strapi, which is an open source headless CMS written in Node.js. And today, we'll cover what Strapi is, what works for us, things like components, dynamic tone, the blocks editor. We also discuss the rough edges with how to run it well on AWS, and also some tips and tricks that we learned to have some kind of local workflow, and then publish the content remotely when needed. We will also mention Strapi Cloud, but full disclaimer, this episode is not sponsored by Strapi, so this is just our own unfiltered opinion. My name is Luciano, and I'm here with Eoin for another episode of AWS Bites. This episode is brought to you by fourTheorem. We'll mention a little bit more about fourTheorem on the end, so stay tuned. Okay, I admit I overdramatized the intro. I hope you enjoyed it. That's probably just one of the many many use cases that something like Strapi can help you with. So, Eoin, what do you think are other very relevant use cases for this kind of product, and what is the landscape right now?
Eoin: I think I'd put it in the general space of building CRUD applications, and if you're in the software game for a few years, you might find yourself building applications that do CRUD against the database, and a lot of the time you feel like every application you build, you're building some sort of a CMS with some extra features, and you don't often foresee that you need the complexity of a CMS or the flexibility of a CMS, but there's always this trade-off between, you know, can I use something general purpose, or do I really need to build something that's really fine-tuned to our needs, but that we have to spend a lot of time building and maintaining? So, whether you're in, you know, a SaaS company building a SaaS application, which always needs plenty of CRUD, you know, you've got relational model or some sort of NoSQL storage, an API in front of it, and a front-end in front of that, but equally, it could be like a line of business application in an enterprise when, you know, you've got some business user who needs to be able to enter data, retrieve data, and update data from a web app, mobile app, whatever it is. It's a good idea, I think, every so often to look at what's out there that maybe could save you tons and tons of work and stop you from having to reinvent that wheel yet again. And there's a lot of providers in the space with a lot of different trade-offs. So, there's Contentful, which has been around for a good amount of time. I remember using it like seven or eight years ago, I think. Storyblock is another one. Sanity CMS is one called HighGraph, which used to be called Graph CMS, I believe. And we see a lot of these come and go. Byline CMS is another one. Now, that's fully open source, but very new. So, it's very much work in progress. And then there's the one that we'll get to talk about a little bit more today, which is Strapi. Luciano, do you want to give us the 10,000-foot overview of what Strapi is?
Luciano: I'll try my best. So, yeah, the way that Strapi described itself is a headless CMS. And this is the entire category you described. So, probably worth explaining a little bit more what that means. So, the idea is that more typically, like we mentioned at the beginning, the example of WordPress. So, these kind of tools, they try to handle the entire workflow of managing content and then publishing the entire site, rendering that content in a certain way. Where headless CMS are a little bit different is where it's basically they don't try to care too much about how you actually use the data and where you actually render it. They just provide effectively like an admin interface to model your data and then insert it. So, they are more, I guess, geared towards trying to separate the responsibility for whoever manages the content versus whoever needs to use that content programmatically, either to render a static website or even as kind of application model data.
And, yeah, Strapi is one of the very few open source ones and it offers a few interesting features that I really like. So, the first one is that the way you fetch the data, it's over a nice REST API. But if you prefer to use something like GraphQL, which I think is really convenient with this kind of data models that where generally you need to kind of combine different pieces of data and depending on the pages you are trying to render, you might need to, you could express everything as like as a one query that gets you all the data you need. In that case, you can also use GraphQL. It's not enabled by default, but you can easily install a plugin to make that available and it works quite well.
And the other thing that I really like is that there is kind of a visual content type builder. So, you can run, you can download Strapi and there is even a CLI utility that makes it easy to bootstrap a project. And at that point, you can run a local version of Strapi that uses SQLite. So, you don't even need to have a database server running locally. So, it's just literally a Node.js server that starts locally very easily. And at that point, you can see an admin interface. And in that admin interface, you have effectively an editor that helps you to model your data model. And you can also start to configure all things like roles and permissions, translations, web books. You have a media library where you can upload files and manage them. And there is even an entire growing ecosystem of plugins.
So, if you need additional features, chances are that there is a plugin providing this kind of feature. There is also a commercial option, as we mentioned in the intro, that is called Strapi Cloud, where basically, if you eventually need to publish your Strapi instance somewhere to make it usable inside your company or with the customers you're working with, if you don't want the trouble of hosting that, you can just pick the option of using Strapi Cloud and they will take care of all the hosting. So, effectively, it's a SaaS service that the company that develops Strapi offers you.
So, one thing we know that is using it, because this is what we have been using in our latest project, is that it looks like, if you just look at the logs, whenever you create a new Strapi instance, it looks like they are actually bootstrapping a new virtual machine in DigitalOcean for every instance you create. And also, every time you upload assets, it looks like they are using some kind of CDN to make those assets easily available and easy to distribute worldwide. So, this is just an inside thing we noticed, which is interesting, just to understand a little bit more what Strapi Cloud is actually offering you when you use that kind of service. Now, Eoin, I'll let you discuss what are some of the other things we really liked about using Strapi.
Eoin: Well, I think using a headless approach, like having that decoupled content from how you render it, is great, because even if a developer or development team is going to say, okay, we're happy to offload all the CRUD to another provider, it's probably too much to expect that there's going to be a frontend that will meet your needs as well. So, it's great that it separates those two things. The modeling that maps to modern frontends is quite nice. So, there's a content type builder, and it supports collection types and single types. And it also has things called components and dynamic zones. And essentially, this is giving you like Lego-like ways to build pages. And then developers can wire components to React or Astro or view components with typed properties.
It has a blocks editor as well. So, if you're imagining rich content, often even in a line of business application, you might also want some web page-like content, like blog article type content. And the blocks field allows you to structure these things, but stores content as a JSON tree rather than raw HTML. So, that gives you a lot more flexibility in how you render it. It also has APIs that fit different stacks. So, it's got REST out of the box. You can use GraphQL via a plugin. Both are very powerful for population and filtering. So, it's handy when you want static builds at CI time or on-demand revalidation at runtime. I'd say it's static site friendly as well. So, you can fetch data at build time, publish your assets, and use strappy webhooks to trigger rebuilds when editors hit publish. Your production site doesn't have to talk to the CMS at request time. That's really good for cost, performance, and security, SEO as well, if that matters to you. And then there's a media library with S3. So, it has built-in media management with an official AWS Upload Provider, which is a plugin, and easy CloudFront integration if you want a CDN as well. We'll link to that provider in the show notes if anybody wants to leverage that. Now, Luciana, you've been using this in anger a lot, and I'm pretty impressed with what you've been able to do with it, to be honest. What are some of the things that you really liked and got into in a big way?
Luciano: Yeah, I think I'm going to repeat some of the things you said, but maybe I'm going to try to go a little bit more in detail. For instance, the blocks editor is one of the things that I really enjoyed using, because in the past, every time I was dealing with some kind of rich content type of widget or editor, you always end up with a bunch of HTML. And then the best thing you can do is just take that HTML block and slap it somewhere in a web page, but then you have very limited flexibility in terms of customizing it, in terms of look and feel, or even just making parts of it more dynamic.
Imagine, I don't know, there's a picture and you might want to provide an on-click handler that make you zoom the picture, like in a model window, something like that, which could be very common for many websites. Well, that's kind of very limiting, but also has been the dominating approach for a long time. And I think the blocks editor tries to change that approach in a very smart way. So the idea is, again, another abstraction layer. So rather than giving you the fully rendered content that was effectively created through this WYSIWYG type of editor, the editor itself is storing all the different things that you are laying out in your content as effectively like a JSON abstract syntax tree. So everything is a block. Every block has a type, and that type can be a paragraph, a heading, a image, a quote, a table, and more. There are so many different types. And of course, every block can also have children. So this is effectively how you structure the entire content. And then in the end, what you get out of it is literally this blob of JSON. And at this point, it's up to you to decide how to render it. And of course, that comes with some complexity as well, because effectively, you have to deal with a tree-like structure. So you need to figure out, okay, how do I traverse the structure?
And how do I render all the different types? So there might be a lot of work involved in just rendering a basic piece of text. So thankfully, Strapi offers some built-in renderers. For instance, if you use React, there is one called blocks React Renderer, we'll have the link in the show notes, which gives you effectively a component that knows how to render the abstract syntax tree with very clear defaults, and allows you also to override some of these defaults. For example, if you want to customize the image block, then you can say, okay, I'm going to provide my own image component. And only when in the abstract syntax tree, there is an image that is going to be rendered, then your component is going to be injected, and you have full control on how to render images. You don't need to specify all the other blocks kind if you are okay with the defaults at that point. So this is pretty cool, because it kind of does all the heavy lifting for you. And it gives you a very easy interface in case you want to customize something. So yeah, that's an experience that I think is really enjoyable, because it unlocks another level of customization. And you can even end up creating your own custom components, which is something that I also enjoyed. So this is outside the block renderer. So you can imagine the block renderer as a field in your data model, where you can say, every time I need rich content, I'm just going to put it in a field, maybe you call that, I don't know, content, or blog body, or whatever that is.
But sometimes you want to do something even more flexible, maybe you have a design system where you have things like a hero or a slider, or maybe, I don't know, a preview of a product with a buy button, you have all these kind of widgets that have been taught together with a team of designers, maybe you have an entire design system, you can actually start to map all the components in your design system and make them available in the CMS as well, using this abstraction called components. And effectively, what a component is, is another data model, which is a model that you can use and put it inside your other data models. And it maps the props that you have in your own, let's say you're using React, so you might have a bunch of React components, you can map one to one all the props of every component.
of every component in React with the components in Strapi. So what that allows is that then whenever a content editor is working on a page, for example, they could say, okay, here, I want to show a hero. So I'm going to just drag and drop the hero component. And then that hero component is going to start to display all the fields that needs to be populated, which effectively are all the props that are available in your hero component.
And the way that you map content with components is through dynamic zones. So dynamic zones is kind of the glue between the two worlds. So effectively, every time you are modeling, let's say, I don't know, let's make the example of a landing page, right? Maybe you have the concept of a landing page as a data model in your CMS. In your landing page, you might just use a dynamic zone to say, in this area of the landing page, the editors are free to pick between all of these components and order them in whichever way they like. So dynamic zone are effectively a way to say which components will be available in which part of the page. And then the marketing team or the content team is totally free to pick among those components, shuffle them in whichever way makes sense and provide all the properties.
So those three things I think I really like them. And I think they really unlock that full control in the sense that you still keep everything fully decoupled. But then you can get to the point, like if you are really clever, really put the time to configure things properly, to almost build like your own, I don't know, template builder entirely in Strapi. So the marketing team or the content team will have total freedom to change things around very quickly. And you don't have to always work with a designer just to maybe swap, I don't know, a certain type of header with another one. That sounds great. It seems like you've got the capability there to have entities. If you wanted to do a CRUD application, you can have those specific, you can have that data model there. But if you want to have richer content, like blog articles or other types of content, that's maybe SEO friendly in your application, then things like components and dynamic zones really are there to support that.
Eoin: I'm curious about the data side of things. So if you have, I presume that it's got its own schema under the hood, right? In its relational database. How do you manage data migration, maybe even working locally, working with sample data, synchronizing it between environments? Because this is always a question, no matter what kind of data, what kind of project it is, it always comes up. How do you manage data synchronization across environments? Yeah, I think there are different kinds of workflows that you can put in place. The one that I've personally used, and I think it works decently well, is kind of a local first approach. So effectively, you start a local Strapi instance by using the CLI that creates a project and you can see all the source code, you can install dependencies through NPM. And then at some point, when you're ready, you can just start the instance locally and access the local admin.
Luciano: In the local admin, what you can do is that you have a panel where you can design your data model. And that's effectively like a totally visual experience where you can specify things like what is the name of this data model? Is it a collection? Is it a single type? What are all the fields for every field? What is the type of that field? You can specify is it mandatory or is it optional? Are there other validation rules? Like I don't know, strings, you can check on length, that kind of stuff. Or maybe when it's a string, you can decide is it like a single line input? Or it's like a larger text input?
You can choose a file picker. Or you can choose a file picker, all these kind of things that I think are very standard for most CMS. But the nice thing is that you're doing all of this stuff locally. And once you do it visually from the admin, actually, if you check your Git history, well, you just do it like a Git status, I mean, then you can see that it's actually changing files. So it's not really storing all this information in a database, but it's actually building schema files for you. In a schema language that's actually very similar to JSON schema.
And everything you do, then eventually you can just commit to Git and keep the entire history. Every time you are starting Strapi, Strapi checks effectively that history against the state of the database and is able to effectively do like a soft migration where it's going to restore the new status. And if there are new fields, it's going to create them or if fields have been removed, it's going to remove them. And you can also insert data locally, which I think is very useful for testing reasons.
But then sometimes you end up creating lots of the basic data you need. Like for instance, I've seen in my use case that it's very common to start with like SEO type of data. So you might have a single component with fields like what is the title of the website? What is the SEO description? What is the fav icon? What is the, I don't know. Yeah, all this kind of information that is more something you initially populate because you need it for testing and to start building the pages.
And then you realize, well, I've put all these efforts into populating this data locally. There must be an easy way to propagate this data to the actual remote production instance, rather than having to manually do all the work again. And thankfully the CLI that Strapi offer has a feature called transfer. And the way it works is that you can kind of synchronize in both direction. So you can even go from remote to local or from local to remote.
And I think both are useful for instance, the case I'm describing is useful. Like you created a bunch of basic data. You want to push it to the remote. So you are not starting to scratch. But then sometimes a content editor is working on the site and they do changes and they tell you, okay, there is some kind of weird bug. An easy way to reproduce that bug locally is that you can pull all the remote data locally.
So it's also interesting that this transfer can work in both direction. And the way it works is that you can create a token in the admin UI, either the local one or the remote one. And then you have this kind of source token and destination token, and you can decide how to push the data. And it's gonna, it could be a little bit dangerous because effectively it's going to wipe everything and then copy the data from source to destination.
I'm not sure there is a way that you just do like incremental changes, but yeah, just check the docs and make sure you use it properly. But it's cool that they offer this feature where you can use it synchronize data. And by the way, you can also use this as a breach to copy data between two remote instances of Strapi. So for instance, if you are migrating, I don't know, your Strapi instance from a VM to another, or maybe you're just changing the database from a SQLite to, I don't know, maybe a Postgres. You can actually do this migration where you copy everything locally from a source and then locally you copy it to a destination. So we have also done that because in our current project, we are managing multiple instances of Strapi for different brands, but there is a lot of common data. So it was just easy to do it that way. So what is the bad news? What did we not like about Strapi?
Eoin: Yeah, I think there isn't like a huge amount that we didn't like. I think in general, it's like I really like the structure and the principles.
Luciano: And I think there is lots of potential. One thing is that it's, it feels still a little bit immature, although Strapi has been around for a while. It seems like a lot of like, it's really moving very fast and a lot of things are not properly polished. For instance, that it's very common to find the small bugs that can be annoying. Like sometimes one silly thing that I noticed just to give an example is that if you copy a snippet of code from somewhere into the block editor, the block editor also supports the code type.
It messes up all the lines and it actually ends up creating a block for each line. And then you have to kind of compact them all together manually, which can be very annoying if you're actually getting, I don't know, like a tech block where you might, where you might have lots of articles with code samples. Then I think it wouldn't be like the best experience. Now, this is just one example I've seen probably a dozens of this kind of small bugs. And I've also seen to be fair that they get resolved fairly quickly.
So there is actually a very big active community where people are constantly reporting these bugs. You can see releases, I think weekly, if not more than one release a week and every release has bunch of bug fixes. So hopefully this is going to make the product much more stable in the coming months or years. Also, the documentation can be improved. It can be sometimes misleading. Like for instance, there was a big re-architecture between Strapi 4 to 5, if I remember the version correctly. 5, I think is the latest. So lots of the documentation is still giving you tips for Strapi 4. And sometimes it's not clear when that is the case. So you might end up trying to do something and then it doesn't really work the way you would expect just because the documentation is not fully up to date. So again, I totally expect those things will be fixed over time, especially because there is also a company behind and they are trying to market a product which is Strapi Cloud. So I think it's in their best interest to make the product as polished as possible and to give the best possible user experience. Okay. And given that we said the cloud offering maybe isn't as mature as we might expect, what's the best way we recommend people self-hosting this on AWS?
Eoin: Yeah. And I think I wouldn't say that the cloud isn't mature. I think it's probably a bit simple at this stage, but that's the job for most cases.
Luciano: There might be other reasons why you might want to self-host. Maybe you have, I don't know, data constraints. Like you don't want to publish your data in Strapi. You want to keep it in whatever local deployment you have or even in your own data center. I don't know. What's the problem for you to do? You want to have to be a problem for you to do? Or within your VPC, for instance, if you are in AWS, that could be one reason.
Another reason might be maybe you're hosting lots of instances for whatever is your use case. And I think at some point, there might be a level where putting the effort into managing the deployment and hosting yourself might be more cost convenient than having dozens of instances in Strapi Cloud. So, of course, you need to do the maths and see where that point is, but it might be a valid story where it might be more convenient to host it yourself rather than using Strapi Cloud.
And especially if you use some of the more enterprise features, like if you need SSO sign up, I think this is one of the more expensive ones. So, if you need it for every single site, I think then you might be better off just hosting it yourself and doing the SSO layer yourself. So, given all of that, I guess the question might be, how do you go about hosting it, for instance, on AWS, right? If you're listening to this podcast, that's what you want to know.
And full disclaimer, I haven't tried to do this fully, but I think I understand enough of Strapi now to give kind of an informed potential architecture that you might want to use for hosting Strapi. And just talking about the compute, Strapi is a traditional Node.js server, so you can easily containerize it and run it on Fargate or AppRunner. Or if you have already an EKS cluster, you might even run it on EKS.
You can also use it in EC2, of course, but you will need, as always, if you manage bare-bone virtual machines, there is a lot more that you need to manage. So, this is totally up to you to decide if it makes sense or not. Yeah, I think I would prefer personally containers just because it gets a little bit easier and you have less to manage yourself. Then the database, you can use SQLite, we mentioned, and this is the default when you run it locally.
But of course, when you start to run it in the cloud, it doesn't make too much sense because you might want to use multiple instances of compute. And at that point, you need a shared database. So, the other options are Postgres, MySQL, or MariaDB. So, you can easily spin up, for instance, an RDS and then connect your instances to that RDS instance. And whichever flavor you like, Postgres or MySQL, I think Strapi uses some kind of ORM in between where it doesn't really make a difference. One thing that they say, though, in the docs, I found this snippet somewhere where they say they don't... They say something a little bit weird because they say, we don't support NoSQL, which makes sense because I think they have a relational model by default. And then the next line is like, we also don't support Aurora. And then I found blog posts of people actually using Aurora. So, I think it's more that they might have seen some bugs, some slight differences. They just don't test it. Maybe it's not in their test coverage.
Eoin: Exactly. So, they basically say, it's up to you if you want to try that at your own risk, but we don't basically take any responsibility if it doesn't work.
Luciano: So, I think Aurora is still a decent choice, but yeah, just be aware of the disclaimer. Then in terms of assets, as we mentioned, there is a plugin that allows you to publish all the assets that you upload into Strapi directly into S3. So, then you can easily create, for instance, a CDN distribution with CloudFront. So, that could be another great option for public websites. Secrets and configurations.
So, Strapi needs a few secret parameters. For instance, it creates API tokens, JWT, and also some secrets that then are used internally for encryption. All this stuff is something you can store in Secrets Manager, and then you need to pass it as an environment variable when the container starts, or whenever your process, if you're using EC2, starts. For builds, you can probably use whatever you want, and effectively, it's the same process you would use locally.
So, you have a script that you can launch with NPM, Yarn, or PMPM, whatever you prefer to use, that builds a production version of the backend. And then you have a folder where you can take that backend and execute it in a production-ready way. Because, by default, if you run it in development mode, of course, it's much slower, but also gives you more, I guess, debug messages that can be useful in development mode.
So, it's important, I guess, to distinguish whenever you are building for production and then whenever you're just running it locally. So, those are two different processes and make sure to set up your CI to use the production process. And finally, if you want to do some security, this really depends because, of course, you have an admin to manage content, and somebody needs to be able to access that admin, right?
I'm sure you're going to be working with content editors, or even if you are the content editor yourself, it's not like you want to keep that very open. By default, Strapik gives you a username and password type of access. You can use plugins to do things that are a little bit more advanced, like SSO. You can even have IP allow lists. You also have ORBAC, for instance. You can create different profiles with different roles and give those roles different permission in terms of editing, or even reading different kinds of data models.
So, all this stuff is actually quite well done, and you have lots of freedom. One thing that I would like to explore more is maybe if you are using, if you're doing like a static site, and you want to secure as much as possible your admin UI, you might put it in a private VPC on AWS, then give like a VPN access to your content editors, and then your CI is the only thing that can access as well. And then effectively, whenever you are building, you read all the necessary content, render on the pages statically, and then you have just a bunch of HTML, CSS, JavaScript that you need to publish in a CDN. I think that would be a pretty secure setup at that point, and not too complex to do as well. Interesting.
Eoin: Yeah, I guess another thing you might consider if you really want to lock down, but keep that admin page visible to administrators, is you could use a separate load balancer listener, and only allow the paths through that. And then you can put an authorizer on that load balancer like integrated with SSO, which is quite easy to do, at least at a basic level. Application load balancer allows you to do that, so it might be a cheap way of getting that much sought after enterprise SSO stuff. Absolutely, which would be probably the most expensive plan just to unlock that.
Luciano: So I think if you're doing that a lot, it might get to a price point where doing what you just described makes more sense. Yeah, maybe that's a topic for another episode.
Eoin: So it sounds like the people are wondering like where would I use this and where it would fit best. The sweet spot is you kind of want full control over your data models. You probably want self hosting, and you want something which is a headless CMS. You know, it gives you the storage and the API, and it plays nicely then with your serverless applications or your static builds. If all of that ticks, all the boxes get ticked, Strapi is a fairly solid choice.
But if you prefer something fully managed, there's a lot of other options out there, and Strapi Cloud is just one of those options. And again, we're not sponsored. This is just, you know, it's great to be able to promote an open source project that remains open source, of course. But there are a lot of options out there, so we mentioned some of them at the start. Even there's a lot of applications in the kind of enterprise low code space, which are much more expensive, and also kind of fit into this category to a certain degree. But it seems like Strapi Cloud is a decent option as well. Yeah, I totally agree with this take, and I think that brings us to the end of this episode.
Luciano: So just to summarize our take, I think we really like Strapi, the content modeling, the dynamic zones, and the block editor. Also, the workflow is generally pretty nice. So work locally, create the data model, you can also create data, move things around to production when needed. With the transfer CLI, I think, yeah, there is a quite good productivity boost in doing things this way, of course, rather than building your own CMS from scratch.
And you can even have a quite pleasant experience if you know how to avoid certain small bugs, but I'm sure that those bugs will be fixed as we go in the next few months, years. So I think Strapi can be a valid, very valid option going forward for sure. So again, thank you to fourTheorem for sponsoring another episode of AWS Bites. And fourTheorem is a consulting company specialized on AWS. So if you want help designing an AWS architecture that's simple, scalable, and cost effective, make sure to visit fourTheorem.com and reach out to us if you need more information.
Now we'll leave you with a final question. Have you shipped something with Strapi? If you did, I'm curious to know, did you like it? Was working end to end or there was some unexpected hiccup or also another question, how did you host it? Did you go with the cloud option or did you host it yourself? And if you hosted it yourself in AWS, please share your architecture because this is definitely something we're talking about. And we are sure we might be learn a thing or two from you. And if you ever use any other CMS, headless CMS like Strapi, I think it would be also nice to hear your opinion, which ones did you like or not. So let us know in the comments or ping us on socials and we'd love to talk to you. And thank you so much again, and we'll see you in the next episode.