Pronounced "frōg" as in "yogurt". This repo shows how to deploy a website to a ton of decentralized solutions so it will stay up.
-
IPFS This will last until no one pins it
-
Filecoin: Deal Pending... This will last till my X months deal is up
-
Arweave (Gateway) This will last forever (or at least the location of the data at that hash, the gateway might go down)
-
Sia This will only last 3 months if I don't renew the contract, also only I can see it.
-
Sia Skynet (Web3 Portal Gateway) This will only last 3 months, and you need to use a Skynet API Key in the header. Use the below command:
curl --location --request GET 'https://web3portal.com/_AZKZDBq_o4N3440GYb6_ow5yAFsrLW2F2idlHE-UcMoog' \
--header 'Skynet-Api-Key: CJMSR68MCOINQ3OCP51LMI3RLU6JG8KLS4GDS02VJ4C9GT4PGP2G'
-
Ethereum (NFT Address: 0xD8E1A2Bf94D72Cca7C6584B502FF05F618FCC509) This will last forever
-
ENS This will last until no one pins it or I forget to renew it in 30 years, but it has a Sia, Arweave, and ETH Address backup in the ENS text records
GitHub isn't rendering these links correctly, see the full dataURI in the comments at the bottom of this file.
- Small Site Example- Unstoppable Froge
- Unstoppable Deployments
- Table Of Contents
- Getting Started
- Unstoppableness
- Name Servers
- Censorship & Unstoppableness
- Base64 Encodings Explained
- Other Considerations
- Store UI on all decentralized storage
- IPFS
- Filecoin
- Arweave
- Sia
- Skynet
- Ethereum
- Add Domain Namers
- ENS
- Unstoppable Domains
- Store code on all decentralized git
- Radicle
- Sourc3
- Add Logic to Smart Contract Platform (ETH)
- We don't have one, but this would be the easy part
- git
- You'll know you did it right if you can run
git --version
and you see a response likegit version x.x.x
- You'll know you did it right if you can run
- Nodejs
- You'll know you've installed nodejs right if you can run:
node --version
and get an ouput like:vx.x.x
- You'll know you've installed nodejs right if you can run:
- Yarn instead of
npm
- You'll know you've installed yarn right if you can run:
yarn --version
And get an output like:x.x.x
- You might need to install it with npm
- You'll know you've installed yarn right if you can run:
If you're familiar with
npx
andnpm
instead ofyarn
, you can usenpx
for execution andnpm
for installing dependencies.
- Clone this repo, install dependencies.
git clone https://PatrickAlphaC/unstoppable-ui
cd unstoppable-ui
yarn
- Check out the UI!
yarn dev
Open http://localhost:3000 with your browser to see the result.
Get the joke?
First, we need to create a static build of our app.
yarn next build
yarn export-ipfs
yarn export-relative-links
This will generate all the code we need in a folder named unstoppable-ui-static-export
and relative-links-output
.
IPFS stands for Interplanetary File Storage, and it's a way to store data to a network in a permissionless manner to a distributed and decentralized collective of IPFS nodes. When you upload a file you get a unique IPFS Hash that can only represents the data that was uploaded. Once uploaded, other nodes can "pin" that data, which is when these nodes cache the data themselves so that there are more copies of the data.
IPFS doesn't have any data persistance guarantee, meaning IPFS nodes only pin data they care about and don't get paid to do so, but is a way to get a unique hash for a single piece of data. This means that if you point to an IPFS hash, at least 1 node has to host that data, or you'll get a blank page when looking it up. This also means that with this one hash, the worst that you can get is a blank page and never wrong data, since the hash can only point to the exact data that is associated with it.
Install the IPFS Desktop app. You could install the IPFS command line too, but the desktop app is nice.
- Open the app and click
import
->folder
- Choose
unstoppable-ui-static-export
and hitupload
You'll now have this folder on your IPFS node!
- Pin it, share it with everyone and tell them to pin it.
You now have a CID with your pinned Website! Copy your CID from IPFS, and paste it into your browser with an ipfs://
prefix.
If you have a IPFS enabled browser with something like brave or your browser has IPFS Companion, you can go to the following URL in your browser:
ipfs://QmUrF435TTvK6wQGUEJ5W6mLTokyD98do2LHmPwk29amed
Or
ipfs://bafybeidaxlgco3us3dbs2svojipcfvwl4e6dwne3wohlhmxd2ozjdexbxy/
Ask centralized projects like Pinata or nft.storage to host your data on other IPFS nodes for some redundancy.
Now this is great! The next step on our journey is hosting to Filecoin. IPFS is great, but if we are the only node on the planet that is hosting the data, we could get shut down! So we need to have our data hosted on a decentralized blockchain that can't get shut down! So we want to store it on Filecoin.
Now... The raw saving to Filecoin... It's really hard right now. You can follow these docs to store data after running a Filecoin node. Just note, the Filecoin (lotus) node is... pretty big.
-
Run a filecoin (lotus) node
-
Convert our folder to a
.car
file
yarn ipfs-car --pack unstoppable-ui-static-export/ --output static-output.car
- Import the file
lotus client import --car static-output.car
Take note of the out put, like so:
Import 1661260127537379662, Root bafybeifz67t7vcm7gbtifgomwm7rpqsgob4gli4hbprr6fsrz2rrba6oii
- Follow the rest of the Filecoin docs to create a deal with:
filecoin client deal
Now the Filecoin deployment process can get... tricky. An easier way for us to deploy to Filecoin (but not censorship resistant!) is FleekHQ.
Just follow their docs, deploy your code, and BOOM. You'll have a deal setup with IPFS & Filecoin! You'll need to integrate Github as well. I'm going going to go over it here since you should follow their docs.
For the build command, use:
yarn fleek-install && yarn build && yarn export-ipfs
For the publish directory, use:
unstoppable-ui-static-export
Right now, you can use centralized sites like web3.storage or nft.storage to help facilitate deals with Filecoin.
Arweave is the "nuclear" option, in the sense that all data is stored on Arweave chain. Sia & Filecoin store contracts and points to hosts hosting the data, the Arweave chain stores all the data.
Now this isn't to say that every node on the Arweave chain holds all the data, not quite. The Arweave network works by mining new blocks, and nodes get paid to mine these blocks. In order to mine the next block, they will need to have some random data the chain is looking for at the time of mint, if they don't have the data, they will have to get a new random number, which takes extra time meaning they will be slower to mine the block!
This also means, that each node is incentivized to store "rare" or not well duplicated data, since they will be quicker to mine blocks where the rare data is randomly chosen.
To upload to Arweave, we are going to use arkb
, which is a node-as-a-service tool for Arweave. Otherwise, we'd have to run our own node.
And I'm not setting up a 90TB node.
- Export another output
yarn build
yarn next export -o relative-links-output
- Update to relative imports
Arweave can only understand relative imports. So, go into index.html
of the relative-links-output
file, and do a find & replace of "/
with "./
.
Then, update:
src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
with
src="./lily-pad.png"
- Get an arweave wallet/key
You can get some free arweave for testing here. Then just save your json key to a file.
- Deploy to arweave
yarn arkb deploy ./relative-links-output --wallet /path/to/wallet.json
Sia is a PoW blockchain that stores contract agreements with "Sia Hosts" that store your data. You can send a request to the sia blockchain which will split your data into many encrypted chunks and you can host the data on as many "hosts" as you like. This splitting up means hosts won't even be sure exactly what they are storing. You as a "renter" pay "hosts" Siacoin to store your data and you get to select as many hosts as you like for redundancy of data. Hosts put up some stake of Siacoin as a promise to host your data.
Hosts are challenges periodically by sending proof of storage to prove they have your data.
Right now, if you want to store data on Sia, you have to run a node, or figure out a way to setup a deal with the Sia blockchain. Skynet is the sort of RPC URL of Sia, where if you don't have your own node to facilitate transactions with, Skynet will do it for you. Skynet is a network where different people run their own "portal" to Sia. A portal is essentially their own Sia deal-making shop, and Skynet is the whole marketplace or mall.
Skynet makes the process of making deals with Sia much easier, and helps facilitate working with Hosts. Skynet is a centralization vector, but they were working on making "portals" much easier to access even if that Skynet portal goes down.
- Buy Siacoin
Siacoin is the L1 token that powers the Sia Chain.
- Run a Sia node.
You can run either the CLI or the desktop app. You'll need at least 40 GB of space (maybe more depending on when you read this), and you'll have to wait a long time for it to get synced.
I'm using the UI for these instructions.
- Rent from Hosts
Note: Skynet labs has ended, but Skynet is still a think.
Skynet is much easier. Skynet is a centralized eye into Sia - sort of like using Infura or Alchemy to interact with ETH.
- Build & Export the Site
yarn build
yarn next export -o relative-links-output
- Drop the
relative-links-output
file the UI
Go to web3portal and drop your file into the UI. This will setup a 3 month contract for our site on Sia.
You can also run:
node upload-to-skynet.js
Which will also upload your site
And finally, yes, we could even use ETH or any smart contract platform as a data storage system... but we'd probably spend a LOT of money.
But I ended up deploying a really, really, crappy SVG based NFT to Arbitrum, so that's cool. It's also deployed sort of weird, so if you have foundry you can see the "site" easily by running:
cast call --rpc-url $ARBITRUM_RPC_URL 0xD8E1A2Bf94D72Cca7C6584B502FF05F618FCC509 "tokenURI(uint256)" 0 | cast --to-ascii
And you'll end this base64 encoded... "site".
data:application/json;base64,eyJuYW1lIjoiVW5zdG9wcGFibGVGcm9nIiwgImRlc2NyaXB0aW9uIjoiQW4gTkZUIHRoYXQgaGFzIGEgdG9rZW5VUkkgZm9yIGEgdW5zdG9wcGFibGUgd2Vic2l0ZSIsICJhdHRyaWJ1dGVzIjogW3sidHJhaXRfdHlwZSI6ICJjb29sbmVzcyIsICJ2YWx1ZSI6IDEwMH1dLCAiaW1hZ2UiOiJkYXRhOmltYWdlL3N2Zyt4bWw7YmFzZTY0LFBITjJaeUI0Yld4dWN6MGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNakF3TUM5emRtY2lJSGh0Ykc1ek9uaHNhVzVyUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMM2hzYVc1cklpQjNhV1IwYUQwaU5UQXdJaUJvWldsbmFIUTlJalV3TUNJK1BISmxZM1FnZDJsa2RHZzlJakV3TUNVaUlHaGxhV2RvZEQwaU1UQXdKU0lnWm1sc2JEMGlZbXhoWTJzaUlDOCtQSFJsZUhRZ2VEMGlNQ0lnZVQwaU1UVWlJR1pwYkd3OUluZG9hWFJsSWo1SklHRnRJR0oxZENCaElHaDFiV0pzWlNCbWNtOW5JUENma0xnOEwzUmxlSFErUEM5emRtYysifQ==
Where ARBITRUM_RPC_URL
is your endpoint to arbitrum.
So someone took unstoppablefrog.crypto already, so I didn't bother to buy one from there.
However, I was able to pick up unstoppablefrog.eth from ENS for 30 years!
You can base64 encode sites to get a single URI that points to all the data! You can do this with folders:
zip -r my_zip_name.zip my_folder_to_zip
cap my_folder_to_zip | base64 > encoded.txt
echo "data:application/zip;base64,$(cat encoded.txt)" > uri.txt
And this will give you a base64 encoded zip URI of your site someone can download.
A "better" way to do this, would be to base64 encode a single HTML file, with all the CSS, Javascript, and HTML in it, and then you just base64 encoded that file. This way, our data URI can be of type html/text
instead of a zip, saving the users the step of unzipping the zip file.
The hard part is "flattening" our site into 1 file.
But once you do flatten it, you can just do
base64 website.html > encoded.txt
echo "data:text/html;base64,$(cat encoded.txt)" > uri.txt
To get your URI.
Storj: We didn't work with Storj since we couldn't find a way to connect with the network, host a node, or really much of anything without some kind of permissoned access.
0Chain: We didn't work with 0Chain as it doesn't have a mainnet yet, but is an interesting project to keep your eyes on.
We didn't go over hosting the code on a decentralized github as most of these are still in a beta stage right now, feel like there are a lot of developer experience enhancements to be made, and may change by the time this video comes out.
radicle: A decentralized Github
Sia chain holds contract agreements & merkle roots of data. Hosts put up collateral to promise they will store the data. The renter has to rent from enough hosts to get paid.