Inside of the Beaker browser, we’ve implemented a set of new Web APIs for connecting apps to the peer-to-peer network. This is part 1 of a series about how to build peer-to-peer Web apps.
I recently published a peer-to-peer Photos app using the Beaker browser. Today we’ll step through how the app was built, and how you can make other peer-to-peer Web apps like it.
Introduction
The Photos app takes advantage of Beaker’s DatArchive
API, which has methods for reading and writing the user’s filesystem, and for publishing the files on the peer-to-peer network.
App requirements
- The user should be able to create albums and upload photos to their albums
- The user should be able to share individual albums with friends
Where will the photos be stored?
If you were to build this app on the traditional Web, you’d store the user’s photos on your own server, or alternatively on a static storage service like Amazon S3 or Google Cloud Storage.
But inside of Beaker, publishing files on the peer-to-peer network is as simple as using a builtin Web API. So instead of uploading the images to a remote server, we can host the photos directly from the user’s device!
Building the app
The file structure of the app looks like this:
/css
-- album.css // CSS for the album page
-- base.css // shared CSS
-- main.css // CSS for the main app
/js
-- album.js
-- index.js
album.html
index.html
The index.html
is used as the interface for the main app, and album.html
provides the interface for the album pages.
How album.html
is used might surprise you. We’ll talk about how it works in Step 1 below.
Step 1: Allow users to create albums
Step 1 is fairly simple, but it requires us to understand how peer-to-peer Web apps differ from traditional Web apps.
If we were building this app on the traditional Web, we’d store each album somewhere on a remote server. But in our app, each album will be represented as a new peer-to-peer website that’s stored and hosted from the user’s device.
So when the user clicks the “New album” button, the app will create a new website that represents the album and its photos. This means that in order to share an album with a friend, all you need to do is share the album’s dat://
URL!
To get started, we’ll add a click
listener to the “New album” button in index.html:
document.querySelector(‘.create-album’).addEventListener(‘click’, onCreateAlbum)
Then we’ll define onCreateAlbum
, which will create a new Dat archive to house everything that composes the album:
Let’s break this snippet down:
- On line 3, we first create a new Dat archive, which serves as a website specifically for the album.
- On line 10, we keep track of the user’s albums by storing it in
localStorage
. - On line 13, we read
album.html
from the main application’s Dat archive, and write it toindex.html
in the album’s archive. This means thealbum.html
from the main app’s archive will actually serve as the main page for each album we create.
If you view the source for album.html
, you’ll see that there are <script>
and <link>
tags that reference the main app’s CSS and JS, so if our app’s code is ever updated, the album pages will receive the updates from the main app.
Step 2: Implement photo uploading
Each album page has an <input type="file">
, so in js/albums.js
we add a change
listener on that input. When photos are selected, we read the data from each of the selected files. Then, we write the image data to the album archive.
Note: the archive object in the example below comes from a setup function that sets the archive variable using Beaker’s DatArchive
constructor:
const archive = new DatArchive(window.location)
Let’s start by reading the image files and writing them to the album’s archive. We use a FileReader
to get the data from each selected photo, then use Beaker’s DatArchive.writeFile
method to write to the archive.
Step 3: Display the user’s albums in the main app page
Recall that in step 1, when we created an album, we added the album’s URL to the albums
array, and then wrote a stringified representation of the array to localStorage
.
To display the albums, we’ll read the value of the albums
item in localStorage
, then render a preview of each album URL in the array.
In our setup function in js/index.js
, we’ll start by reading the albums data fromlocalStorage
:
Then for each album, we’ll render a preview of it in the main app:
Notice on line 23 that we use the url
attribute on the album. Each archive has its own URL, so we can embed images from the archive just like any other web page.
And that’s it! Now we have an app that displays album previews, creates shareable photo albums, and hosts photos locally on the user’s device!
Try it out yourself in Beaker! The app’s URL is:
dat://f0abcd6b1c4fc524e2d48da043b3d8399b96d9374d6606fca51182ee230b6b59/
Or view the full source.
Resources for building a peer-to-peer app
- Install Beaker
- Beaker’s API documentation
- Example applications
- Ask for help on Twitter, or join us in
#beakerbrowser
on freenode.