<!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 > Todo List Application Tutorial | Blockstack< / title >
< meta name = "generator" content = "Jekyll v3.6.3" / >
< meta property = "og:title" content = "Todo List Application Tutorial" / >
< meta name = "author" content = "Blockstack" / >
< meta property = "og:locale" content = "en_US" / >
< meta name = "description" content = "Todo List Application Tutorial" / >
< meta property = "og:description" content = "Todo List Application Tutorial" / >
< link rel = "canonical" href = "https://docs.blockstack.org/browser/todo-list.html" / >
< meta property = "og:url" content = "https://docs.blockstack.org/browser/todo-list.html" / >
< meta property = "og:site_name" content = "Blockstack" / >
< meta property = "og:type" content = "article" / >
< meta property = "article:published_time" content = "2018-10-26T14:02:20-07:00" / >
< script type = "application/ld+json" >
{"url":"https://docs.blockstack.org/browser/todo-list.html","headline":"Todo List Application Tutorial","dateModified":"2018-10-26T14:02:20-07:00","datePublished":"2018-10-26T14:02:20-07:00","mainEntityOfPage":{"@type":"WebPage","@id":"https://docs.blockstack.org/browser/todo-list.html"},"author":{"@type":"Person","name":"Blockstack"},"description":"Todo List Application Tutorial","@type":"BlogPosting","@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" >
< 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 > Introduction< / h5 >
< ul class = "uk-nav uk-nav-default doc-nav" >
< / ul >
< ul class = "uk-nav uk-nav-default doc-nav" >
<!-- -->
< li class = "" > < a href = "/develop/dapp_principles.html" > Principles of Blockstack applications< / a > < / li >
< / ul >
< h5 > Try a tutorial< / h5 >
< ul class = "uk-nav uk-nav-default doc-nav" >
<!-- -->
< li class = "" > < a href = "/browser/hello-blockstack.html" > Hello, Blockstack Tutorial< / a > < / li >
<!-- -->
< li class = "uk-active" > < a href = "/browser/todo-list.html" > Todo List Application 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 > Application mining< / h5 >
< ul class = "uk-nav uk-nav-default doc-nav" >
<!-- -->
< li class = "" > < a href = "/develop/mining_intro.html" > Understand app mining< / a > < / li >
<!-- -->
< li class = "" > < a href = "/develop/mining_enroll.html" > How to enroll< / 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/mining_faq.html" > Mining FAQ< / a > < / li >
<!-- -->
< li class = "" > < a href = "/common/javascript_ref.html" > Blockstack Javascript Reference< / a > < / li >
<!-- -->
< li class = "" > < a href = "/common/core_ref.html" > Blockstack CORE API< / 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" > Todo List Application 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-10-26T14:02:20-07:00" itemprop = "datePublished" >
< a " target = "_blank" href = "https://github.com/blockstack/blockstack-browser/blob/master/docs/todo-list.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" > w < / span > Oct 26, 2018
< / time >
< / div >
< div markdown = "span" class = "article-content" >
< p > In this tutorial, you build the code for and run a single-page application (SPA)
with Blockstack and Vue.js. Once the application is running, you take a tour
through the applications’ Blockstack functionality. You’ll learn how it manages
authentiation using a Blockstack ID and how it stores information associated
with that ID using Blockstack Storage (Gaia).< / 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 = "#install-the-application-code-and-retrieve-the-dependencies" id = "markdown-toc-install-the-application-code-and-retrieve-the-dependencies" > Install the application code and retrieve the dependencies< / a > < / li >
< li > < a href = "#sign-into-the-application" id = "markdown-toc-sign-into-the-application" > Sign into the application< / a > < / li >
< li > < a href = "#understand-the-sign-in-process" id = "markdown-toc-understand-the-sign-in-process" > Understand the sign in process< / a > < / li >
< li > < a href = "#undder-the-covers-in-the-sign-in-code" id = "markdown-toc-undder-the-covers-in-the-sign-in-code" > Undder the covers in the sign in code< / a > < / li >
< li > < a href = "#working-with-the-application" id = "markdown-toc-working-with-the-application" > Working with the application< / a > < / li >
< li > < a href = "#implementing-storage" id = "markdown-toc-implementing-storage" > Implementing storage< / a > < / li >
< li > < a href = "#summary" id = "markdown-toc-summary" > Summary< / a > < / li >
< / ul >
< p > If you prefer a video, you can view < a href = "https://www.youtube.com/embed/oyvg-h0obFw" target = "\_blank" > a video of the tutorial< / a > .< / p >
< 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 blockstack.js. 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" > < div class = "highlight" > < pre class = "highlight" > < code > < span class = "nv" > $ < / span > which npm
/usr/local/bin/npm
< / code > < / pre > < / div > < / 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 = "{site.baseurl}}/browser/ids-introduction.html#create-an-initial-blockstack-id" > created at least one Blockstack ID< / a > .
You’ll use this ID to interact with the application.< / p >
< h2 id = "install-the-application-code-and-retrieve-the-dependencies" > Install the application code and retrieve the dependencies< / h2 >
< p > You can clone the source code with < code class = "highlighter-rouge" > git< / code > or < a href = "https://github.com/blockstack/blockstack-todos/archive/master.zip" > download and unzip the code from
the
repository< / a > .
These instructions assume you are cloning.< / p >
< ol >
< li >
< p > Install the code by cloning it.< / p >
< div class = "highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > $ git clone git@github.com:blockstack/blockstack-todos.git
< / code > < / pre > < / div > < / div >
< / li >
< li >
< p > Change to directory to the root of the code.< / p >
< div class = "highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > $ cd blockstack-todos
< / code > < / pre > < / div > < / div >
< / li >
< li >
< p > Use < code class = "highlighter-rouge" > yarn< / code > to install the dependencies.< / p >
< div class = "highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > $ yarn install
yarn install v1.9.2
info No lockfile found.
...
[4/5] 🔗 Linking dependencies...
[5/5] 📃 Building fresh packages...
success Saved lockfile.
✨ Done in 19.90s.
< / code > < / pre > < / div > < / div >
< / li >
< / ol >
< p > The Todo application has a basic Vue.js structure. There are several configuration files but the central programming files are in the < code class = "highlighter-rouge" > src< / code > directory:< / p >
< table >
< thead >
< tr >
< th > File< / th >
< th > Description< / th >
< / tr >
< / thead >
< tbody >
< tr >
< td > < code class = "highlighter-rouge" > main.js< / code > < / td >
< td > Application initialization.< / td >
< / tr >
< tr >
< td > < code class = "highlighter-rouge" > App.vue < / code > < / td >
< td > Code for handling the < code class = "highlighter-rouge" > authResponse< / code > .< / td >
< / tr >
< tr >
< td > < code class = "highlighter-rouge" > Landing.vue < / code > < / td >
< td > Code for the initial sign on page.< / td >
< / tr >
< tr >
< td > < code class = "highlighter-rouge" > Dashboard.vue< / code > < / td >
< td > Application data storage and user sign out.< / td >
< / tr >
< / tbody >
< / table >
< h2 id = "sign-into-the-application" > Sign into the application< / h2 >
< p > The example application runs in a node server on your local host. In the this section, you start the application and interact with it.< / p >
< ol >
< li >
< p > Make sure you are in the root of the code base.< / p >
< div class = "language-bash highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > < span class = "nv" > $ < / span > < span class = "nb" > pwd< / span > /Users/moxiegirl/repos/blockstack-todos
Start the application.
< / code > < / pre > < / div > < / div >
< / li >
< li >
< p > Start the application.< / p >
< div class = "highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > $ npm run start
< / code > < / pre > < / div > < / div >
< p > You should see a simple application:< / p >
< p > < img src = "images/todo-sign-in.png" alt = "" / > < / p >
< / li >
< li >
< p > Choose < strong > Sign In with Blockstack< / strong > .< / p >
< p > If you have already signed into Blockstack the application prompts you to select the ID to use. If you aren’t signed in, Blockstack prompts you to:< / p >
< p > < img src = "images/login-choice.png" alt = "" / > < / p >
< p > If the login to the application is successful, the user is presented with the application:< / p >
< p > < img src = "images/todo-app.png" alt = "" / > < / p >
< / li >
< / ol >
< h2 id = "understand-the-sign-in-process" > Understand the sign in process< / h2 >
< p > Clicking the Sign In With Blockstack button brings up a modal that prompts you
to sign in with an existing ID or create a new ID. When Blockstack is provided
an ID, it generates an ephemeral key within the application. An ephemeral key is
generated for each execution of a key establishment process. This key is just
used for the particular instance of the application, in this case to sign a Sign
In request.< / p >
< p > A Blockstack Core node also generates a public key token which is sent to the
browser as an < code class = "highlighter-rouge" > authRequest< / code > from the browser to your core node. The signed
authentication request is sent to Blockstack through a JSON Web Token (JWT).
Blocktack passes the token in via a URL query string in the authRequest
parameter:< / p >
< p > < code class = "highlighter-rouge" > https://browser.blockstack.org/auth?authRequest=j902120cn829n1jnvoa...< / code > < / p >
< p > To decode the token and see what information it holds:< / p >
< ol >
< li > Copy the < code class = "highlighter-rouge" > authRequest< / code > string from the URL.< / li >
< li > Navigate to < a href = "https://jwt.io/" > jwt.io< / a > .< / li >
< li >
< p > Paste the full token there.< / p >
< p > The output should look similar to below:< / p >
< div class = "language-json highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > < span class = "w" > < / span > < span class = "p" > {< / span > < span class = "w" >
< / span > < span class = "s2" > "jti"< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "s2" > "3i96e3ad-0626-4e32-a316-b243154212e2"< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "iat"< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "mi" > 1533136622< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "exp"< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "mi" > 1533140228< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "iss"< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "s2" > "did:btc-addr:1Nh8oQTunbEQWjrL666HBx2qMc81puLmMt"< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "public_keys"< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "p" > [< / span > < span class = "w" >
< / span > < span class = "s2" > "0362173da080c6e1dec0653fa9a3eff5f5660546e387ce6c24u04a90c2fe1fdu73"< / span > < span class = "w" >
< / span > < span class = "p" > ],< / span > < span class = "w" >
< / span > < span class = "s2" > "domain_name"< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "s2" > "http://localhost:8080"< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "manifest_uri"< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "s2" > "http://localhost:8080/manifest.json"< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "redirect_uri"< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "s2" > "http://localhost:8080/"< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "version"< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "s2" > "1.2.0"< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "do_not_include_profile"< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "kc" > true< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "supports_hub_url"< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "kc" > true< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "scopes"< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "p" > [< / span > < span class = "w" >
< / span > < span class = "s2" > "store_write"< / span > < span class = "w" >
< / span > < span class = "p" > ]< / span > < span class = "w" >
< / span > < span class = "p" > }< / span > < span class = "w" >
< / span > < / code > < / pre > < / div > < / div >
< blockquote >
< p > < strong > Note< / strong > :< / p >
< ul >
< li > The < code class = "highlighter-rouge" > iss< / code > property is a decentralized identifier or < code class = "highlighter-rouge" > did< / code > . This identifies you and your name to the application. The specific < code class = "highlighter-rouge" > did< / code > is a < code class = "highlighter-rouge" > btc-addr< / code > .< / li >
< li > The Blockstack JWT implementation is different from other implementations because of the underlying cryptography we employ. There are libraries in < a href = "https://github.com/blockstack/jsontokens-js" > Javascript< / a > and < a href = "https://github.com/blockstack/ruby-jwt-blockstack" > Ruby< / a > available on the Blockstack Github to allow you to work with these tokens.< / li >
< / ul >
< / blockquote >
< / li >
< / ol >
< p > When the Blockstack node receives the < code class = "highlighter-rouge" > authRequest< / code > , it generates a session token
and returns an authentication response to the application. This response is
similar to the < code class = "highlighter-rouge" > authRequest< / code > above in that the < code class = "highlighter-rouge" > authResponse< / code > includes a private key
intended only for the application. This allows the application to encrypt data
on your personal Blockstack storage.< / p >
< p > After the completion of this process, the user is logged in.< / p >
< h2 id = "undder-the-covers-in-the-sign-in-code" > Undder the covers in the sign in code< / h2 >
< p > Now, go to the underlying < code class = "highlighter-rouge" > blockstack-todo< / code > code you cloned or downloaded. Sign
in and sign out is handled in each of these files:< / p >
< table >
< thead >
< tr >
< th > File< / th >
< th > Description< / th >
< / tr >
< / thead >
< tbody >
< tr >
< td > < code class = "highlighter-rouge" > App.vue < / code > < / td >
< td > Handles the < code class = "highlighter-rouge" > authResponse< / code > .< / td >
< / tr >
< tr >
< td > < code class = "highlighter-rouge" > Landing.vue < / code > < / td >
< td > Generates the < code class = "highlighter-rouge" > authRequest< / code > .< / td >
< / tr >
< tr >
< td > < code class = "highlighter-rouge" > Dashboard.vue< / code > < / td >
< td > Handles sign out.< / td >
< / tr >
< / tbody >
< / table >
< p > The < code class = "highlighter-rouge" > src/components/Landing.vue< / code > code calls a < a href = "https://blockstack.github.io/blockstack.js#redirectToSignIn" > < code class = "highlighter-rouge" > redirectToSignIn()< / code > < / a > function which generates the < code class = "highlighter-rouge" > authRequest< / code > and redirects the user to the Blockstack authenticator:< / p >
< div class = "language-js highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > < span class = "nx" > signIn< / span > < span class = "p" > ()< / span > < span class = "p" > {< / span >
< span class = "kd" > const< / span > < span class = "nx" > blockstack< / span > < span class = "o" > =< / span > < span class = "k" > this< / span > < span class = "p" > .< / span > < span class = "nx" > blockstack< / span >
< span class = "nx" > blockstack< / span > < span class = "p" > .< / span > < span class = "nx" > redirectToSignIn< / span > < span class = "p" > ()< / span >
< span class = "p" > }< / span >
< / code > < / pre > < / div > < / div >
< p > Once the user authenticates, the application handles the < code class = "highlighter-rouge" > authResponse< / code > in the < code class = "highlighter-rouge" > src/App.vue< / code > file. :< / p >
< div class = "language-js highlighter-rouge" > < div class = "highlight" > < 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 = "k" > this< / span > < span class = "p" > .< / span > < span class = "nx" > user< / 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 = "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 = "p" > .< / span > < span class = "nx" > then< / span > < span class = "p" > ((< / span > < span class = "nx" > userData< / span > < span class = "p" > )< / span > < span class = "o" > => < / 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 > < / div >
< p > If < a href = "https://blockstack.github.io/blockstack.js/#isusersignedin" > < code class = "highlighter-rouge" > blockstack.isUserSignedIn()< / code > < / a > is true, the user was previously signed in so Blockstack pulls the data from the browser and uses it in our application. If the check on < a href = "https://blockstack.github.io/blockstack.js/#issigninpending" > < code class = "highlighter-rouge" > blockstack.isSignInPending()< / code > < / a > is true, a previous < code class = "highlighter-rouge" > authResponse< / code > was sent to the application but hasn’t been processed yet. The < code class = "highlighter-rouge" > handlePendingSignIn()< / code > function processes any pending sign in.< / p >
< p > Signout is handled in < code class = "highlighter-rouge" > src/components/Dashboard.vue< / code > .< / p >
< div class = "language-js highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > < span class = "nx" > signOut< / span > < span class = "p" > ()< / span > < span class = "p" > {< / span >
< span class = "k" > this< / 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" > href< / span > < span class = "p" > )< / span >
< span class = "p" > }< / span >
< / code > < / pre > < / div > < / div >
< p > The method allows the application creator to decide where to redirect the user upon Sign Out:< / p >
< h2 id = "working-with-the-application" > Working with the application< / h2 >
< p > Now, trying adding a few itmes to the todo list. For example, try making a list of applications you want to see built on top of Blockstack:< / p >
< p > < img src = "images/make-a-list.png" alt = "" / > < / p >
< p > Each list is immediately stored in the Gaia Hub linked to your Blockstack ID.
For more information about the Gaia hub, see the < a href = "https://github.com/blockstack/gaia" > hub
repository< / a > . You can fetch the < code class = "highlighter-rouge" > todos.json< / code >
file you just added by opening the Javascript console and running the following
command:< / p >
< pre > < code class = "language-Javascript" > blockstack.getFile("todos.json", { decrypt: true }).then((file) => {console.log(file)})
< / code > < / pre >
< p > You should see a JSON with the todos you just added:< / p >
< div class = "language-json highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > < span class = "p" > [< / span > < span class = "w" >
< / span > < span class = "p" > {< / span > < span class = "w" >
< / span > < span class = "s2" > "id"< / span > < span class = "p" > :< / span > < span class = "mi" > 2< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "text"< / span > < span class = "p" > :< / span > < span class = "s2" > "Software package manager secured by the blockchain"< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "completed"< / span > < span class = "p" > :< / span > < span class = "kc" > false< / span > < span class = "w" >
< / span > < span class = "p" > },< / span > < span class = "w" >
< / span > < span class = "p" > {< / span > < span class = "w" >
< / span > < span class = "s2" > "id"< / span > < span class = "p" > :< / span > < span class = "mi" > 1< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "text"< / span > < span class = "p" > :< / span > < span class = "s2" > "Mutable torrents with human readable names"< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "completed"< / span > < span class = "p" > :< / span > < span class = "kc" > false< / span > < span class = "w" >
< / span > < span class = "p" > },< / span > < span class = "w" >
< / span > < span class = "p" > {< / span > < span class = "w" >
< / span > < span class = "s2" > "id"< / span > < span class = "p" > :< / span > < span class = "mi" > 0< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "text"< / span > < span class = "p" > :< / span > < span class = "s2" > "Decentralized twitter"< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "completed"< / span > < span class = "p" > :< / span > < span class = "kc" > false< / span > < span class = "w" >
< / span > < span class = "p" > }< / span > < span class = "w" >
< / span > < span class = "p" > ]< / span > < span class = "w" >
< / span > < / code > < / pre > < / div > < / div >
< p > Add another todo and check it off. When you fetch the newly generated file
using the Javascript console, the results reflect your change. Look for < code class = "highlighter-rouge" > "completed":true< / code > :< / p >
< div class = "language-json highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > < span class = "p" > [< / span > < span class = "w" >
< / span > < span class = "p" > {< / span > < span class = "w" >
< / span > < span class = "s2" > "id"< / span > < span class = "p" > :< / span > < span class = "mi" > 3< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "text"< / span > < span class = "p" > :< / span > < span class = "s2" > "Blockstack Todo"< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "completed"< / span > < span class = "p" > :< / span > < span class = "kc" > true< / span > < span class = "w" >
< / span > < span class = "p" > },< / span > < span class = "w" >
< / span > < span class = "p" > {< / span > < span class = "w" >
< / span > < span class = "s2" > "id"< / span > < span class = "p" > :< / span > < span class = "mi" > 2< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "text"< / span > < span class = "p" > :< / span > < span class = "s2" > "Software package manager secured by the blockchain"< / span > < span class = "p" > ,< / span > < span class = "w" >
< / span > < span class = "s2" > "completed"< / span > < span class = "p" > :< / span > < span class = "kc" > false< / span > < span class = "w" >
< / span > < span class = "p" > },< / span > < span class = "w" >
< / span > < span class = "err" > ...< / span > < span class = "w" >
< / span > < span class = "p" > ]< / span > < span class = "w" >
< / span > < / code > < / pre > < / div > < / div >
< p > Now that you have seen the application in action, dig into how it works.< / p >
< h2 id = "implementing-storage" > Implementing storage< / h2 >
< p > Go to the underlying < code class = "highlighter-rouge" > blockstack-todo< / code > code you cloned or downloaded. The
application interactions with your Gaia Hub originate in the
< code class = "highlighter-rouge" > src/components/Dashboard.vue< / code > file. First, examine where the changes to the
Todos are processed:< / p >
< div class = "language-js highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > < span class = "nx" > todos< / span > < span class = "p" > :< / span > < span class = "p" > {< / span >
< span class = "nl" > handler< / span > < span class = "p" > :< / span > < span class = "kd" > function< / span > < span class = "p" > (< / span > < span class = "nx" > todos< / span > < span class = "p" > )< / span > < span class = "p" > {< / span >
< span class = "kd" > const< / span > < span class = "nx" > blockstack< / span > < span class = "o" > =< / span > < span class = "k" > this< / span > < span class = "p" > .< / span > < span class = "nx" > blockstack< / span >
< span class = "c1" > // encryption is now enabled by default< / span >
< span class = "k" > return< / span > < span class = "nx" > blockstack< / span > < span class = "p" > .< / span > < span class = "nx" > putFile< / span > < span class = "p" > (< / span > < span class = "nx" > STORAGE_FILE< / span > < span class = "p" > ,< / span > < span class = "nx" > JSON< / span > < span class = "p" > .< / span > < span class = "nx" > stringify< / span > < span class = "p" > (< / span > < span class = "nx" > todos< / span > < span class = "p" > ))< / span >
< span class = "p" > },< / span >
< span class = "nx" > deep< / span > < span class = "p" > :< / span > < span class = "kc" > true< / span >
< span class = "p" > }< / span >
< / code > < / pre > < / div > < / div >
< p > The < code class = "highlighter-rouge" > todos< / code > JSON object is passed in and the
< a href = "https://blockstack.github.io/blockstack.js/#putfile" > < code class = "highlighter-rouge" > blockstack.putFile()< / code > < / a >
method to store it in a Gaia Hub.< / p >
< p > The code needs to read the Todo items from the storage with the < a href = "https://blockstack.github.io/blockstack.js/#getfile" > < code class = "highlighter-rouge" > blockstack.getFile()< / code > < / a > method which returns a promise:< / p >
< div class = "language-js highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > < span class = "nx" > fetchData< / span > < span class = "p" > ()< / span > < span class = "p" > {< / span >
< span class = "kd" > const< / span > < span class = "nx" > blockstack< / span > < span class = "o" > =< / span > < span class = "k" > this< / span > < span class = "p" > .< / span > < span class = "nx" > blockstack< / span >
< span class = "nx" > blockstack< / span > < span class = "p" > .< / span > < span class = "nx" > getFile< / span > < span class = "p" > (< / span > < span class = "nx" > STORAGE_FILE< / span > < span class = "p" > )< / span > < span class = "c1" > // decryption is enabled by default< / span >
< span class = "p" > .< / span > < span class = "nx" > then< / span > < span class = "p" > ((< / span > < span class = "nx" > todosText< / span > < span class = "p" > )< / span > < span class = "o" > => < / span > < span class = "p" > {< / span >
< span class = "kd" > var< / span > < span class = "nx" > todos< / span > < span class = "o" > =< / span > < span class = "nx" > JSON< / span > < span class = "p" > .< / span > < span class = "nx" > parse< / span > < span class = "p" > (< / span > < span class = "nx" > todosText< / span > < span class = "o" > ||< / span > < span class = "s1" > '[]'< / span > < span class = "p" > )< / span >
< span class = "nx" > todos< / span > < span class = "p" > .< / span > < span class = "nx" > forEach< / span > < span class = "p" > (< / span > < span class = "kd" > function< / span > < span class = "p" > (< / span > < span class = "nx" > todo< / span > < span class = "p" > ,< / span > < span class = "nx" > index< / span > < span class = "p" > )< / span > < span class = "p" > {< / span >
< span class = "nx" > todo< / span > < span class = "p" > .< / span > < span class = "nx" > id< / span > < span class = "o" > =< / span > < span class = "nx" > index< / span >
< span class = "p" > })< / span >
< span class = "k" > this< / span > < span class = "p" > .< / span > < span class = "nx" > uidCount< / span > < span class = "o" > =< / span > < span class = "nx" > todos< / span > < span class = "p" > .< / span > < span class = "nx" > length< / span >
< span class = "k" > this< / span > < span class = "p" > .< / span > < span class = "nx" > todos< / span > < span class = "o" > =< / span > < span class = "nx" > todos< / span >
< span class = "p" > })< / span >
< span class = "p" > },< / span >
< / code > < / pre > < / div > < / div >
< p > The < code class = "highlighter-rouge" > todos< / code > data is retrieved from the promise.< / p >
< h2 id = "summary" > Summary< / h2 >
< p > You now have everything you need to construct complex applications complete with authentication and storage on the Decentralized Internet. Why not try coding < a href = "multi-player-storage.md" > a sample application that accesses multiple profiles< / a > .< / p >
< p > If you would like to explore the Blockstack APIs, you can visit the < a href = "https://core.blockstack.org/" > Blockstack Core API< / a > documentation or the < a href = "https://blockstack.github.io/blockstack.js" > Blockstack JS API< / a > .< / p >
< p > Go forth and build!< / p >
< div class = "share uk-text-center" >
< a href = "https://twitter.com/intent/tweet?text=Todo List Application Tutorial&url=https://docs.blockstack.org/browser/todo-list.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 >
< / 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® and Stacks™ are trademarks of Blockstack Public Benefit Corp. < br > © 2018 Blockstack Public Benefits Corp.< / div >
< / div >
< / footer >
< / 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 >
< 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 >