Learn How to Create a Passion Economy Platform on Blockchain

“The line between hobbies, careers and personal brands is blurring.” — Adam Davidson, author of “The Passion Economy: The New Rules for Thriving in the 21st century”

Niharika Singh
Coinmonks
Published in
10 min readMay 8, 2020

--

The passion economy is all about monetizing individuality. Successful people usually have a unique skill set that is uncommon and hard to find elsewhere. When you combine your passion with skills, you can carve out a perfect niche in the economy.

The nature of work as we see it today is changing rapidly. Post COVID-19 crisis, we don’t know if we can go back to the way we were. Who thought they would be writing their end semester exams from their dorm!? Do we really need brick and mortar to run an office? COVID-19 is making us challenge the status quo.

The beginning of the journey into the passion economy starts with you. (This is usually the hardest step.) The passion economy is all about monetizing your individuality, so step #1 is reflecting within to find what you’re truly passionate about. This idea resonates with many religions where the focus is on finding a greater purpose in life and to work towards it with raw passion.

And passion pays off. According to a16z, the top-earning writer on the paid newsletter platform Substack earns more than $500,000 a year from reader subscriptions. The top content creator on Podia, a platform for video courses and digital memberships, makes more than $100,000 a month. And teachers across the US are bringing in thousands of dollars a month teaching live, virtual classes on Outschool and Juni Learning.

Yet, so many platforms lack transparency for content creators. In this blog post, we will focus on leveraging blockchain to create a passion economy platform for writers.

Here’s a step-by-step guide on how to develop a journal entry prototype on the Ethereum blockchain using Sia as a decentralized storage platform.

We will build a platform where a user can make a journal entry and push it to a decentralized storage platform. The unique hash of the journal entry will be stored on the blockchain. We will also fetch previous journal entries.

Sia is an open source decentralized storage platform that leverages blockchain technology to create a data storage marketplace. It is more robust and affordable when compared to traditional cloud storage providers. You don’t require any signups, servers, or need to trust third parties. Sia keeps your data private. You control your private encryption keys and you own your data. No third party has access to your files, unlike traditional cloud storage providers. Learn more about Sia here.

DappStarter is a full-stack blockchain app generator. We’ll be using DappStarter to spin up a minimalistic blockchain dapp within 5 minutes. DappStarter makes development faster and more efficient so developers can focus on the smart contract’s business logic, saving weeks of learning and development time. Learn more about DappStarter here.

Checklist before starting:

Step 1: Go to dappstarter.trycrypto.com to generate your blockchain dapp

DappStarter supports your choice of blockchain and blockchain language as well as an integrated front end user experience in your choice of client side framework.

Step 1.1: Select your choice of blockchain. For this tutorial, we will use Ethereum.

Step 1.2: Select Solidity as smart contract language

Step 1.3: For now we will work with vanilla JS

Step 1.4: Select a name for your dapp and click on the ‘CREATE DAPP’ button! 🎉

If you have followed all these steps successfully, you should have a unique github repository link where you can find your dapp!

Step 2: Go to the GitHub repository and start your dapp using README

Once you have successfully started your dapp, you should see something like this-

To get an overview of DappStarter, go to trycrypto.com/.

Step 3: Customize your dapp

Let’s see how we can modify the navigation pane. Go to src/dapp/pages/components/page-navigation.js

You can find all the code related to dapp navigation here.

