Familiar Day #1 - My new open source project for table-top roleplaying, built with modern technologies.
Published: 2019-06-18 18:36:06

As part of this series, I'll be (sporadically) walking you through how I built my upcoming open-source project, Familiar, and what difficulties and challenges I (hopefully) overcome along the way.

##What is Familiar?
[Familiar](https://github.com/NickBlow/familiar) is an all-in-one Tabletop Roleplaying game assistant, providing campaign tools, a virtual tabletop, and real time chat. It's named after a wizard's familiar, a small magical creature who assists them. As naming things is one of the hardest problems in computer science, I'm already partially there!

Eventually I'll need a cute logo though...

##Who are you, and why should I care?

I currently lead a small team building distributed systems at a start-up called [Wakelet](https://www.wakelet.com), serving many hundreds of thousands of people a month and tens of millions of API calls. I've been building cloud native applications pretty much solidly for about 4 years now. 

I understand the project is a little niche, but hopefully at the end of it, this series will have a great overview of how to build and architect a web app from nothing.

---

##Enough rambling, on with the blog post!

Staring at a blank piece of paper is always the hardest thing about writing, and software is no different. 


I always enjoy setting goals for myself, so let's start with setting some goals, and sketching some high level infrastructure.

##Goals 
I've added the goals to the README in GitHub, but I'll reproduce it here for posterity:

1. Modern front end, progressive web app, using best-in-class tools.
2. Responsive, sleek UI.
3. Performant, well architected back-end.
4. Cost effective infrastructure fully within GCP free tier - pay only for cloud DNS.
5. Take advantage of free tooling for open-source projects.
6. Full CI/CD.

##Goals in depth
###UI
Firstly, the UI. I'm no Android or iOS developer, but luckily [Progressive Web Apps](https://developers.google.com/web/progressive-web-apps/) are here to the rescue. They're definitely not quite ready for primetime, but in my opinion they're the future.

The tools I'm going to be using are [LitElement](https://github.com/Polymer/lit-element), because WebComponents are cool, and the library is really performant. Unfortunately it doesn't support Server-Side Rendering / isomorphic applications right now, but that's on the roadmap 😎.

I'm probably going to use some pre-made CSS and/or WebComponents, and I've been having a look at [Bulma](https://bulma.io) which looks quite cool, and I've used [Material Design Components](https://material.io) in the past. I'll be the first to admit I'm not the best at CSS, so I'm taking this as a learning opportunity.

For state management, [Redux](https://redux.js.org/) is a godsend for complicated projects. It's really the holy grail of state management, and there's not much more to say except that it's great.


###Back End

####Quick note on languages
I'm probably going to be using [TypeScript](https://www.typescriptlang.org/), and [GoLang](https://golang.org/).
I have a love-hate relationship with JavaScript, on the one hand it's amazing for quick prototyping, on the other hand you look away for 3 seconds and your new shiny framework is deprecated. Go is fast becoming my favourite language, it's simple, efficient and is amazing for microservice development. 

There are plenty of modern languages out there that are great, but sticking to two languages means I don't have to keep context switching, and they're both great for web development.

####Infrastructure and API design

The overall goal is to almost entirely fit into the Google Cloud free tier. In terms of raw compute this gives us 28 hours of App Engine to work with, alongside a free Compute Engine instance, and some Cloud Function Invocations.

Each service will be its own docker container, perhaps on [Kubernetes](https://kubernetes.io/), as managed Kubernetes is free on GCP (though I'm not sure how well that will work on one tiny free machine). I'm probably going to use [Traefik](https://traefik.io/) to route to the internal containers and issue SSL certificates. The basic set up I'm aiming for with Traefik will *NOT* work in cluster mode, so that's an exercise left to the reader. All the other services will be stateless docker containers, so can scale horizontally with no issues.
 
For serving the front end, I don't really know what I'll use yet, but there are so many options, I'll probably pick something out of a hat and it'll work well.

The rest of the backend will be a set of microservices, potentially communicating via [GRPC](https://grpc.io) if I'm brave enough, otherwise just over JSON/REST, with a [GraphQL](https://graphql.org/) API stitching them all together into one coherent whole.

For real time communication, I'll try to have it running on a separate server (possibly running on Compute Engine and everything else on App Engine). I'll use GraphQL subscriptions over Server Sent Events now that Edge is moving to Chromium and all other major browsers support it - this is pretty much finished and will probably be the first service to be open-sourced. Ideally I'll be able to get this serving over HTTP/2 as well.


###Build & Test Tools
Build tools/dev-ops are invisible to the user, but you miss them if they're not there. I'm going to start here, to force myself into good habits, and make sure that I'm not handcrafting any infrastructure. [Cattle not pets!](https://martinfowler.com/bliki/SnowflakeServer.html)

Infrastructure as Code (IAC) is great, many of the DSLs for IAC are not. I've used [Terraform](https://terraform.io) recently, and it's pretty nice, and cloud agnostic, so I'm definitely going to use it again.

For a build system, I have a lot of experience with [Jenkins](https://jenkins.io/), which is great, especially with their declarative builds with Jenkinsfiles. However, managing a Jenkins server is overkill. I'm not going to be doing lots of builds. I'm going to evaluate a couple of build services like [CircleCI](https://circleci.com/open-source/) and [TravisCI](https://travis-ci.org/), and pick one I find easiest.

For testing, I'm not entirely sure what's the best way to test WebComponents/ShadowDOM is right now. I really like [Jest](https://jestjs.io), but for DOM testing it includes JSDOM which doesn't support the Shadow DOM just now. [Karma](https://karma-runner.github.io/latest/index.html) actually runs on real browsers, which *do* implement Shadow DOM, so looks a good choice. Running on real browsers also exposes some of their quirks which might not be revealed by something else. Hopefully I'll have some better insights into this after writing my first few tests.

To bundle the front end up, I'll try to use [ParcelJS](https://parceljs.org/), because ideally I want something that *just works*, but I'll fall back to old trusty [Webpack](https://webpack.js.org/) if I run into issues.

##The ~~End~~ Beginning?

###Next time
Join me next time where I'll be writing some terraform templates for GCP, and spinning up some infrastructure!