logo
Published on

Best practices in Notebook - env var and deployment

Authors
  • avatar
    Name
    Selina Zheng
    Twitter

The Twelve-Factor App

Before I embark on my first independent project, I studied the official website of the Twelve-Factor App, eager to create the Notebook on the right note, pun intended. It helps that Adam Wiggins, the creator of the twelve-fator app pattern co-founded Heroku, a service I enjoyed immensely while studying the Full Stack Open course of Helsinki University.

Many factors of the twelve are less relevant specific to my project, given that it is a personal passion project to hone my programming skills and not a commecial project of a corporate team. For example, concurrency, scalability and management of logs and admin processes need not be considered. However, I found the following factors essential to my own project:

  1. One codebase tracked in revision control, many deploys;
  2. Explicitly declare and isolate dependencies;
  3. Store config in the environment;
  4. Treat backing services as attached resources;
  5. Execute the app as one or more stateless processes.

The first four points ensure that the notebook can run in different environments with ease, namely, locally during development and when deploying to Netlify for user consumption.

The fifth point is an inherent property of a statically generated NextJS application. The build output is ultimately just HTML, JavaScript and CSS that run in the user's browser, and the only stateful functionality is accessed through one of the backing services.

Overarching principles

The overarching principle, it seems, is to keep the code (the mechanisms and the logic) separate from the actual contents that are presented and manipulated via the code. Everything else other than the code, e.g. database, dependencies, hostnames, etc., are all detachable and replaceable and not hardcoded.

I thought to follow the factors as best practices. For my own purposes, a strict separation of code and content facilitates using mock data and faster development without compromising the actual content. I can also better share my code with others for reviews.

  • NextJS and React

I keep the dependencies isolated and explicit by referencing npm libraries from the NodeJS and React ecosystems. With NextJS, I'm able to easily define routes and views which keeps me more productive than if I were to use the more low-level react-router. NextJS has served me very well out of the box which meant I could quickly start experimenting and not be slowed down by all the boilerplate code around setting up a more tradititional React project.

  • Environment variables and path rewrite

I started with hardcoded mock data to test my app, accessible from /api/ paths of the app.

I established a NOTES_API_URL environmental variable to be populated with the URL to the backend API. To keep the API access private, I created a .env with placeholder values, and another .env.local file included in the .gitignore file to actually populate the environmental variable.

I used NextJS HTTP Proxy Middleware such that any requests to /api/* get routed to the URL at the above mentioned variable. This way, the backing service can be switched out with ease and not hardcoded.

  • Deployment and Netlify

With my codebase stored in a GitHub repository, I delegate continuous deployment to Netlify. Netlify is a free app hosting platform catering to frontend developers like me. Also, Notebook is intended to be a web app. Compared to Heroku, Netlify specialises in expediting website deployment and hosting process.

The previously mentioned NOTES_API_URL is populated for the production environment in Netlify's admin dashboard, far away from any github repository.

I linked the Notebook Github repository to the Netlify hosting site. Everytime local code is pushed to the Github repository, Netlify automatically builds, deploys and publishes the new production to the site. I debug build the app in VS code before pushing to avoid deployment failure and unnecessary git commits.