getPages() {let staticPages = [{name: ‘dapp’,title: ‘Start Writing!’,route: ‘/’}, {name: ‘admin’,title: ‘Dapp Admin’,route: ‘/admin’,hidden: true}]return staticPages.concat([{“name”:”administrator_role”,”title”:”Administrator Role”,”description”:”Define accounts that can perform certain admin functions.”,”category”:”Access Control”,”route”:”/administrator_role”},{“name”:”contract_access”,”title”:”Contract Access”,”description”:”Control which external contracts can interact with your contract.”,”category”:”Access Control”,”route”:”/contract_access”},{“name”:”contract_runstate”,”title”:”Contract Run State”,”description”:”Ability to pause operation of your smart contract.”,”category”:”Access Control”,”route”:”/contract_runstate”}]);

On saving the file, the dapp will be reloaded automatically because DappStarter uses webpack. Now, you should see a navigation panel and Start Writing page like this-

Step 4: Create a new widget to make our dapp modular

It’s good practice to create widgets for different functionalities. Create a file named html-widget.js in src/lib/components/widgets.

Insert the following code in this file

import CustomElement from ‘../shared/custom-element’;export default class HtmlWidget extends CustomElement {static get ATTRIBUTE_FIELD() {return ‘field’}static get ATTRIBUTE_LABEL() {return ‘label’}static get ATTRIBUTE_PLACEHOLDER() {return ‘placeholder’}static get observedAttributes() {return HtmlWidget.attributes;}static get attributes() {return [HtmlWidget.ATTRIBUTE_FIELD,HtmlWidget.ATTRIBUTE_LABEL,HtmlWidget.ATTRIBUTE_PLACEHOLDER];}constructor(…args) {super(HtmlWidget.attributes, …args);this.quill = null;}get value() {let markup = this.quill.container.querySelector(‘.ql-editor’).innerHTML;return `<html><head> </head><body><div style=”font-family:lato;”>${markup}</div></body></html>`}render() {let self = this;let content = `<div class=”input-group”><div id = “editor” class = “form-control”> </div></div>`self.style.display = ‘block’;if (self.nextSibling) {self.classList.add(‘mb-3’)}self.innerHTML = content;var toolbarOptions = [[‘bold’, ‘italic’, ‘underline’, ‘strike’], // toggled buttons[‘blockquote’, ‘code-block’],[{ ‘header’: 1 }, { ‘header’: 2 }], // custom button values[{ ‘list’: ‘ordered’}, { ‘list’: ‘bullet’ }],[{ ‘script’: ‘sub’}, { ‘script’: ‘super’ }], // superscript/subscript// [{ ‘indent’: ‘-1’}, { ‘indent’: ‘+1’ }], // outdent/indent// [{ ‘direction’: ‘rtl’ }], // text direction// [{ ‘size’: [‘small’, false, ‘large’, ‘huge’] }], // custom dropdown[{ ‘header’: [1, 2, 3, 4, 5, 6, false] }],[{ ‘color’: [] }, { ‘background’: [] }], // dropdown with defaults from theme// [{ ‘font’: [] }],// [{ ‘align’: [] }],[‘clean’] // remove formatting button];self.quill = new Quill(‘#editor’, {modules: {toolbar: toolbarOptions},theme: ‘snow’});}}customElements.define(‘html-widget’, HtmlWidget);

In this file, we have integrated Quill to make rich text journal entries. Quill is a free, open source WYSIWYG editor built for the modern web.

To use Quill’s functionalities, make sure you add Quill CDNs in dapp/index.html. In the head, add <link href=”https://cdn.quilljs.com/1.3.6/quill.snow.css" rel=”stylesheet”> and just before closing body, add <script src=”https://cdn.quilljs.com/1.3.6/quill.js"></script>

To increase length of the text editor, make the following changes to src/dapp/index.css-

#editor {height: 375px;}strong { font-weight: bold !important; }

Step 5: Make use of html-widget in our dapp

Go to src/dapp/pages/dapp-page.js (this is where all our dapp front-end logic will reside) and make the following changes. Import the created html-widget there. We will be able to use this widget like a regular html tag to use Quill editor anywhere in our dapp.

import DappLib from ‘../../lib/dapp-lib’;import CustomElement from ‘../../lib/components/shared/custom-element’;import DOM from ‘../../lib/components/shared/dom’;import ‘../../lib/components/shared/action-card.js’;import ‘../../lib/components/widgets/number-widget.js’;import ‘../../lib/components/widgets/html-widget.js’;import ActionButton from ‘../../lib/components/shared/action-button’;import canvas from ‘../assets/img/canvas.jpg’;export default class SiaPage extends CustomElement {constructor(…args) {super([], …args);this.mode = ‘multiple’;this.files = [];this.eventHandlerRegistered = false;}render() {let self = this;self.category = “Maintain your journal on decentralized web”;self.description = “Store your journal on decentralized file storage”;let uiHtml = {[CustomElement.UI_READ]: ‘’,[CustomElement.UI_WRITE]: ‘’,[CustomElement.UI_ADMIN]: ‘’}uiHtml[CustomElement.UI_READ] =`<action-cardtitle=”Get Document” description=”Get Sia document using its ID”action=”getSiaDocument” method=”${CustomElement.METHOD_GET}” fields=”id”><number-widgetfield=”id” label=”Doc ID” placeholder=”Document ID”></number-widget></action-card><action-cardtitle=”Get Documents by Owner” description=”Get all Sia documents for any account”action=”getSiaDocumentsByOwner” method=”${CustomElement.METHOD_GET}” fields=”account”><account-widgetfield=”account” label=”Account” placeholder=”Account address”></account-widget></action-card>`uiHtml[CustomElement.UI_WRITE] =`<action-cardtitle=”Make a journal entry” description=”Upload entry to Sia and add hash to contract”action=”addSiaDocument” method=”${CustomElement.METHOD_POST}” fields=”myText”target=”card-body-addSiaDocument”message=”Waiting for Sia upload and smart contract transaction”><h2> Start Writing! </h2><html-widgetdata-field= “myText” field=”label” label=”Label”placeholder=”Description”></html-widget><input type=”hidden” data-field=”mode” value=”${self.mode}” style=”display:none;”></input></action-card>`let content =`<page-body title=”${self.title}” category=”${self.category}” description=”${self.description}”>${uiHtml[CustomElement.UI_READ]}${uiHtml[CustomElement.UI_WRITE]}${uiHtml[CustomElement.UI_ADMIN]}</page-body><page-panel id=”resultPanel”></page-panel>`self.innerHTML = content;// self.querySelector(‘upload-widget’).addEventListener(UploadWidget.EVENT_FILES_CHANGED, (e) => {// //Could do something here// //let files = e.detail.files;// });if (!self.eventHandlerRegistered) {self.eventHandlerRegistered = true;DappLib.onAddSiaDocument((result) => {let resultPanel = self.querySelector(‘#resultPanel’);resultPanel.append(DappLib.getFormattedResultNode(result));resultPanel.open();});}}async fetchAndDisplayCounter() {let result = await DappLib[‘getStateCounter’].call();DOM.elid(‘counter’).innerHTML = result.callData;}}customElements.define(‘dapp-page’, DappPage);

Your dapp should look like this now-

Step 6: Remove extra blocks and change logo

Let’s take the customization of the dapp to the next level. Let’s make it look like this-

Let’s change the logo first. You can use any image. Save it in src/dapp/assets/img. Let’s name it YOUR_FILE_NAME.png. Now go to src/dapp/pages/components/page-navigation.js. You see this line in the code-

import logo from “../../../dapp/assets/img/dappstarter.png”;

Change it to

import logo from “../../../dapp/assets/img/YOUR_FILE_NAME.png”;

We also need to make a change to webpack.config.dapp.js (this is in the root of the project)-

plugins: [new HtmlWebpackPlugin({template: path.join(__dirname, ‘src/dapp/index.html’)}),new FaviconsWebpackPlugin(‘src/dapp/assets/img/YOUR_FILE_NAME.png’)],

This is what your dapp should look like now-

Now let’s remove the Feature blocks from the left navigation panel. Go to src/dapp/pages/components/page-navigation.js.

// Remove the block between //BEGIN //END below to remove feature blocks from navigation// BEGIN: Feature Blocks// DOM.h4({// className: ‘mt-5 mb-2’// },// “Feature Blocks”),// DOM.ul({// id: self.listId + ‘-blocks’,// className: ‘list-group list-group-flush’// },// listItems.slice(1)// ),// END: Feature Blocks

Your dapp should look like this now-

We are almost there!! Finally, let’s get rid of the top navigation bar. Go to src/dapp/pages/components/top-navigation.js and remove all the html that is being rendered.

src/dapp/pages/components/top-navigation.js should look like this-

import CustomElement from ‘../../../lib/components/shared/custom-element’;export default class TopNavigation extends CustomElement {static get ATTRIBUTE_COLLAPSE() {return ‘collapse’}static get observedAttributes() {return TopNavigation.attributes;}static get attributes() {return [TopNavigation.ATTRIBUTE_COLLAPSE];}constructor(…args) {super(TopNavigation.attributes, …args);}}customElements.define(‘top-navigation’, TopNavigation);

This is what your dapp should look like now-

Step 7: Handle journal entry with Sia

All the code related to Sia document upload rests in src/lib/dapp-lib.js. Go to FILE STORAGE: SIA section. The only code block that needs editing here is addSiaDocument().

static async addSiaDocument(data) {let folder = data.mode === ‘folder’;let config = DappLib.getConfig();//Name of the journal entry is the date and time when it was writtenconst timeStamp = new Date().toString();// Convert data received from html-widget into a filedata.files = [new File([data.myText], `${timeStamp}.html`, {type: “text/html”,})];// Push files to SIAlet siaResult = await DappLib.siaUpload(config, data.files, folder);let results = [];for(let f=0; f<siaResult.length; f++) {let file = siaResult[f];let result = await Blockchain.post({config: config,contract: DappLib.DAPP_STATE_CONTRACT,params: {from: null,gas: 2000000}},‘addSiaDocument’,file.docId,DappLib.fromAscii(data.label || ‘’, 32));results.push({transactionHash: DappLib.getTransactionHash(result.callData),docId: file.docId});}

Step 8: Final touch ups

Our dapp is almost ready. We just need to make a few tweeks in src/dapp/index.css. Add the following lines to the file-

.markup {font-family:courier;}

These were all the changes we had to make! Now let’s see our dapp in action.

Congratulations, if you made it till here! 🎉

You can modify your dapp to develop more sophisticated platforms for writers. What we built was merely an example of one of the many use cases you as a developer could build upon.

The future of the passion economy is predicated on the concept of transparency and fairness for content creators. Blockchain provides a unique infrastructure that encourages creators to make awesome content by ensuring that they’ll be fairly compensated for their efforts. Building a dapp for the passion economy is about more than just monetizing content — it’s about providing a transparent, open system where creators feel empowered to create and share what makes them unique.

Start building your dapp with DappStarter.

Get Best Software Deals Directly In Your Inbox

--

--