Skip to content

Instantly share code, notes, and snippets.

@mrcnski

mrcnski/blog.md Secret

Created September 30, 2020 11:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrcnski/8d6a1a268b97522fa5efb803bed7bdef to your computer and use it in GitHub Desktop.
Save mrcnski/8d6a1a268b97522fa5efb803bed7bdef to your computer and use it in GitHub Desktop.

Creating Your First Web App on Skynet

If you've been following the Sia project (or our blog here on Medium) then you probably know about Skynet, a decentralized storage platform built on top of the Sia blockchain. You may have also seen that, beyond just sharing data, people have been using Skynet to host entire web applications called "Sky Apps", including an impressive livestreaming platform. Maybe you wanted to build a sky app yourself.

You can do it too!

In this tutorial we'll be loosely following the skynet-workshop repo, which itself is based on our video tutorial. We'll go through and create a simple application together that takes an image from the user and generates their own media page on Skynet. It will look like this:

[screenshot of application]

Prerequisites

The goal of this tutorial is to make your introduction to web development on Skynet as smooth as possible. However, some minimal prior experience with HTML, JS, and the command line may be required. If anything is unclear, check out MDN or ask one of us! (The author can be reached directly at marcins@nebulous.tech.)

Software

Make sure you have the following software installed on your machine:

Setting Up The Project

Initialization

Let's use the command line to make a new directory for our project and enter into it:

https://gist.github.com/b5a465ec67a24d80fcb89dcd47d30ee0

Initialize an empty git repository for version control:

https://gist.github.com/fe223fdf212deffa45afbd9387dacaf9

Now initialize a brand new NPM project in the directory:

https://gist.github.com/f32bda26f6bbeba6ebf50f61a771a3f2

Running this will bring up a series of prompts allowing you to customize your project. Accept the defaults or change them at your leisure. You can always edit your project's settings in package.json after.

When you're done with that, there's a couple changes to make in package.json:

https://gist.github.com/82ed3b99ed88d6f01fd586a958472232

Installing Dependencies

We'll be using Webpack, a standard way of packaging web applications into standalone bundles. Let's add webpack as a dev dependency to our project:

https://gist.github.com/ba1a92c0049a4f48c98090522ec2d86a

You'll also want to install our Browser JS SDK, which is the library that allows us to make Skynet calls in our applications:

https://gist.github.com/bb4fff6c4a3aadcad609fc2f1e26e385

You'll notice that a directory called node_modules/ was generated. This contains our app's dependencies -- generally you don't want to commit this into version control, so let's ignore it. Create a file called .gitignore with the contents

https://gist.github.com/d716e2ea059e2ece4aade8b18886e2db

Adding The CSS

First, we want to add a CSS file for styling, so that our application looks nice. Create a folder called dist and run the following command:

https://gist.github.com/00132d5159bb0986f93e1a6338558e61

We won't be explaining this file as it is beyond the scope of this tutorial.

Adding The HTML

Now we'll be creating the structure of the app in HTML. This will provide the layout of the page; we'll add interactivity and behavior to our app later, using Javascript.

https://gist.github.com/55af88b5af6cfe2f909c56d020b5ab06

This will create a file in dist called index.html. A file with this filename, if it exists, is loaded by default whenever a Sky App is opened.

Let's go through everything, piece by piece.

https://gist.github.com/2c79ccccd29e1412dfd9ac53d9e9144c

This is the start of our HTML. We provide a header, which defines the title and links to the CSS file we are using.

Exercise: Replace the title of this app with a different one.

https://gist.github.com/4023d9afcbdb4eb3285595b8abbde2d8

Next we begin the body, which defines the actual visible layout of the page. Here we provide the top-level h1 header, as well as the form that allows the user to pick a media file to upload. We give this form the #mediaFile ID. Input forms are the only way the browser can access the user's local files.

Exercise: Modify the above code to inform the user that they must pick a .jpg file.

Exercise: Modify the above input form so that the user can only select .jpg files.

[Picture of what we have so far]

https://gist.github.com/de5e1b3dae771a447dd193c155ae8f20

This is a span with the ID #file-selected. Here we will display the path of the file once it's been selected. Until then, this <span> element is not visible.

https://gist.github.com/0a74b8d1aa0d3cf80a1ebed290c6180a

The comments here are fairly self-explanatory. The onclick event specifies what happens when the "Create Media Page" button is clicked. It will fire the createMediaPage function with the selected media file as input; this function is defined in the Javascript file we look at later.

Question: What happens if the user selects more than one file?

https://gist.github.com/bac30d4a15c4c0690982cd40fcd7add0

This <a> element is another empty HTML element that is used to fill in the generated skylink after the user creates his media page.

https://gist.github.com/bcd876caf6ad3c232417d1452df9de24

Here we include two scripts. The first is main.js, the Webpack bundle that we will generate later from our Javascript code. This script provides the createMediaPage function that is triggered when clicking "Create Media Page".

In the second script, we select the input form with the mediaFile ID and add an event listener: for any change in the input form, we update the text content to be the path of the selected file.

Adding The Javascript

Let's create another folder called src. Run the following to download src/index.js:

https://gist.github.com/dcac653a1e781b1f2706cd620f42df1d

Again, we'll go through and explain every part of this code.

The first thing we do is import SkynetClient from skynet-js and create a new client:

https://gist.github.com/600cad4b346175c8f16f0b725e48c33a

The client can be created with additional, optional parameters, such as the address of the portal to upload to. For this example, we call SkynetClient without any parameters to let the SDK use the portal that our sky app is running from. For more about the Skynet client, see the docs.

https://gist.github.com/3d7798e4cb5633aa2ac6fe5bb0e95bd9

Here we start defining the createMediaPage function. The function takes a file from an input form as its only parameter.

Note: The window. part before the function name is required in order to make the function globally accessible from a Webpack bundle.

We'll be generating a new page on Skynet that displays the media file uploaded by the user. So, the first thing we do in createMediaPage is define what we want the new page to look like. Note that it contains complete HTML and that we include an image with the source media.jpg. This will be the name of the user-selected media file.

Exercise: Feel free to make the generated page more interesting in any way you wish!

https://gist.github.com/d9fecc0ae7b73cdc6433f8812546f665

Here we construct the directory that we upload to Skynet. It actually consists of two files: an index.html which contains pageContent, and media.jpg which is the image file uploaded by the user.

Exercise: Modify the code so that media files other than .jpg also work. The code should transform pageContent so that it points to a file of the correct file extension.

https://gist.github.com/764d670c61a13ec010cf650bdaceec94

Here we finally call the Skynet SDK to upload the files! First though, we create a try-catch block and an async function, since Skynet is an asynchronous library that throws errors. Then, we call the uploadDirectory method on client, passing in the directory of two files we created and calling it "mediaFolder". This returns a skylink which we then display to the user.

Exercise: Now that you've seen all of the code, here's a final exercise: Modify the app to allow the user to upload multiple files at once.

Building And Deploying Your Application

Building your application is easy:

https://gist.github.com/681eb329924f3e9370d171fe4cfcf7a0

This will generate a dist/main.js Javascript bundle which is the source script, referenced by our dist/index.html file.

To make your application accessible across Skynet you will need to upload it to a Skynet portal. We maintain the user-friendly siasky.net webportal but you can also use the command-line interface.

Whichever method you choose, you will want to:

  1. Upload the dist directory.
  2. Follow the returned skylink to your app.

That's it!

Conclusion

That's it! We hope that this tutorial was informative and helpful. Feel free to play around with the application and make further changes, or even use it as a starting point for your own ideas.

More Resources

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment