Monorepo deployment best practices

Hi everybody!

I’m about to deploy a web application built with Nuxt.js and Strapi to production. The code lives in a monorepo as two different apps.

How would you deploy such an application and what should we keep in mind when doing so?

I appreciate any tips you can share with us.

Hi @mrwindmills,

Welcome and thanks for asking this question!

It will depend on how your repo was setup and how you want the apps to work in production. If you’re looking to have the Strapi API be public with it’s own domain, you’d want to set up a site for Strapi and another for site Nuxt and then deploy them both separately (though, you can use the deployment hook and add a deployment hook to tie deployment chain together).

If Nuxt will be talking to Strapi locally and the entry points are different, then creating one site with two web apps (one for back-end and one for front-end) and deploying them that way may work - though I’m not so sure about this setup working for Strapi tbh… I’ll set something up similar to what you’re doing and will see what works.

Thank’s again for bringing up this question! Let us know if you try deploying and what issues you run across. We’re looking at making our support for Nuxt.js apps with a headless CMS more fluid so this question couldn’t have come up at a better time! :smiley:

1 Like

I have a video series of doing something similar - Nuxt frontend with an Adonis backend that may be helpful - https://www.youtube.com/playlist?list=PLApnZzwJN4G5gHKMr4owbFKUdAtdwPB-X.

The main difference in deploying is I’d assume you’re deploying to one server as opposed to multiple and of course having one repository over two.

Great! it does appear this is Strapi’s default behavior.

I set up a Strapi and Nuxt project bundled in the same repo - you can see it here https://github.com/armgitaar/mystrapi2. I was also able to deploy as a single site / app by adding some custom deployment hooks.

Basically, I just put Strapi in the backend directory and didn’t try to optimize the package.json file or anything like that (which would likely remove the need for some of the steps).

Though, I did add a backend/server.js file for Strapi to run PM2.

const strapi = require('strapi');
strapi().start();

Here are steps from here:

  1. Created a node.js site in Cleavr (also added a MySQL 8 database to connect to)
  2. Created a web app with npm as entry point and start as an argument
  3. In deployment hooks, enabled build assets and then created the following custom deployment hooks

backend yarn install

cd {{ releasePath }}/backend
yarn install --production

backend yarn build

cd {{ releasePath }}/backend
NODE_ENV=production yarn build

backend start

cd {{ releasePath }}/backend
NODE_ENV=production pm2 start server.js --name api
  1. Order the hooks

  2. Deploy

Things to watch out for

  • Strapi asset build step takes a lot of juice; a 5 dollar DO server may work if this is the only app otherwise, may experience an out of memory error
  • Will need to enable 1337 port to access admin panel; SSH into the server and run
    sudo ufw allow 1337 and sudo ufw allow 1337/tcp
  • Also, I couldn’t access admin via http://mydomain.com:1337/admin for whatever reason; though <public ip>:1337/admin worked fine

This may not be the way you want / need to do it. And, I’m sure we’ll think of an even better way to do this. Let me know if you do something different. I’ve already got some ideas on how we can improve Cleavr to better facilitate these types of deployments. :grinning:

2 Likes

First of all, thank you so much for your involvement, I appreciate it. I’ll check your repo out and see how close it is to my use case and I’ll come back with my feedback once I deploy to production.

Again, thank you!

Hi @mrwindmills - no worries!

I was curious about what a standard way to structure frontend and backend would be for a Strapi app and keep in a single repro, so I reached out to the people at Strapi and they pointed me to this - https://github.com/strapi/foodadvisor. Basically how I’d expected the file structure to be. But, one that would require Cleavr to drill down into folders a bit more.

If you look at my repo, I basically put the backend in a backend directory and then used custom deployment hooks to point to the correct directory. The default Cleavr deployment hooks look in the root folder so those won’t work for this scenario. You’d have to build the custom hooks for the frontend to install / build / activate and then same for the backend. Basically, using the deployment hooks I posted above.

There is one more thing to consider… The above can be done via one web app in Cleavr and you can deploy backend and then frontend in one fell swoop. If you only want to deploy the frontend only or the backend only, then you’d disable the hooks you don’t want to deploy.

Another option would be to create two separate web apps, one for the frontend and one for the backend. That may be easier overall to keep them separate; that way you don’t have to worry about disabling / enabling hooks all the time and it might be a bit cleaner.

1 Like