I’ve been trying to come up with a good general-purpose tech stack for building web apps for small, local community user-bases. There are lots of great “share-economy-style” collaborative use cases at this level of organisation and I want a vehicle to test out ideas, to see what works and what doesn’t in my local area, from a social standpoint.
I obviously want to make what I develop freely available in hopes that others might contribute ideas or code and I want people to be able to trust that it does what it says on the tin to be able to use it, so everything needs to go up on github.
I’m a big believer in the power of constraints to focus the design process and these were nice and clear for this endeavour in regards to the technology to be used.
- Cost – needs to be as close to free to operate as possible
- Usability – the barriers to someone using the apps built on the stack need to be as low as possible
- Administrative simplicity – spinning up an instance of the stack, needs to be a straight-forward as possible
- Open Source tech is to be favoured over proprietary (where feasible)
- Flexibility to extend into native mobile versions in future
Serverless Cloud Provider
Being a huge fan of the serverless paradigm and the opportunities it unlocks (not least from a cost perpective), I knew I would be leaning heavily on the serverless capabilities of one of the major cloud providers to build out my solution. Already being well versed in what Azure has to offer (and admittedly knowing precious little about the alternatives), the choice was easy.
Realtime comms on a shoe-string
Get an effectively free static website up is laughably easy these days. So many great services like now and glitch exist in addition to the big-name cloud providers who all have free tiers, but for me the trick was real-time communication (via websockets or similar) was never covered on those platforms (or at least not to the scale I needed to potentially support). Same goes for the many real-time “pub-sub-as-a-service” 3rd party offerings – their free tiers all stop at 100 simultaneous connections (which is probably way more than I need, but still a constraint that I could well bump up against at some point). Plus, as per point 3 above, I don’t particularly want people to have to sign up to multiple cloud providers to get this all working.
The solution: the distributed magic that is IPFS pubsub.
Interplanetary File System (IPFS)
I won’t go into any detail into what IPFS is here – the official website is as good an intro as you could want. Suffice it to say, it is a distributed storage platform for web content, including publish-subscribe realtime messaging capbilities (experimental feature). You don’t have to pay to host an IPFS node, and through some voodoo that I have no idea about, you can even host one in a web browser (a decent modern one). So basically, we get ephemeral (don’t expect it to stick around in the IPFS network) realtime comms for free.
N.B. In the next installment in this series of posts, I’ll be persisting the realtime messages to Azure Table Storage… stay tuned…
Reactive Web Framework – Cycle.js
I’m a relative newcomer to React (love React Native, less enamoured with the original web version), but having worked with RxJS on a large Angular project recently, I was keen to see if I could find a framework that does a better job of managing state (yes, React has redux and and various side effects plugins, but they all seemed a little tacked-on) and uses the power of observables and found one in Cycle.js
Cycle has state management as it’s raison detré or at least, the way that it is structured kind of relegates state to a by-product of how data flows through your application, as opposed to treating it as an object you need to explicitly maintain.
Cycle uses a abstraction called a “driver” to handle any external effects (incoming or outgoing) to your application. The primary ones are drivers for interacting with the virtual DOM and making HTTP requests, but there are many others, including myriad community efforts. I couldn’t find one for IPFS, so created one to wrap the ipfs-pubsub-room helper library.
Here we are setting up the incoming (listening for new messages being broadcasted) and outgoing (broadcasting messages input by the user) observable streams. There are more API methods for ipfs-pubsub-room (e.g. for sending private messages to individual peers) but for this example, we’ll stick with the basics.
A quick note on importing modules: I wasn’t able to get IPFS-JS to bundle cleanly on my Windows machine, so am just loading from a CDN in a script tag. Works just fine for the purposes of this demo.
Show me the demo already!
Alright, you’ve been patient – here you go: https://ipfs-cycle-chat.azurewebsites.net/
N.B. Use Chrome for best results – haven’t seen this work in IE or Edge.
I won’t paste the rest of the code here, but you check out the full sample at https://github.com/balbany/ipfs-cycle-demo. Note that the main logic of the Cycle.js app is lifted pretty-much wholesale from CreaturePhil’s cyclejs-chat socket.io sample (cheers Phil!) and the styling is pilfered from here.
Just the beginning…
As alluded to before, this is just the first in a planned series of posts as I build out my little project that I’m calling Community AppStack for now. Please check back for the next installment (or follow me on Twitter @BruceAlbany) and let me know if you liked this one in the comments!