Serve your Fauna Single Page App from IPFS
IPFS is a distributed file system for the web. It uses content-addressing so that popular content is served by more peers, instead of overwhelming a single source. This also means content is validated by clients and can be received safely from any source. IPFS resources can be provided to web clients from any gateway, and it’s simple to configure DNS so that users don’t even know IPFS is the underlying technology.
This article will show you how I ran my favorite Fauna single page app on IPFS. It was easy. The hardest part was the bit about relative paths in my create react app build configuration, which this post will make easy for you. Follow along with these steps, and you’ll be set up in no time.
As a result of combining Fauna’s global availability and serverless pricing with IPFS peer-to-peer storage, this application model gives robust worldwide access at low cost. Apps deployed using Fauna and IPFS will be able to scale beyond millions of users, without requiring code or architecture changes.
Install the IPFS tools
Before you start developing, it’s worth it to install the IPFS tools, which include the option to run a local gateway daemon. Download the latest go-ipfs package here and follow these instructions for your platform.
Clone the app code
To obtain the latest code, run:
git clone https://github.com/fauna/todomvc-fauna-spa
cd todomvc-fauna-spa/
npm install
We won’t cover the application logic in this post, except to say that it uses Fauna’s security APIs for user identity and access control. This allows fine-grained control over the database privileges that backend processes can operate with, and enables single page and mobile applications to connect directly to the database.
Test your app with live code changes
If you are familiar with create react app, you are probably already playing around with the app by using npm start, which starts a development server locally and allows you to see code changes reflected in the browser in real-time for quick iteration. Thank create react app, and the tools it’s built on!
When you run it, you should see something like this:
Any changes you make will be reflected immediately on the development server. You won’t need to make changes to the code as part of this article, but live reload is one of the most powerful features of create react app’s development environment, so take a moment to appreciate it.
Configure your app for relative paths
If you are running the example app above, this step has already been done for you. I’m mentioning it because you’ll need to do it yourself if you start a fresh app.
The default build output from create react app’s npm run build contains URL paths based on the pattern {homepage}/static/assets/… by setting “homepage” : “.” in your package.json you are able to set a relative build page. (If you are on an older versions of create react app, this will be "homepage": "./", instead.)
You can tell you got it right when you open your build/index.html file and the links to css and js bundles start with ./static/ instead of /static/ or http://example.com/static/... create a static build suitable to serverless hosts like Netlify, and Neocities, and in this case IPFS. The same build configuration should work in all cases, so feel free to check in your “homepage” : “.” change to package.json.
Deploy it
Now that you have run npm run build and validated that build/index.htmlcontains the correct URL paths, you can add the build to IPFS by running ipfs add -r build which will recursively add the site to IPFS, with output like this:
added Qmb3qYy89Q9d2HV3S26d4JD3TGGUJXQBJePbepKuX77zWP build/asset-manifest.json
added Qmci3NaiZpMDoGMAG5NRcWCfRTekxdGtUj69fjdwJMQv2W build/favicon.ico
added QmdvJ2NyPQKebmJo9dR5PB1TL8tL3puEBjN73pi8soQRf9 build/index.html
added QmVDLWb9FKR3MzoT11XmpBoiV79jsL3F8qozRxonAeKATX build/static/css/main.64cc0607.css
added QmbF2KAreFn41VVzYKqZttH7qoStjvdgo26xbK8NgfFJKy build/static/css/main.64cc0607.css.map
added QmUvAnr8Z7RomrZx5fSR2gBq5mi6EDgsMEWgr4MLPkXozr build/static/js/main.ec74f5df.js
added QmUmw6CBVbndEUqamTwGnFJst2qyEQoUoAiBPDMHxmiHoA build/static/js/main.ec74f5df.js.map
added QmdD1cVeEkckCntAiRHHQqJxnQHnYVadWP5T2z9tZzZ9Ng build/static/css
added Qmd3T4mqKYSDKsRGNfxaowtxQ6nA2Zi96nHFUbbuagh2KB build/static/js
added Qma1ajJXuWPotQ3TuEMmBNN1bp9ccz4FyCChCLAHCqCjYH build/static
added QmRdrpAVPu1SHDseh71G8bKCSkPwZ8SF3NkUX1PfSYCt8A build
2.41 MiB / 2.41 MiB [========================================================================================] 99.98%
Now you can access your app on the web via a gateway. Your local IPFS daemon will make it available at
http://localhost:8080/ipfs/QmRdrpAVPu1SHDseh71G8bKCSkPwZ8SF3NkUX1PfSYCt8A/ and you can also find it publicly via http://ipfs.io/ipfs/QmRdrpAVPu1SHDseh71G8bKCSkPwZ8SF3NkUX1PfSYCt8A/
Pin your files
Just adding your files isn’t quite enough. You also need to pin them somewhere or else they won’t stay on the network long. If your IPFS daemon is running on a workstation that doesn’t shut down, pinning to your local workstation should be fine. If you are like me, your laptop is offline at least when you’re asleep. So I pinned my content using https://www.eternum.io/ which allows you to buy IPFS storage at affordable rates. To pin content to your local IPFS daemon, run:
ipfs pin add -r /ipfs/QmRdrpAVPu1SHDseh71G8bKCSkPwZ8SF3NkUX1PfSYCt8A
The hash in this command will be the same as in the last line of build output above, and the -r option pins all the files recursively. Now anyone who requests your content from a public gateway will be able to see it.
Set up DNS
A URL like http://ipfs.io/ipfs/QmRdrpAVPu1SHDseh71G8bKCSkPwZ8SF3NkUX1PfSYCt8A/ is not very human-friendly. Luckily, IPFS provides a clean way to link a DNS name to the URL. Basically, you use your DNS provider to point your subdomain at a public gateway, and add a specific TXT record with metadata that tells the IPFS gateway which piece of content to serve for that name.
Additionally, the IPFS naming feature called IPNS can be used to alias your content to your IPFS cryptographic identifier. This allows you to point DNS to your identifier, and have it resolve to the content hash you choose. This means you can update your application’s codebase without making DNS changes, just by publishing an updated to IPNS.
I won’t duplicate the instructions here, but if you are putting your app on the public web, you’ll want to follow them. Here is an article about how to publish content using your IPNS identifier. And here is an article about how to use DNS to serve your content from Cloudflare’s CDN.
The final result
If you do the work to configure DNS, your site will live at a normal URL, and your users will be none the wiser. Here is the human readable URL at which you can see my copy of the app running: http://todomvc-fauna.edgemob.org/
The IPFS distributed filesystem is a good mix for Fauna, because both are globally available with serverless pricing models. Fauna’s ACID transactions and multi-region consistency contrast with the IPFS gradual distribution model. Because they have different strengths, they are useful together. For instance, Fauna can be used to track account status and profile data, while IPFS could be used for social media image uploads. This combination offers the best of both worlds, so developers can dip a toe in the waters of the distributed web and still benefit from convenient cloud database features.
If you enjoyed our blog, and want to work on systems and challenges related to globally distributed systems, serverless databases, GraphQL, and Jamstack, Fauna is hiring!
Subscribe to Fauna's newsletter
Get latest blog posts, development tips & tricks, and latest learning material delivered right to your inbox.