Introduction

If you work with a codebase that works as a monorepo. A react client, multiple servers; a node server, maybe a flask server, etc. all under the same directory. Typically a client and a server running on different ports. Have you wondered how to deploy each of them on various platforms ?

Let’s consider an example of a MERN application, we have a client intented to be served via Vercel or Netlify and an Express server.

Here, In the case of deploying the client, both Vercel and Netlify provides an option to deploy a sub-directory out of the box.

Netlify

Link: https://docs.netlify.com/configure-builds/get-started/

Vercel

Link: https://vercel.com/blog/advanced-project-settings


Consider this example, the below is the file structure of my MERN SPA application.

.
├── LICENSE
├── docker-compose.prod.yml
├── docker-compose.yml
├── Makefile
├── Procfile
├── client
│   ├── Dockerfile
│   ├── Makefile
│   ├── package.json
│   ├── src
└── server
    ├── Dockerfile
    ├── Makefile
    ├── Procfile
    ├── index.ts
    ├── app/
    └── yarn.lock

Have you tried pushing the whole repo and have stumbled upon this?

remote: Building source:
remote:
remote:  !     No default language could be detected for this app.
remote:    HINT: This occurs when Heroku cannot detect the buildpack to use for this application automatically.
remote:    See https://devcenter.heroku.com/articles/buildpacks
remote:
remote:  !     Push failed
remote: Verifying deploy...
remote:
remote: ! Push rejected to app-name.
remote:
To https://git.heroku.com/mern-app-server.git

When it comes to deployment, on Heroku. The default language needs to be identified by Heroku in order to build the application. Eg. in the case of a node.js application. The package.json at the top level (root) helps Heroku identify that it is a node app. So that a builder for node is used to deploy the application.

When you heroku push the entire repo, Heroku can’t identify the default language from the top-level of the repo.

A simple solution!

Use subtrees

A git subtree lets you nest one repository inside another as a sub-directory. It is one of several ways Git projects can manage project dependencies.

Lets implement this via Git Subtrees

Heroku Setup

heroku login
heroku git:remote -a mern-app-server

Run, from the top-level of the repo.

git subtree push --prefix path-to/subdirectory heroku master

For example, if the subdirectory is the server in the root of my-repo, then running:

git subtree push --prefix server/ heroku master

will push the server subtree into Heroku ☁️

Finally if you get this output,

remote: Building source:
remote:
remote: -----> Node.js app detected
...
remote: Verifying deploy... done.
To https://git.heroku.com/mern-app-server.git

Boom!

Pic Credits: Photo by Safar Safarov