You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

868 lines
46 KiB

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Begin Jekyll SEO tag v2.5.0 -->
<title>Hello, Blockstack Tutorial | Blockstack</title>
<meta name="generator" content="Jekyll v3.8.3" />
<meta property="og:title" content="Hello, Blockstack Tutorial" />
<meta name="author" content="Blockstack" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="Hello, Blockstack Tutorial" />
<meta property="og:description" content="Hello, Blockstack Tutorial" />
<link rel="canonical" href="https://docs.blockstack.org/browser/hello-blockstack.html" />
<meta property="og:url" content="https://docs.blockstack.org/browser/hello-blockstack.html" />
<meta property="og:site_name" content="Blockstack" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2018-09-17T14:01:09-07:00" />
<script type="application/ld+json">
{"description":"Hello, Blockstack Tutorial","author":{"@type":"Person","name":"Blockstack"},"@type":"BlogPosting","url":"https://docs.blockstack.org/browser/hello-blockstack.html","headline":"Hello, Blockstack Tutorial","dateModified":"2018-09-17T14:01:09-07:00","datePublished":"2018-09-17T14:01:09-07:00","mainEntityOfPage":{"@type":"WebPage","@id":"https://docs.blockstack.org/browser/hello-blockstack.html"},"@context":"http://schema.org"}</script>
<!-- End Jekyll SEO tag -->
<!-- <meta property="og:image" content="https://docs.blockstack.org/assets/posts/logo.png"/> -->
<meta property="og:image" content="/assets/posts/logo.png"/>
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="shortcut icon" type="image/png" href="/assets/img/touch-icon.png" >
<link rel="alternate" type="application/rss+xml" title="Blockstack" href="/feed.xml">
<script src="/assets/js/main.js"></script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-125894815-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-125894815-1');
</script>
</head>
<body>
<header class="uk-background-secondary">
<div data-uk-sticky="sel-target: .uk-navbar-container; cls-active: uk-navbar-sticky" class="uk-sticky uk-sticky-fixed" style="position: fixed; top: 0px; width: 1904px;">
<nav class="uk-navbar-container">
<div class="uk-container">
<div data-uk-navbar>
<div class="uk-navbar-left">
<!-- <a class="uk-navbar-item uk-logo" href="/"><img src="https://docs.blockstack.org/assets/posts/logo.png" alt="Docs"></a> -->
<a class="uk-navbar-item uk-logo" href="/"><img src="/assets/posts/logo.png" alt="Docs">
&nbsp;&nbsp;&nbsp;
<svg style="width:141.602;height:11.487px" viewBox="0 0 141.602 11.487" enable-background="new 0 0 141.602 11.487"><path fill="#000000" d="M5.471,7.791c0,0.511-0.16,0.875-0.488,1.111C4.631,9.158,4.097,9.287,3.398,9.287H2.387V6.456h1.011 C5.256,6.456,5.471,7.219,5.471,7.791z M4.554,4.223C4.29,4.448,3.82,4.562,3.16,4.562H2.387V2.2h0.821 c0.611,0,1.066,0.094,1.352,0.279C4.81,2.641,4.933,2.907,4.933,3.292C4.933,3.704,4.809,4.008,4.554,4.223z M6.004,5.338 c0.325-0.181,0.59-0.418,0.79-0.709c0.327-0.476,0.493-1.001,0.493-1.562c0-0.53-0.105-0.989-0.313-1.362 c-0.208-0.374-0.5-0.677-0.867-0.9C5.754,0.59,5.333,0.432,4.855,0.335C4.391,0.24,3.879,0.192,3.334,0.192h-3.06 C0.123,0.192,0,0.317,0,0.471v10.545c0,0.154,0.123,0.278,0.274,0.278h3.315c0.591,0,1.143-0.065,1.645-0.194 c0.513-0.132,0.966-0.339,1.345-0.615c0.388-0.283,0.694-0.641,0.91-1.067C7.702,8.992,7.811,8.488,7.811,7.92 c0-0.78-0.226-1.413-0.672-1.879C6.847,5.737,6.467,5.502,6.004,5.338z M22.197,9.158h-4.595V0.471c0-0.153-0.123-0.278-0.274-0.278 h-1.824c-0.151,0-0.273,0.125-0.273,0.278v10.545c0,0.154,0.122,0.278,0.273,0.278h6.693c0.151,0,0.274-0.124,0.274-0.278v-1.58 C22.47,9.282,22.348,9.158,22.197,9.158z M35.076,5.695c0,0.567-0.051,1.086-0.151,1.543c-0.1,0.45-0.24,0.836-0.416,1.149 c-0.167,0.299-0.37,0.53-0.603,0.688c-0.461,0.312-1.061,0.3-1.505-0.001c-0.233-0.157-0.436-0.389-0.604-0.688 c-0.175-0.313-0.312-0.699-0.407-1.146c-0.096-0.458-0.144-0.978-0.144-1.546c0-1.126,0.187-2.013,0.556-2.638 c0.346-0.587,0.791-0.873,1.36-0.873c0.568,0,1.012,0.285,1.359,0.873C34.889,3.682,35.076,4.569,35.076,5.695z M36.319,1.541 c-0.378-0.494-0.844-0.879-1.381-1.144c-1.076-0.529-2.477-0.529-3.553,0c-0.538,0.265-1.003,0.65-1.381,1.144 c-0.373,0.487-0.669,1.09-0.879,1.792c-0.208,0.696-0.313,1.49-0.313,2.362c0,0.882,0.105,1.685,0.313,2.386 c0.21,0.706,0.504,1.318,0.876,1.821c0.378,0.511,0.844,0.908,1.382,1.179c0.538,0.27,1.136,0.407,1.779,0.407 c0.642,0,1.24-0.137,1.778-0.408c0.538-0.27,1.003-0.667,1.382-1.178c0.372-0.503,0.667-1.115,0.876-1.821 c0.208-0.7,0.314-1.502,0.314-2.386c0-0.873-0.105-1.667-0.314-2.363C36.988,2.631,36.692,2.028,36.319,1.541z M51.29,8.346 c-0.052-0.058-0.125-0.092-0.203-0.092c-0.077,0-0.151,0.033-0.203,0.092c-0.273,0.308-0.566,0.549-0.871,0.715 c-0.602,0.33-1.469,0.308-2.099,0.002c-0.326-0.159-0.608-0.387-0.841-0.681c-0.236-0.299-0.423-0.675-0.554-1.116 c-0.134-0.45-0.203-0.968-0.203-1.539c0-0.56,0.068-1.07,0.203-1.515c0.132-0.437,0.316-0.81,0.548-1.111 c0.227-0.293,0.504-0.522,0.825-0.68c0.614-0.302,1.45-0.317,2.02-0.032c0.283,0.142,0.543,0.333,0.775,0.568 c0.054,0.054,0.147,0.088,0.2,0.081c0.075-0.002,0.146-0.036,0.196-0.092l1.03-1.161c0.098-0.11,0.094-0.278-0.01-0.383 c-0.355-0.361-0.799-0.687-1.317-0.968c-1.105-0.597-2.643-0.547-3.841-0.044c-0.621,0.262-1.165,0.648-1.618,1.149 c-0.451,0.498-0.809,1.113-1.064,1.827c-0.253,0.71-0.381,1.521-0.381,2.408c0,0.899,0.128,1.712,0.381,2.417 c0.255,0.709,0.614,1.317,1.066,1.805c0.454,0.489,0.993,0.865,1.603,1.115c0.607,0.249,1.268,0.374,1.966,0.374 c0.695,0,1.333-0.142,1.897-0.423c0.559-0.279,1.068-0.684,1.513-1.204c0.09-0.106,0.089-0.264-0.004-0.368L51.29,8.346z M64.109,4.608l3.075-3.966c0.065-0.083,0.077-0.198,0.031-0.293c-0.045-0.096-0.141-0.157-0.245-0.157h-2.046 c-0.084,0-0.163,0.039-0.215,0.106l-3.254,4.218V0.47c0-0.153-0.123-0.277-0.274-0.277h-1.855c-0.151,0-0.274,0.124-0.274,0.277 v10.546c0,0.153,0.122,0.278,0.274,0.278h1.855c0.151,0,0.274-0.125,0.274-0.278V8.034l1.185-1.483l2.392,4.594 c0.048,0.091,0.141,0.148,0.242,0.148h2.046c0.097,0,0.186-0.052,0.236-0.138c0.049-0.085,0.05-0.19,0.003-0.276L64.109,4.608z M81.006,6.088c-0.218-0.244-0.478-0.462-0.773-0.647c-0.286-0.179-0.606-0.339-0.94-0.47l-1.368-0.598 c-0.235-0.097-0.461-0.189-0.679-0.276c-0.196-0.079-0.371-0.169-0.516-0.27c-0.134-0.092-0.24-0.197-0.315-0.311 c-0.065-0.099-0.097-0.22-0.097-0.369c0-0.297,0.112-0.514,0.351-0.683c0.263-0.187,0.64-0.281,1.12-0.281 c0.437,0,0.833,0.074,1.179,0.22c0.355,0.151,0.702,0.36,1.03,0.623c0.116,0.094,0.287,0.074,0.381-0.044l0.952-1.193 c0.091-0.114,0.079-0.279-0.026-0.38c-0.456-0.429-0.993-0.775-1.597-1.028c-1.11
</a>
</div>
<div class="uk-navbar-right">
<ul class="uk-navbar-nav uk-visible@m">
<li><a href="https://blockstack.org" target="_blank" >Blockstack.org</a></li>
<li><a href="https://forum.blockstack.org/" target="_blank" >Forums</a></li>
<li><a href="https://github.com/blockstack" target="_blank" >GitHub</a></li>
</ul>
<div>
<a class="uk-navbar-toggle" uk-search-icon href="#"></a>
<div class="uk-drop uk-background-default uk-border-rounded" uk-drop="mode: click; pos: left-center; offset: 0">
<form class="uk-search uk-search-navbar uk-width-1-1" onsubmit="return false;">
<input id="searchBox" class="uk-search-input" type="search" placeholder="Search..." autofocus>
</form>
<ul id="searchBox-results" class="uk-position-absolute uk-width-1-1 uk-list"></ul>
</div>
</div>
<a class="uk-navbar-toggle uk-hidden@m" href="#offcanvas" data-uk-navbar-toggle-icon data-uk-toggle></a>
</div>
</div>
</div>
</nav>
</div>
</header>
<div class="uk-section">
<div class="uk-container">
<div class="uk-grid-large" data-uk-grid>
<div class="sidebar-fixed-width uk-visible@m">
<div class="sidebar-docs uk-position-fixed">
<!-- -->
<h5>Try a tutorial</h5>
<ul class="uk-nav uk-nav-default doc-nav">
<!-- -->
<li class="uk-active"><a href="/browser/hello-blockstack.html">Hello, Blockstack Tutorial</a></li>
<!-- -->
<li class=""><a href="/browser/blockstack_storage.html">Blockstack Storage Tutorial</a></li>
</ul>
<h5>Work with an SDK</h5>
<ul class="uk-nav uk-nav-default doc-nav">
<!-- -->
<li class=""><a href="/android/tutorial.html">Android SDK Tutorial (Pre-release)</a></li>
<!-- -->
<li class=""><a href="/ios/tutorial.html">iOS SDK Tutorial (Pre-release)</a></li>
</ul>
<h5>Reference</h5>
<ul class="uk-nav uk-nav-default doc-nav">
<!-- -->
<li class=""><a href="/core/faq_developer.html">Developer FAQs</a></li>
<!-- -->
<li class=""><a href="/common/javascript_ref.html">Blockstack Javascript Reference</a></li>
</ul>
<!-- -->
</div>
</div>
<div class="uk-width-1-1 uk-width-expand@m">
<article markdown="span" class="uk-article">
<h1 class="uk-article-title">Hello, Blockstack Tutorial</h1>
<div class="uk-article-meta uk-margin-top uk-margin-medium-bottom">
<!-- <img class="avatar avatar-small" alt="Blockstack" width="32" height="32" data-proofer-ignore="true" src="https://avatars2.githubusercontent.com/Blockstack?v=3&s=32" srcset="https://avatars2.githubusercontent.com/Blockstack?v=3&s=32 1x, https://avatars2.githubusercontent.com/Blockstack?v=3&s=64 2x, https://avatars2.githubusercontent.com/Blockstack?v=3&s=96 3x, https://avatars2.githubusercontent.com/Blockstack?v=3&s=128 4x" /> -->
<!-- Written by <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">Blockstack</span></span><br> -->
<time datetime="2018-09-17T14:01:09-07:00" itemprop="datePublished">
<a "target="_blank" href="https://github.com/blockstack/blockstack-browser/blob/master/docs/hello-blockstack.md" class="btn btn-default githubEditButton" role="button">
<span data-uk-icon="icon: pencil; ratio: 1.2"></span> Edit this page on Github</a>
<span style="font-family:Wingdings">&#119;</span> Sep 17, 2018
</time>
</div>
<div markdown="span" class="article-content">
<p>In this tutorial, you generate a simple application on Blockstack. The application
is a single-page application (SPA) that runs completely client-side. The
application has no backend API to talk to, other than the identity and storage
API that the user provides. In this sense, the application is a completely
decentralized, server-less application. You work through the following sections:</p>
<ul id="markdown-toc">
<li><a href="#about-this-tutorial-and-the-prerequisites-you-need" id="markdown-toc-about-this-tutorial-and-the-prerequisites-you-need">About this tutorial and the prerequisites you need</a></li>
<li><a href="#use-npm-to-install-yeoman-and-the-blockstack-app-generator" id="markdown-toc-use-npm-to-install-yeoman-and-the-blockstack-app-generator">Use npm to install Yeoman and the Blockstack App Generator</a></li>
<li><a href="#generate-an-initial-blockstack-application" id="markdown-toc-generate-an-initial-blockstack-application">Generate an initial Blockstack application</a></li>
<li><a href="#review-the-basic-application-structure" id="markdown-toc-review-the-basic-application-structure">Review the basic application structure</a></li>
<li><a href="#start-the-server-and-view-the-application" id="markdown-toc-start-the-server-and-view-the-application">Start the server and view the application</a></li>
<li><a href="#understand-the-generated-application-code" id="markdown-toc-understand-the-generated-application-code">Understand the generated application code</a> <ul>
<li><a href="#application-manifest" id="markdown-toc-application-manifest">Application manifest</a></li>
<li><a href="#save-your-application-code" id="markdown-toc-save-your-application-code">Save your application code</a></li>
</ul>
</li>
</ul>
<h2 id="about-this-tutorial-and-the-prerequisites-you-need">About this tutorial and the prerequisites you need</h2>
<p>For this tutorial, we will use the following tools:</p>
<ul>
<li><code class="highlighter-rouge">npm</code> to manage dependencies and scripts</li>
<li><code class="highlighter-rouge">browserify</code> to compile node code into browser-ready code</li>
<li><code class="highlighter-rouge">blockstack.js</code> to authenticate the user and work with the user’s identity/profile information</li>
</ul>
<p>At minimum, Blockstack requires macOS High Sierra. This tutorial was written for
a user running macOS High Sierra 10.13.4. The application you build is a
React.js application that is completely decentralized and server-less. While
not strictly required to follow along, basic familiarity with React.js is
helpful.</p>
<p>When complete, the app is capable of the following:</p>
<ul>
<li>authenticating users using Blockstack</li>
<li>posting new statuses</li>
<li>displaying statuses in the user profile</li>
<li>looking up the profiles and statuses of other users</li>
</ul>
<p>The basic identity and storage services are provided by <code class="highlighter-rouge">blockstack.js</code>. To test
the application, you need to have already registered a Blockstack ID.</p>
<p>The tutorial relies on the <code class="highlighter-rouge">npm</code> dependency manager. Before you begin, verify
you have installed <code class="highlighter-rouge">npm</code> using the <code class="highlighter-rouge">which</code> command to verify.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>which npm
/usr/local/bin/npm
</code></pre>
</div>
<p>If you don’t find <code class="highlighter-rouge">npm</code> in your system, <a href="https://www.npmjs.com/get-npm">install
it</a>.</p>
<p>Finally, make sure you have <a href="/browser/ids-introduction.html#create-an-initial-blockstack-id">created at least one Blockstack ID</a>. You’ll use this ID to interat with the application.</p>
<h2 id="use-npm-to-install-yeoman-and-the-blockstack-app-generator">Use npm to install Yeoman and the Blockstack App Generator</h2>
<p>You use <code class="highlighter-rouge">npm</code> to install Yeoman. Yeoman is a generic scaffolding system that
helps users rapidly start new projects and streamline the maintenance of
existing projects.</p>
<ol>
<li>
<p>Install Yeoman.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> npm install -g yo
</code></pre>
</div>
</li>
<li>
<p>Install the Blockstack application generator.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> npm install -g generator-blockstack
</code></pre>
</div>
</li>
</ol>
<h2 id="generate-an-initial-blockstack-application">Generate an initial Blockstack application</h2>
<p>In this section, you build an initial React.js application called <code class="highlighter-rouge">hello-world-tutorial</code>.</p>
<ol>
<li>
<p>Create the <code class="highlighter-rouge">hello-world-tutorial</code> directory.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> mkdir hello-world-tutorial
</code></pre>
</div>
</li>
<li>
<p>Change into your new directory.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> <span class="nb">cd </span>hello-world-tutorial
</code></pre>
</div>
</li>
<li>
<p>Use Yeoman and the Blockstack application generator to create your initial <code class="highlighter-rouge">hello-world-tutorial</code> application.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> yo blockstack
</code></pre>
</div>
<p>You should see several interactive prompts.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> <span class="nv">$ </span>yo blockstack
_-----_ ╭──────────────────────────╮
| | │ Welcome to the │
|--<span class="o">(</span>o<span class="o">)</span>--| │ Blockstack app │
<span class="sb">`</span>---------´ │ generator! │
<span class="o">(</span> _´U<span class="sb">`</span>_ <span class="o">)</span> ╰──────────────────────────╯
/___A___<span class="se">\ </span> /
| ~ |
__<span class="s1">'.___.'</span>__
´ <span class="sb">`</span> |° ´ Y <span class="sb">`</span>
? Are you ready to build a Blockstack app <span class="k">in </span>React? <span class="o">(</span>Y/n<span class="o">)</span>
</code></pre>
</div>
</li>
<li>
<p>Respond to the prompts to populate the initial app.</p>
<p>After the process completes successfully, you see a prompt similar to the following:</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> ...
create public/icon-192x192.png
create public/index.html
create public/robots.txt
create public/manifest.json
I<span class="s1">'m all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.
</span></code></pre>
</div>
</li>
</ol>
<p>Depending on your environment you may have some problems with the <code class="highlighter-rouge">npm</code> packages. Go ahead and fix these before continuing to the next section.</p>
<h2 id="review-the-basic-application-structure">Review the basic application structure</h2>
<p>The initial application you create is a generic Javascript application you run
with a local express node. Before you continue, take a moment to examine the
structure of this generic application structure:</p>
<table>
<thead>
<tr>
<th>File</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>.editorconfig</td>
<td>Sets universal values for editor.</td>
</tr>
<tr>
<td>.gitignore</td>
<td>Git configuration file.</td>
</tr>
<tr>
<td>firebase.json</td>
<td>Configuragion for mobile application.</td>
</tr>
<tr>
<td>package.json</td>
<td>Specifies required packages.</td>
</tr>
<tr>
<td>requires.js</td>
<td>A Javascript module loader.</td>
</tr>
<tr>
<td>server.js</td>
<td>Simple static server configuration.</td>
</tr>
</tbody>
</table>
<p>In the <code class="highlighter-rouge">public</code> folder you find these files:</p>
<table>
<thead>
<tr>
<th>File</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>app.css</td>
<td>Contains application styles.</td>
</tr>
<tr>
<td>app.js</td>
<td>Main application file.</td>
</tr>
<tr>
<td>boostrap.min.css</td>
<td>Minifield css for production.</td>
</tr>
<tr>
<td>icon-192x192.png</td>
<td>Application icon</td>
</tr>
<tr>
<td>index.html</td>
<td>Single page.</td>
</tr>
<tr>
<td>manifest.json</td>
<td>Tells the browser about the application and how it should behave.</td>
</tr>
<tr>
<td>robots.txt</td>
<td>Configures crawling and indexing.</td>
</tr>
</tbody>
</table>
<p>The simple static file server in the <code class="highlighter-rouge">server.js</code>file serves all of the files in
the <code class="highlighter-rouge">/public</code> directory, including <code class="highlighter-rouge">index.html</code>, <code class="highlighter-rouge">app.js</code>, <code class="highlighter-rouge">bootstrap.min.css</code>
and <code class="highlighter-rouge">app.css</code>. The main file of the application is in the <code class="highlighter-rouge">app.js</code>. It contains
the majority of the application logic.</p>
<h2 id="start-the-server-and-view-the-application">Start the server and view the application</h2>
<p>When you start the server, it will create a Node.js server, start it locally,
and open your browser ‘http://localhost:5000’. From the root of your new application directory:</p>
<ol>
<li>
<p>Start the application server.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> npm start
</code></pre>
</div>
<p>The first time you run it, your system prompts you to accept incoming connections.</p>
<p><img src="images/network-connections.gif" alt="Network Connection" /></p>
</li>
<li>
<p>Choose <strong>Allow</strong>.</p>
</li>
<li>
<p>Open your browser to <code class="highlighter-rouge">http://localhost:8080</code>.</p>
<p>You should see a simple application:</p>
<p><img src="images/initial-app.gif" alt="" /></p>
</li>
<li>
<p>Choose <strong>Sign In with Blockstack</strong>.</p>
<p>The application detects whether the user has the Blockstack client edition installed or
not. This is done automatically by the Blockstack API, more about this later.
What the browser displays depends on the users’ current state.</p>
<table>
<thead>
<tr>
<th>Using web app</th>
<th>Has client edition installed</th>
</tr>
</thead>
<tbody>
<tr>
<td><img src="images/login-choice.png" alt="" /></td>
<td><img src="images/login.gif" alt="" /></td>
</tr>
</tbody>
</table>
<p>If the user logged into the Blockstack Browser but not reset it, the user can
simply use the exiting identity.</p>
<p><img src="images/login-no-auth.png" alt="" /></p>
<p>If the user chooses <strong>Deny</strong>, the Blockstack Browser displays its
<strong>Home</strong> page but the user is not logged into the sample application.</p>
</li>
<li>
<p>Leave your new application running and move onto the next section.</p>
</li>
</ol>
<h2 id="understand-the-generated-application-code">Understand the generated application code</h2>
<p>In this section, you look at the basic application generated with the <code class="highlighter-rouge">yo
blockstack</code> command. The generated code contains simple authentication methods
that allow a user to log into the browser. The main application code is located
in the <code class="highlighter-rouge">public/app.css</code> file. Open this file now.</p>
<p>All of the code in the file is wrapped in an event
listener.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="nb">document</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s2">"DOMContentLoaded"</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="p">})</span>
</code></pre>
</div>
<p>This listener that waits until the DOM content is loaded. Then, it creates an auth request and redirects the user to sign in:</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'signin-button'</span><span class="p">).</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'click'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">blockstack</span><span class="p">.</span><span class="nx">redirectUserToSignIn</span><span class="p">()</span>
<span class="p">})</span>
</code></pre>
</div>
<p>You can find the <code class="highlighter-rouge">redirectUserToSignIn()</code> function is part of the <a href="https://blockstack.github.io/blockstack.js/">Blockstack Javascript documentation</a>. There is also a sign out button handler. This handler deletes the local user data and signs the user out:</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'signout-button'</span><span class="p">).</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'click'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">blockstack</span><span class="p">.</span><span class="nx">signUserOut</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">origin</span><span class="p">)</span>
<span class="p">})</span>
</code></pre>
</div>
<p>The handlers are followed by a <code class="highlighter-rouge">showProfile()</code> function for showing the user’s profile:</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">showProfile</span><span class="p">(</span><span class="nx">profile</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">person</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">blockstack</span><span class="p">.</span><span class="nx">Person</span><span class="p">(</span><span class="nx">profile</span><span class="p">)</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'heading-name'</span><span class="p">).</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="nx">person</span><span class="p">.</span><span class="nx">name</span><span class="p">()</span> <span class="p">?</span> <span class="nx">person</span><span class="p">.</span><span class="nx">name</span><span class="p">()</span> <span class="p">:</span> <span class="s2">"Nameless Person"</span>
<span class="k">if</span><span class="p">(</span><span class="nx">person</span><span class="p">.</span><span class="nx">avatarUrl</span><span class="p">())</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'avatar-image'</span><span class="p">).</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'src'</span><span class="p">,</span> <span class="nx">person</span><span class="p">.</span><span class="nx">avatarUrl</span><span class="p">())</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'section-1'</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">display</span> <span class="o">=</span> <span class="s1">'none'</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'section-2'</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">display</span> <span class="o">=</span> <span class="s1">'block'</span>
<span class="p">}</span>
</code></pre>
</div>
<p>Each <code class="highlighter-rouge">getElementById()</code> function refers to elemments in the <code class="highlighter-rouge">index.html</code> file.</p>
<p>Once a user is successfully signed in, there is logic for loading the user
profile and displaying the application. As illustrated earlier, there are
several states the user can be in:</p>
<ul>
<li>The user is already signed in</li>
<li>The user has a pending sign in request</li>
<li>The user is signed out</li>
</ul>
<p>The application handles these situtations as followed:</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="nx">blockstack</span><span class="p">.</span><span class="nx">isUserSignedIn</span><span class="p">())</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">profile</span> <span class="o">=</span> <span class="nx">blockstack</span><span class="p">.</span><span class="nx">loadUserData</span><span class="p">().</span><span class="nx">profile</span>
<span class="nx">showProfile</span><span class="p">(</span><span class="nx">profile</span><span class="p">)</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">blockstack</span><span class="p">.</span><span class="nx">isSignInPending</span><span class="p">())</span> <span class="p">{</span>
<span class="nx">blockstack</span><span class="p">.</span><span class="nx">handlePendingSignIn</span><span class="p">().</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">userData</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">location</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">origin</span>
<span class="p">})</span>
<span class="p">}</span>
</code></pre>
</div>
<p>When the user is signed in, Blockstack loads the user data from local storage
and displays the profile with the <code class="highlighter-rouge">showProfile()</code> function. When the user has a
pending sign in request, the appplication signs the user in and redirects the
user back to the home page.</p>
<h3 id="application-manifest">Application manifest</h3>
<p>The application’s <code class="highlighter-rouge">/public/manifest.json</code> file configures your app. The
configurations dictate how the application is displayed in auth views and on
user home screens. The contents are very simple:</p>
<div class="language-json highlighter-rouge"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Hello, Blockstack"</span><span class="p">,</span><span class="w">
</span><span class="nt">"start_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"localhost:5000"</span><span class="p">,</span><span class="w">
</span><span class="nt">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"A simple demo of Blockstack Auth"</span><span class="p">,</span><span class="w">
</span><span class="nt">"icons"</span><span class="p">:</span><span class="w"> </span><span class="p">[{</span><span class="w">
</span><span class="nt">"src"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://helloblockstack.com/icon-192x192.png"</span><span class="p">,</span><span class="w">
</span><span class="nt">"sizes"</span><span class="p">:</span><span class="w"> </span><span class="s2">"192x192"</span><span class="p">,</span><span class="w">
</span><span class="nt">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"image/png"</span><span class="w">
</span><span class="p">}]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre>
</div>
<p>Keep it as is or fill it in with new information that describes your app.</p>
<h3 id="save-your-application-code">Save your application code</h3>
<p>Complete the tutorial by storing your app code on GitHub. Before you begin, make sure you have a GitHub account and have configured your environment to use it.</p>
<ol>
<li>
<p>Initialize the application code as a Git repo.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> git init
</code></pre>
</div>
</li>
<li>
<p>Add and commit all of the files:</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> git add . <span class="o">&amp;&amp;</span> git commit -m <span class="s2">"first commit"</span>
</code></pre>
</div>
</li>
<li>
<p>In GitHub, create a <code class="highlighter-rouge">hello-blockstack</code> repository.</p>
</li>
<li>
<p>Back in your termininal window, add a remote for GitHub.</p>
<p>Make sure to fill in your username:</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> git remote add origin git@github.com:YOUR_USERNAME_HERE/hello-blockstack.git
</code></pre>
</div>
</li>
<li>
<p>Push your new code to the master branch of the remote repo:</p>
<div class="highlighter-rouge"><pre class="highlight"><code> git push origin master
</code></pre>
</div>
</li>
</ol>
<p>You’re done! You just built your first Blockstack app and shipped the code.
You’re well on your way to becoming a Blockstack app legend.</p>
<div class="share uk-text-center">
<a href="https://twitter.com/intent/tweet?text=Hello, Blockstack Tutorial&url=https://docs.blockstack.org/browser/hello-blockstack.html&via=&related=" rel="nofollow" target="_blank" title="Share on Twitter" onclick="window.open(this.href, 'twitter', 'width=550,height=235');return false;"><span data-uk-icon="icon: twitter; ratio: 1.2"></span></a>
<a class="uk-margin-small-left" href="https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fdocs.blockstack.org%2Fbrowser%2Fhello-blockstack.html" rel="nofollow" target="_blank" title="Share on Facebook" onclick="window.open(this.href, 'facebook-share','width=580,height=296');return false;"><span data-uk-icon="icon: facebook; ratio: 1.2"></span></a>
</div>
</div>
<hr class="uk-margin-medium">
<!-- <div class="uk-margin-large-top">
<h3>Related Articles</h3>
<ul class="uk-list">
</ul>
</div>
-->
</article>
<script>
// Table of contents scroll to
UIkit.scroll('#markdown-toc a', {
duration: 400,
offset: 120
});
</script>
</div>
</div>
</div>
<div id="offcanvas" data-uk-offcanvas="flip: true; overlay: true">
<div class="uk-offcanvas-bar">
<button class="uk-offcanvas-close" type="button" data-uk-close></button>
<ul class="uk-nav uk-nav-default">
<!-- <li><a class="uk-logo uk-margin-small-bottom" href="/"><img src="https://docs.blockstack.org/assets/posts/logo.png" alt="Docs"></a></li> -->
<li><a class="uk-logo uk-margin-small-bottom" href="/"><img src="/assets/posts/logo.png" alt="Docs"></a></li>
<li><a href="https://blockstack.org" target="_blank" >Blockstack.org</a></li>
<li><a href="https://forum.blockstack.org/" target="_blank" >Forums</a></li>
<li><a href="https://github.com/blockstack" target="_blank" >GitHub</a></li>
</ul>
<div class="uk-margin-small-top uk-text-center uk-text-muted uk-link-muted">
<div data-uk-grid class="uk-child-width-auto uk-grid-small uk-flex-center uk-grid">
<div class="uk-first-column">
<a href="https://twitter.com/" data-uk-icon="icon: twitter" class="uk-icon-link uk-icon" target="_blank"></a>
</div>
<div>
<a href="https://www.facebook.com/" data-uk-icon="icon: facebook" class="uk-icon-link uk-icon" target="_blank"></a>
</div>
<div>
<a href="https://www.instagram.com/" data-uk-icon="icon: instagram" class="uk-icon-link uk-icon" target="_blank"></a>
</div>
<div>
<a href="https://vimeo.com/" data-uk-icon="icon: vimeo" class="uk-icon-link uk-icon" target="_blank"></a>
</div>
</div>
</div>
</div>
</div>
<footer class="uk-section uk-text-center uk-text-muted uk-link-muted">
<div class="uk-container uk-container-small">
<!-- <div>
<ul class="uk-subnav uk-flex-center">
<li><a href="https://blockstack.org" target="_blank" >Blockstack.org</a></li>
<li><a href="https://forum.blockstack.org/" target="_blank" >Forums</a></li>
<li><a href="https://github.com/blockstack" target="_blank" >GitHub</a></li>
</ul>
</div>
<div class="uk-margin-medium">
<div data-uk-grid class="uk-child-width-auto uk-grid-small uk-flex-center uk-grid">
<div class="uk-first-column">
<a href="https://twitter.com/" data-uk-icon="icon: twitter" class="uk-icon-link uk-icon" target="_blank"></a>
</div>
<div>
<a href="https://www.facebook.com/" data-uk-icon="icon: facebook" class="uk-icon-link uk-icon" target="_blank"></a>
</div>
<div>
<a href="https://www.instagram.com/" data-uk-icon="icon: instagram" class="uk-icon-link uk-icon" target="_blank"></a>
</div>
<div>
<a href="https://vimeo.com/" data-uk-icon="icon: vimeo" class="uk-icon-link uk-icon" target="_blank"></a>
</div>
</div>
</div> -->
<div class="uk-margin-medium uk-text-small copyright"> Blockstack&reg; and Stacks&trade; are trademarks of Blockstack Public Benefit Corp. &copy; 2018 Blockstack Public Benefits Corp.</div>
</div>
</footer>
<script type="text/javascript">
/* Create a configuration object */
var ss360Config = {
/* Your site id */
siteId: 'blockstack',
/* A CSS selector that points to your search box */
searchBox: {
selector: '#searchBox'
},
results: {
embedConfig: undefined, // {'url':undefined,'contentBlock':'.page-content-body'}, // if url is given the page will change to that URL and look for the content block there to insert the results
fullScreenConfig: undefined, // {trigger: '#ss360-search-trigger', caption: 'Search this site'}, trigger is the CSS selector to the element that starts the search full screen overlay and searchCaption the caption on the full screen search page
caption: 'Found #COUNT# search results for \"#QUERY#\"', // the caption of the search results
group: true, // whether results should be grouped if content groups are available
filters: undefined,
num: 96, // the maximum number of search results to be shown
highlightQueryTerms: true, // whether to highlight the query terms in search results
moreResultsButton: "Show more results", // HTML for the more results button, all results will be shown if this is null
noResultsText: 'Sorry, we have not found any matches for your query.', // the text to show when there are no results
queryCorrectionText: 'Did you mean "#CORRECTION#"?',
searchQueryParamName: 'ss360Query', // the name of the search query parameter
linksOpenNewTab: false, // should clicking on the result links open a new tab/window?
showSearchBoxLayover: true, //whether to show search box in search result layover
moreResultsPagingSize: 12, // the number of new results to show each time the more results button is pressed (max: 24)
orderByRelevanceText: "Relevance" // the text to be shown in order select box to describe 'order by relevance' option
},
suggestions: {
show: true, // whether to show search suggestions
maxQuerySuggestions: 3, // the maximum number of query suggestions
querySuggestionHeadline: undefined, // the headline of the query suggestions, leave blank if no headline should be shown
emptyQuerySuggestions: undefined,
showImages: false, // show images in search suggestions
num: 6, // the maximum number of search suggestions to be shown
minChars: 3, // minimum number of characters before the suggestions shows, default: 3,
maxWidth: 'auto', // the maximum width of the suggest box, default: as wide as the input box, at least 275px
throttleTime: 300, // the number of milliseconds before the suggest is triggered after finished input, default: 300ms
extraHtml: undefined, // extra HTML code that is shown in each search suggest, you can even show values of datapoints here,
highlight: true, // whether matched words should be highlighted, default: true
},
smart404: { /* The caption of the search results. */
caption: 'These links might be useful', /* The string in the title that identifies the page as a 404 page. */
identifier: 'Page not found', /* A CSS selector that points to the area in which the alternative links should be shown. */
resultSelector: '#ss360-404',
}
};
</script>
<script src="https://cdn.sitesearch360.com/sitesearch360-v11.min.js" async></script>
</body>
</html>