- 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:
-- album.css // CSS for the album page
-- base.css // shared CSS
-- main.css // CSS for the main app
index.html is used as the interface for the main app, and
album.html provides the interface for the album pages.
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
To get started, we’ll add a
click listener to the “New album” button in
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
- On line 13, we read
album.htmlfrom the main application’s Dat archive, and write it to
index.htmlin the album’s archive. This means the
album.htmlfrom 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
<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
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
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 from
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:
Or view the full source.