How I Hosted my Strapi CMS Driven Website for Free.

This article was first shared on Strapi's blog

A couple months ago, I was rejected for a job with an awesome company. It was a bummer, but it made me rethink the ways I was marketing myself as a software developer.

In order to better position myself and make a better impression with a future employer, I decided to build my own personal portfolio.

Even though I have been doing web design and development for companies through my own company, Soltech, for three years now, I had never had a portfolio just about my skills and software projects.

When I started my personal portfolio project, a big goal for me was to host my website for less than $10/month. Thankfully, once I got to the deployment stage, I was able to host my website securely, on great hosting providers, for free!

Here is an overview of how I hosted my website for free.

Tech Stack

Static Frontend

The first thing that I did was set up my frontend Nuxt application to build statically.

This is easy to do with Nuxt. All that you need to do is add the static target flag to your nuxt.config.js. This will set up your app so that when you run "nuxt build", the site will be built statically.

// In nuxt.config.js:
export default {
  target: 'static',

By building your website statically, pages will be served as HTML for the first request, then via JavaScript without a full page load for pages linked using the NuxtLink component included with Nuxt.

This will also mean that no HTML will be generated on the fly. Everything is built at build time.

Statically Serve Content from the Strapi API

Another choice I made was to use the fetch() hook in Nuxt to pull in data from the Strapi application from my page components.

This way, data is pulled in at build time via the server and rendered server-side on page loads.
This helps with SEO because search engines can more easily parse the content of pages.

<!-- In pages/posts/index.vue -->
export default {
  scrollToTop: true,
  data() {
    return {
      postPage: {},
      posts: []
  async fetch() {
    this.posts = await this.$axios.$get('/posts')
    this.postPage = await this.$axios.$get('/posts-page')

Static Content for the Users

Another reason I did this was so that I could serve all of the content from my Strapi CMS backend statically. I wanted to use Heroku to host the Strapi backend, but the Heroku servers automatically shut down after a period of inactivity.

If the content was pulled in on the client, users would have had to wait a long time with a loader before seeing content, making the bounce rate much higher.

Since all of the content is served statically, the Strapi API is only called during deployment, then the server shuts down until the next deployment or when I log in to update content.

This also helps a lot with the costs! Heroku charges per hour of server activity. Since the server is rarely on, costs will stay low or free, even if I start updating my content more often or make more deployments.

Database Hosted on MongoDB

When I deployed my Strapi application on Heroku the first time, I made a bunch of edits, went away for a few hours and realized that everything I did was destroyed!

That was because Heroku uses the git repo to rebuild the application, and the SQLite database by default will not work with Heroku.

I set up a free MongoDB account for the database. In order to connect to the Database in Strapi, you also need to install the Mongoose database connector. The Strapi docs are great.

Also, make sure to set up your database configuration in the config settings of your Heroku account! This was confusing at first, but you need to add the env key and values to the config settings in Heroku before deployment. These settings take the place of your env file that is in development.

You want to make sure never to commit your database configuration to git.

Images Hosted on Cloudinary

Another thing about Heroku that you need to know is that any images that you store locally will be destroyed along with the SQLite database as soon as the server shuts down.

In my case, I decided to host my websites images on Cloudinary. They have a free account that will work just fine for my uses. (I think this past month I've only used 2% of the plan!)

Backend Hosted on Heroku

As I have already stated, the Strapi Application is hosted on Heroku.

It was AMAZING to set up. I also played around with trying to get Microsoft Azure Web Apps to work, but I still have been unable.

Strapi has great documentation of getting your server set up on Heroku.

Zero Downtime Deployments in Heroku

My website is using the free Heroku plan. There are two instances of the Strapi CMS set up in a Heroku “pipeline” for zero-downtime deployments from my git repo.

Whenever I push a commit to the main branch in GitHub, my development application in Heroku is built. This gives me time to test the Strapi application and changes before releasing them to the production backend.

Frontend Hosted on Netlify

After using Netlify for the first time on this application, I have to say I am pleased.

The Netlify team has done a great job of simplifying the deployment process in huge ways.

Like Heroku, there are also config variables that you must add. These are any configs that are in your env file while in development. For me, I am using these to store the API endpoint that Axios uses for API requests. That way my API is mostly out of view from the public and can remain a secret.

You can also create a webhook in Strapi so that when you update or create content in the CMS, Netlify will automatically rebuild your website for you. In Netlify, these are called “build hooks”.

Concluding Thoughts

This was a great project for me. Ironically, it was also the first website that I have ever built entirely API driven, and I loved it! You can read more of my journey building my personal portfolio on DEV.

I can say that the Strapi documentation helped me a ton, so if you struggle with doing this, make sure to look there first!

Also, if you are looking for a software developer to join your team, I would love to chat! You can view my website here.

Chris Wray website logo

Trying to do my part in making the world a better place.

This site is hosted for free, so I am thanking the services I am using by adding a link to their websites here in the footer.

© 2020 Chris Wray. All rights reserved.