A tutorial to build your first app on the decentralized web
Blockstack is a network for decentralized applications. This platform leverages a serverless architecture, which helps remove critical points of vulnerability. By eliminating these weak points, which have frequently fallen victim to hacks, Blockstack makes user data more secure.
Prerequisites: Knowledge of React.js will be required for this tutorial.
Blockchain tech can be complicated, but getting started doesn’t have to be. Blockstack’s 3rd party sign in/sign up/authentication makes it easy to get started developing apps and publishing it to a decentralized App store like App.co
I was able to publish this on App.co in less than a week
After integrating Blockstack, you have the option to either send the unique username that a user creates from Blockstack to your own API and build the user object that way, or use Gaia Storage, Blockstack’s decentralized backend provider. You can also opt to have a combination of both, where private user information like phone numbers and addresses are encrypted and stored in Gaia Storage but public information like comments or posts are stored in a public API.
This blog post is meant to simplify and abstract as much as possible. If you would like deep dive video tutorials, check out Tech Rally on YouTube (this is where I learned about Blockstack).
For now, we’ll cover getting Blockstack Sign In/Sign Out authentication set up. Let’s get started!
1) Install Blockstack Browser
2) Create your Blockstack ID (be sure to save your Secret Recovery Key somewhere safe)
In your terminal:
npm init react-app blockstack-tutorial
cd blockstack-tutorial
npm install --save blockstack@19.0.0-alpha.2
npm install react-app-rewired --save-dev
mkdir src/utils
touch src/utils/constants.js
open src/utils/constants.js
If npm install
gives you a problem, try yarn add
:
yarn add blockstack@19.0.0-alpha.2
yarn add react-app-rewired --save-dev
4) constants.js
:
import { AppConfig } from 'blockstack'
export const appConfig = new AppConfig(['store_write', 'publish_data'])
5) In your terminal:
touch config-overrides.js
open config-overrides.js
6) config-overrides.js
:
module.exports = { | |
webpack: function (config, env) { | |
return config; | |
}, | |
jest: function (config) { | |
return config; | |
}, | |
// configFunction is the original react-scripts function that creates the | |
// Webpack Dev Server config based on the settings for proxy/allowedHost. | |
// react-scripts injects this into your function (so you can use it to | |
// create the standard config to start from), and needs to receive back a | |
// function that takes the same arguments as the original react-scripts | |
// function so that it can be used as a replacement for the original one. | |
devServer: function (configFunction) { | |
return function(proxy, allowedHost) { | |
const config = configFunction(proxy, allowedHost); | |
// Edit config here - example: set your own certificates. | |
// | |
// const fs = require('fs'); | |
// config.https = { | |
// key: fs.readFileSync(process.env.REACT_HTTPS_KEY, 'utf8'), | |
// cert: fs.readFileSync(process.env.REACT_HTTPS_CERT, 'utf8'), | |
// ca: fs.readFileSync(process.env.REACT_HTTPS_CA, 'utf8'), | |
// passphrase: process.env.REACT_HTTPS_PASS | |
// }; | |
config.headers = { | |
"Access-Control-Allow-Origin": "*", | |
"Access-Control-Allow-Methods": "GET,PUT,POST,DELETE", | |
"Access-Control-Allow-Headers": "Content-Type" | |
} | |
return config; | |
}; | |
} | |
} |
7) In your terminal:
open package.json
8) package.json
:
{ | |
"name": "app-name", | |
"version": "0.1.0", | |
"private": true, | |
"dependencies": { | |
"blockstack": "19.0.0-alpha.2", | |
"react": "^16.8.6", | |
"react-app-rewired": "^2.1.3", | |
"react-dom": "^16.8.6", | |
"react-scripts": "3.0.1" | |
}, | |
"scripts": { | |
"start": "react-app-rewired start", | |
"build": "react-app-rewired build", | |
"test": "react-app-rewired test --env=jsdom", | |
"eject": "react-app-rewired eject" | |
}, | |
"eslintConfig": { | |
"extends": "react-app" | |
}, | |
"browserslist": { | |
"production": [ | |
">0.2%", | |
"not dead", | |
"not op_mini all" | |
], | |
"development": [ | |
"last 1 chrome version", | |
"last 1 firefox version", | |
"last 1 safari version" | |
] | |
} | |
} |
9) In your terminal:
open src/App.js
10) App.js
:
import React, { Component } from "react"; | |
import { appConfig } from "./utils/constants"; | |
import { UserSession } from "blockstack"; | |
class App extends Component { | |
state = { | |
userSession: new UserSession({ appConfig }) | |
}; | |
componentDidMount = async () => { | |
const { userSession } = this.state; | |
if (!userSession.isUserSignedIn() && userSession.isSignInPending()) { | |
const userData = await userSession.handlePendingSignIn(); | |
if (!userData.username) { | |
throw new Error("This app requires a username"); | |
} | |
window.location = "/"; | |
} | |
}; | |
handleSignIn = () => { | |
const { userSession } = this.state; | |
userSession.redirectToSignIn(); | |
}; | |
handleSignOut = () => { | |
const { userSession } = this.state; | |
userSession.signUserOut(); | |
window.location = "/"; | |
}; | |
render() { | |
const { userSession } = this.state; | |
return ( | |
<div className="App"> | |
{userSession.isUserSignedIn() ? ( | |
<button className="button" onClick={this.handleSignOut}> | |
<strong>Sign Out</strong> | |
</button> | |
) : ( | |
<button className="button" onClick={this.handleSignIn}> | |
<strong>Sign In</strong> | |
</button> | |
)} | |
</div> | |
); | |
} | |
} | |
export default App; |
11) In your terminal:
open src/index.js
12) index.js
:
import React from "react"; | |
import ReactDOM from "react-dom"; | |
import "./App.css"; | |
import "./index.css"; | |
import App from "./App"; | |
import * as serviceWorker from "./serviceWorker"; | |
ReactDOM.render(<App />, document.getElementById("root")); | |
// If you want your app to work offline and load faster, you can change | |
// unregister() to register() below. Note this comes with some pitfalls. | |
// Learn more about service workers: https://bit.ly/CRA-PWA | |
serviceWorker.unregister(); |
13) In your terminal:
open src/App.css
14) App.css
:
.App { | |
display: flex; | |
text-align: center; | |
height: 100vh; | |
} | |
.button { | |
max-width: 8em; | |
max-height: 4em; | |
font-size: 1em; | |
margin: auto; | |
display: inline-block; | |
padding: 1em; | |
color: #000; | |
transition: color 0.3s linear; | |
border-color: #000; | |
border-width: 2px; | |
} | |
.button:hover { | |
color: white; | |
border: 1px solid white; | |
background-color: black; | |
} |
15) In your terminal:
npm start
or
yarn start
That’s it! Simple, but powerful —you are now connected to Blockstack.
In part two of this series, I’ll show you How to Connect Blockstack to your Backend API
Bring your friends and come learn JavaScript in a fun never before seen way! waddlegame.com
Top comments (0)