A Golang + ReactJS Application

Madhan Ganesh
8 min readMar 17, 2019

--

Background

I’ve been creating an app which is mostly for my personal use and hopefully will get used by others. As I wanted to develop this app, I’ve been going thorough some technology selection and hosting options. I want to share my experience and decision in selecting certain set of tools. This article will start with what the app itself followed by the toolset. Reading this might be of use to you, if:

  • You are single developer wanted to code something from CSS to SQL
  • You want to develop an app for yourself and experiment how it feels
  • You want to host with no or minimal cost but have an option to scale

TaskPad

Yes I wanted to develop a TaskPad application. So why yet another taskpad app? I wanted an app which will let me to tag my tasks. Then, I want to create reports to understand where I am spending my time. I looked for apps and could not find one that perfectly meet my needs. So I was out to do one myself. Also another reason is I wanted to create something.

So here is here is the app.

TechStack

I will list down the technology stack I used and give the details as i ended up here:

The complete codebase can be found in github.

UI

This was easy one to go with React.js for below reasons:

  • React.js is gaining lot traction and has wide libraries
  • Declarative style of development is a less error prone
  • All JavaScript is a big win to learn JS and develop as well
  • In case I grow this app to mobile platform, React Native is handy with the mantra

learn once and apply anywhere

With react narrowed down I was stuck with which styling framework to pick. The compelling options are:

  1. Material UI
  2. Bootstrap
  3. Materialize CSS

Finally, I decided not to use any library and just use simple CSS and style the site myself. So why did I decided to do this way:

  • All of the above libraries has a learning curve (and I wanted to develop my MVP fast)
  • These libraries can bring friction with other 3rd party components I will use
  • My site will also have yet another library look and feel

Trust me it was not that difficult to learn and apply CSS for just what you need. The big advantage is you feel greater control over your site design and also learning the basics will be lot helpful. I would highly recommend CSS In Depth book if you are taking this path.

Backend

This is one of tough choice for me. At work I program Java and competing options for me are:

  1. Java
  2. Node.js
  3. Golang

And I finally selected Golang. Why?

Java: for the purpose of this app, Java is not right fit for me. The reasons are:

  • Huge layer of frameworks (and growing layer like SpingBoot, Flux etc)
  • High memory usage (cost is directly proportional to resource usage in cloud)
  • Not very dynamic for developing a fast paced MVP app

Node.js: It is really tough to decide NOT to to use node.js for this “kind” of app. But didn't pick node.js for reasons:

  • Growing tool complexity (build, lint, test etc etc)
  • No type system. Might hurt when the project grows (TypeScript helps, but adds in another layer to tool and learning curve)
  • Debugging is pain (with call stack)
  • Changing async programming models (promise, async await, etc)

Golang: after much of experiementation I decided to use Golang for this app. The reasons are:

  • Simple language and not much cognitive load to learn and apply. If you invest once you can leverage the skill for many such apps.
  • Many tools including type system comes within (no hunting of creating development eco system)
  • Best performant. My personal perf test can be found here
  • After working in multiple BE languages, I personally feel Golang is liberating and gets the job done. Few well thought basic primitives that can be combined elegantly for multiple use cases. Highly recommend the book.
  • Simple, no friction libraries:
  • Golang gin for web REST framework

Authorization

The options that I evaluated are:

  1. Custom
  2. Auth0
  3. Firebase Auth

The reasons I selected Auth0 are:

  • Wide range of support
  • Liberal free limits
  • Well documented APIs and examples

Database

The options that are applicable for this project are:

  1. MongoDB (mlab)
  2. Firebase (firestore)
  3. Postgres SQL

This is really tough choice as you need to balance between the data model and cost. MongoDB and Firebase is NoSQL data stores. And Postgres provide a relational model. For Taskpad app, relational model fits better than NoSQL. Why is that?

  • The app need to query based on various task state (pending, date etc)
  • App needs a reporting capability that need to query/aggregate the data to present the data

Both of the above features, need data model that is suitable for both transaction and reporting needs. SQL is best for this kind of situation. From a cost standpoint Firebase is best, but it constraints on following options:

  • Data model may not suite for all types of query
  • Vendor lock with google
  • Limited APIs and no Golang client

And why not MongoDB:

  • mlab is the best cost effective option. But the free tier is too limiting

Hosting

Now another big question is where to host the app? There are lot choice her, but I came up with the key requirements for myself here:

  • It should be free or low cost to start with
  • It should be PAAS as I am doing this project alone and in side. Going with PAAS will save me time to setup infrastructure
  • It should provide storage of my need (Postgres, in this case)
  • If PAAS, it should provide Golang as a platform
  • The cost model should be predictable as I need to budget this each month on my personal expense
  • If PAAS it should not limit or change the way apps are developed with standard Golang platform

