The Split Client Stack
A modern application architecture
We get a lot of questions about the way that we build websites and apps here at Carrot, and while this type of architecture is nothing novel, I wanted to write this post as a reference to explain the basic architecture of our sites and the philosophy behind it.
Essentially, for any given web app, we split it into two separate projects, an API and a client. These two pieces need each other in order to function properly, but are still two entirely separate projects, whose only connection point is the API documentation.
The API can be written in any language, although ours are typically node or go. It should be an extremely light and straightforward REST API, taking in pure JSON and putting out pure JSON. It should have absolutely zero interaction or concern with how information is presented to users through the web interface, it simply reads or writes data when asked to.
If non-technical people need to make changes to the data, it can be done through a CMS which is integrated with the API (like contentful or rooftop), or connected directly to the database (product in development).
It’s important to note that the client does not include a server at all. It is simply a static site, that can be served as flat html files. This might seem uncomfortable for those used to apps in which the client and server are tied together, but I can assure you there is no type of app which cannot be built in this manner, and more efficiently at that.
So you might be asking, why split your app into two pieces? Doesn’t this just seem more confusing, or like more work? On the contrary, it’s less confusing, easier to work on, faster, more secure, and more flexible.
The approach is also mentally easier to manage. The data is pure — not mixed up with the view logic. The way you think about building an API is different than when you also throw view considerations in. It’s much easier mentally to set up a context around “I am building an API for a database” and “I am building a front-end for users”.
It’s also a lot more flexible and future-proof. As technology marches furiously forward, we end up with more and more devices and places we need to put apps very quickly. We can have apps for iPhone, Android, Windows Desktop, Mac Desktop, TVs, and the web now. And for a large company, it’s necessary to have at least three of those. With AR and VR coming up quickly, we might have more app destinations being quickly added to the requirements list. If you build your front and back end rolled together as a web app, then feel like building a mobile app, you’re in trouble. You’d need to un-bundle your back end from the web app into an API, or make a separate API and keep it in sync with the web app, etc. It would be a mess. However, when you start out with an API, you are set for life. As long as the interface you are building for can handle JSON, there is zero friction building out another interface for your data.
You also get some significant speed gains and complexity reductions from this approach, mostly due to the fact that your primary interface to users is a simple static site. Static sites are extremely fast and simple to set up and host. No more complex cacheing mechanisms or beefy servers are necessary to handle a huge traffic influx — static sites can handle tens of thousands of concurrent users at a time on a $5 digital ocean box running nginx. Price going down and speed going up makes this a substantial argument for businesses.
Finally, you have less surface area for security. While it’s possible to find a number of holes in a site’s security when the server is tightly bound to the client, when you are running a static site, the only things that can be insecure are your API endpoints. Locking these up is simple, and practices for keeping security holes out of APIs are common and well-documented. On top of that, you can apply the same practices across all your APIs.
Let’s Do It!
Does this seem like a compelling approach? We’d encourage you to give it a try. Here at Carrot, we tend to use express with postgres for the API, and spike for the client, but you can use whatever you want! Once we started moving towards this approach, we could never go back, and I’m sure it will be the same for any readers that decide to try it out as well.
And for those already using this technique, please feel free to drop a comment or some feedback if you have any tips or tricks. And of course, you are welcome to use this article as a reference for any time you need to explain your approach to someone who isn’t familiar yet.
Happy coding! 💻
If you liked this article, click the little green heart below to show your support. Thank you!