Deploying a website on SKALE Filestorage

Follow these steps to deploy a decentralized website using SKALE Filestorage and the built in Web3 server.

  1. Get a SKALE Chain Endpoint

    You can either use the SKALE-IMA-SDK for a local development environment using Docker containers, or get access to a DappNet chain. You’ll need to have the owner private key or a deployment-authorized private key, to permissively upload files.

  2. Prepare your files

    Assuming you already have built a statically generated website (if not checkout https://nextjs.org/, https://gohugo.io/, https://www.gatsbyjs.com/, or others, see a list here: https://jamstack.org/generators/). If you haven’t already built a site, then here is a simple code example that you can copy and paste.

    Save this as index.html
    <!DOCTYPE html>
    <link rel="stylesheet" type="text/css" href="styles.css">
    <html>
        <body>
            <h1>SKALE-ING</h1>
            <p>My first decentralized website.</p>
        </body>
    </html>
    Save this as styles.css
    body {
        background-color: #ccc;
    }
  3. Upload to your SKALE Chain

    Assuming the index.html and styles.css, or static site files are stored in a folder called test-skale, and you have already performed npm install @skalenetwork/filestorage.js~1.0.0, then create a script file with the following code:

    Save this as filestorageUpload.js.
    #! /usr/bin/env node
    
    const Filestorage = require('@skalenetwork/filestorage.js');
    const fs = require('fs');
    const Web3 = require('web3');
    
    // If not using the SDK, replace the endpoint below with your SKALE Chain endpoint
    let filestorage = new Filestorage('http://localhost:15000');
    
    // If not using the SDK, replace with the SKALE Chain owner key and address.
    let privateKey = process.env.TEST_PRIVATE_KEY || '<SKALE CHAIN OWNER KEY>';
    let address = process.env.TEST_ADDRESS || '<SKALE CHAIN OWNER ADDRESS>';
    
    let directoryPath = 'test-skale';
    
    // Bytes of filestorage space to allocate to an address
    // reservedSpace must be >= sum of uploaded files
    const reservedSpace = 3 * 10 ** 8;
    
    const files = fs.readdirSync(directoryPath);
    
    async function upload() {
        // Owner must reserve space to an address
        await filestorage.reserveSpace(address, address, reservedSpace, privateKey);
        for(let i = 0; i < files.length; ++i)  {
            let content;
            let contentPath;
            content = await fs.readFileSync(directoryPath + '/' + files[i]);
            contentPath = await filestorage.uploadFile(address, files[i], content, privateKey);
        }
    }
    
    upload();

    When executing, your files are sent to the SKALE Chain endpoint, routed to one of the 16 nodes supporting your chain, and is fed into the EVM in chunks, with a specific header to indicate these EVM messages are for filestorage. These messages are broadcast to the other 15 nodes to reach state consensus. On each of these nodes, a specific predeployed contract called Filestorage will process these chunks and store them into specific partitions. This way your files are replicated across 16 nodes, and served using an nginx container on each of the nodes.

  4. Execute the script

    Be sure to add execution permissions: chmod +x filestorageUpload.js and then run ./filestorageUpload.js.

  5. Access your website

    If you are using the SDK, just head over to http://localhost/fs/<ACCOUNT>/<FILENAME>;, or if using the above example, http://localhost/fs/<ACCOUNT>/index.html to see your SKALE Chain hosted index.html file. This is served by the nginx containers hosted on the nodes of your SKALE Chain. Be sure to replace the <ACCOUNT> with the non-0x prefixed address of the account that performed the upload. For example if 0xA23451234512345123451234512345123451234b performed the upload, then enter http://localhost/fs/a23451234512345123451234512345123451234b/index.html. More more information about the paths, see Filestorage Storage Paths.

The address in URL must be in lowercase.