The options are:

  1. Heroku PAAS
  2. Digital Ocean (though not PAAS)
  3. Google App Engine (standard option)
  4. Firebase app

After much experimentation I elected Google App Engine (standard version). Let us first nail why not others.

Heroku is a good choice. It is simple to use and has latest Golang platform. The reason not to select for this project is that free tier is limiting. It will shut down periodically and when user connects it will take time to boot for first time. Another reason the Postgres add-on is highly priced for a hobby project.

Digital Ocean is an excellent option for this kind of personal projects. It has a very predictable cost option (starting $5 / mo). Also being IAAS means you can install any software of your needs. I will certainly use this for my next project but the reason I do not select for this project is, it is IAAS and I need to setup many things myself. Also, in case my app becomes popular (every dev’s dream) I need to ensure the data is not lost and setup replication all by myself.

Firebase is limiting to do everything from client. The option looks like suitable for a mobile only app, but for web app this may not fit well. Also you are locked-in with firebase all the time. This is best w.r.t cost as the free tier is vert liberal with PAAS model.

Google App Engine seems to fit the bill for all what I need for this app. With standard version following are the possibilities:

  • First with Go 1.11 version you can the a standard go web app as is to host in the PAAS. No constraints!!
  • The free quota that is provided is very generous. Thanks Google!
  • The PAAS model comes with lot of goodies that you can start using your app in a almost production scenario:
  • Monitoring the app is out of box
  • With standard log API all your logs are available in console
  • Has ability debug the production app (though for Go it is pending at this time)

You can use CloudSQL which is a managed version of SQL database. The caveat is cost becomes high. But if you select carefully you can manage to get for very low price (INR 1000) to start with. This gives a freedom to start you app with low cost but when you need you can add more power easily like replication, backup etc.

App Design

Okay.. so once all tech stack is selected, I wanted to quickly tell how I structured the app and deployed.

App Structure

I wanted to maintain this app as a single repo project both (UI and API). After few trials below is my proposed structure for this app:

The root of the project is a Golang app (main.go) that serve UI assets and also REST API. As you can see I’ve kept package.json in the root. Thought this is a golang project, I see value in using node.js to run multiple commands. You can see the scripts tag of this file is repo.

The UI folder contains app created using create react app. The notable change I did to package.json (of UI folder) is:

  1. Move the assets to one level up so it can be copied to Google Cloud to serve by main.go. Note: Google App Engine use .gcloudignore to specify the files to be ignored during deployment. This file is configured to ignore the UI folder but NOT the ui-dist folder.
"postbuild": "mv ./build ../ui-dist",

2. Added proxy tag so that during development the Create React App connects to Golang app started locally. This way I can run side-by-side of the API and UI servers during development. This is so handy!

"proxy": "http://localhost:8080"

See the package.json of UI folder in the repo.

Environment Variables of Golang App

I basically created dev and prod environment for this app. For production the environment variable are configured in app.yaml. GAE reads this file during production. During development I set the local development configuration of DB and Auth0 before I start the dev server. I came across a very sweet ool that helps in live reload of Golang API file changes call gin-reload. Again see the start command of package.json in root on how I set the environment variables. The code in main.go reads these environment variables and valide them before startup.

connectionString := os.Getenv("POSTGRES_CONNECTION_STRING")auth0Domain := os.Getenv("AUTH0_DOMAIN")
auth0ClientID := os.Getenv("AUTH0_CLIENT_ID")
auth0Audience := os.Getenv("AUTH0_AUDIENCE")
auth0Callback := os.Getenv("AUTH0_CALLBACK")

Golang App Structure and DI

The API folder has below structure with respective GO modules in each folder.

API folder structure for GO components

The main.go file create instances of controllers and do the required dependency injections.

taskController := controllers.TaskController{}
taskController.Init(db)
userTagsController := controllers.UserTagsController{}
userTagsController.Init(db)
taskMetricsController := controllers.TaskMetricsController{}
taskMetricsController.Init(db)
reportController := controllers.ReportController{}
reportController.Init(db)

Auth Middleware

Using Auth0 for an app is breeze. The documentation is so easy. For GO API to validate the token I used following libraries

jwtmiddleware “github.com/auth0/go-jwt-middleware”
jwt “github.com/dgrijalva/jwt-go”

Please see auth-middleware on how token from UI is validated before serving any requests.

App Deployment

Currently I build the app in my machine and deploy i using google cloud tool.

Closing Thoughts

I hope this article helps someone in developing a hobby or personal app with some pre-selected options and they do not have to undergo same experiments I’ve done myself. The options presented in this article are not the ones that are best, but best suited given the requirements like this. I hope this will help someone to jump start to create an app. Happy Coding. Thanks for reading so far.

--

--