Permanently deploy decentralized React frontends to Arweave
A short guide on how to deploy censorship-resistant React frontends to a decentralized network like Arweave permanently
The need for permanent and decentralized frontend deployments
Most frontend devs I know in web3 uses Next.js + Vercel for their frontends. Probably for good reason, too. Next.js is fast & feature-packed, and no other platform has a better developer experience than Vercel.
While this stack serves well for most, it is a very centralized solution. Your frontend will be at the mercy of Vercel, who use AWS behind the scenes. Not very web3.
To be fair, most people don't need a decentralized frontend setup. But in some cases, it is an absolute necessity. For example, a decentralized exchange like Uniswap should never solely rely on a centralized provider. It makes sense to use a centralized provider as the primary option for speed & scale, but it is vital to have a backup that is permanent and decentralized. So if Vercel doesn't like Uniswap anymore, it doesn't mean Uniswap goes down completely. The idea here is to have a decentralized deployment ready, at least as a fallback.
Arweave lets you permanently deploy webpages to a decentralized network. This is why we will be going through the process of setting up a React app for deployment to Arweave in this article.
What we will be building
We will be building a very simple React app that lets people connect their wallets, and deploy it to Arweave.
You can also visit the live deployed page and try it out yourself: arweave.net/wI-CGD-uca4Dx_KNODXPg1ypjd5acWQ..
Tech stack
We will be using Vite instead of Next.js for this project, for several reasons:
- Vite is FAST โก๏ธ (follow along and you'll find out)
- Next.js is basically a server that serves webpages. On the other hand, Vite runs fully on the client-side i.e. in the browser. For a frontend to be really decentralized, it should ideally be running fully on the client. We are going for an extreme here, but why not?
- It is super-easy to generate a fully static site using Vite. Using Next.js, it's a bit of a pain in the ass.
Apart from that, we will be using Rainbowkit ๐ to setup our connect wallet functionality.
Make sure you have Node.js and Yarn installed.
Project setup
Let's start off by setting up some boilerplate using Vite's handy CLI tool. In your terminal, run the following command:
Select the options just like in the screenshot above and hit Enter. The next thing we want to do is cd
into our newly-created project's directory and install our dependencies. We will also initialize an empty local git repo in the folder while we're at it.
Awesome! Let's now try running our app by running yarn dev
. Your app will be live on localhost:3000. It should look like this:
You see how fast that was? ๐ Vite means speed.
Building out the UI
Let's add a connect wallet button to our app now. We will need to install some dependencies for that:
Once that's done, let's setup Rainbowkit in our code. I'm just following the Rainbowkit installation docs here, nothing fancy!
Make sure your main.jsx
looks like this:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';
import '@rainbow-me/rainbowkit/styles.css';
import { getDefaultWallets, RainbowKitProvider } from '@rainbow-me/rainbowkit';
import { chain, configureChains, createClient, WagmiConfig } from 'wagmi';
import { jsonRpcProvider } from 'wagmi/providers/jsonRpc';
import { publicProvider } from 'wagmi/providers/public';
const { chains, provider } = configureChains(
[chain.mainnet],
[
jsonRpcProvider({
rpc: () => {
return {
http: 'https://rpc.ankr.com/eth',
};
},
}),
publicProvider(),
]
);
const { connectors } = getDefaultWallets({
appName: 'My RainbowKit App',
chains,
});
const wagmiClient = createClient({
autoConnect: true,
connectors,
provider,
});
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<WagmiConfig client={wagmiClient}>
<RainbowKitProvider chains={chains}>
<App />
</RainbowKitProvider>
</WagmiConfig>
</React.StrictMode>
);
And your App.jsx
like this:
import { ConnectButton } from '@rainbow-me/rainbowkit';
function App() {
return (
<div>
<div
style={{ display: 'flex', justifyContent: 'center', marginTop: '20px' }}
>
<ConnectButton />
</div>
</div>
);
}
export default App;
Your app should now look like this:
Try clicking that button and connecting your wallet. It should work perfectly fine. Rainbowkit is great! ๐โค๏ธ
That's all I'm going to do for the UI but feel free to get create and add whatever you want! I am moving on to the deployment setup now.
Prep for deployment to Arweave
To make sure our Vite app gets built and deployed to Arweave correctly, we need to make small adjustments to two files.
- File:
vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
++ base: '',
});
- File:
package.json
{
"name": "vite-arweave",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
++ "deploy": "yarn build && arweave deploy-dir dist --key-file wallet.json"
},
"dependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0",
},
"devDependencies": {
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"@vitejs/plugin-react": "^1.3.0",
"vite": "^2.9.9"
},
++ "homepage": "./"
}
The base
and homepage
options make sure that our app gets built and loaded on Arweave correctly.
We also added a deploy
script that we will run when we want to deploy our app to Arweave.
The next step is to create an Arweave account if you don't have one already and grab some test funds from the faucet. Go to this link: faucet.arweave.net and follow the instructions.
IMPORTANT: Don't forget to download your wallet during the step I've shown in the screenshot below and keep that file handy. You will need this later on.
After following all the instructions on the faucet page, install the arweave-deploy
CLI. We will make use of this tool to deploy our app. Run the following command to install it:
Quickly verify if the installation was successful or not by running this:
If all looks good, create a new file called wallet.json
at the root of your project. Copy and paste the contents of the wallet file you downloaded from the faucet into this file.
The wallet.json
file contains the seed phrase/private key for your Arweave wallet so let's make sure it does not get committed to Git. Add this line to the bottom of your .gitignore
file:
wallet.json
Now we're all set. It is time to yeet our app straight to the Arweave network! ๐
Arweave deployment
All you need to do now is to run yarn deploy
at the root of your project:
Remember to type in CONFIRM
when prompted! Now all you have to do is sit back and wait for your files to get uploaded to Arweave!
You will see a message similar to that if the deployment was successful. Let's check out what our app looks like. Click on that URL!
LFGG! ๐ YOU JUST PERMANENTLY DEPLOYED A REACT APP TO ARWEAVE! ๐ซก
Give yourself a pat on the back. This page will now live on Arweave FOREVER. No one can take this down. That right there is extremely powerful. ๐ช
You can find the final code in this repo for reference: github.com/Dhaiwat10/vite-arweave
Don't forget to follow me on Twitter or I'll be very sad :'(
Thanks for reading and feel free to DM me if you need help! Ciao! :)