diff --git a/_browser/multi-player-storage.md b/_browser/multi-player-storage.md
deleted file mode 100644
index 988dfef6..00000000
--- a/_browser/multi-player-storage.md
+++ /dev/null
@@ -1,839 +0,0 @@
----
-layout: learn
-permalink: /:collection/:path.html
----
-
-# Manage Data with Gaia
-
-{:.no_toc}
-
-In this tutorial, you build a micro-blogging application using multi-player Gaia
-storage. Gaia is Blockstack's
-[decentralized high-performance storage system](https://github.com/blockstack/gaia).
-The tutorial contains the following topics:
-
-- TOC {:toc}
-
-This tutorial does not teach you about authentication. That is covered in depth
-[in the hello-blockstack tutorial](hello-blockstack.html).
-
-
-
-
-## About this tutorial and the prerequisites you need
-
-{% include note.html content="This tutorial was written for a user running macOS. If you are running a Windows
-machine, you can still work through this tutorial. You will need to adjust the
-instructions for your environment."%}
-
-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.
-
-When complete, the app is capable of the following:
-
-- authenticating users using Blockstack
-- posting new statuses
-- displaying statuses in the user profile
-- looking up the profiles and statuses of other users
-
-The basic identity and storage services are provided by `blockstack.js`. To test
-the application, you need to have already
-[registered a Blockstack ID](ids-introduction.html).
-
-The tutorial relies on the `npm` dependency manager. Before you begin, verify
-you have installed `npm` using the `which` command.
-
-```bash
-$ which npm
-/usr/local/bin/npm
-```
-
-If you don't find `npm` in your system,
-[install it](https://www.npmjs.com/get-npm). Finally, if you get stuck at any
-point while working on the tutorial, the completed
-[source code is available for you](https://github.com/larrysalibra/publik) to
-check your work against.
-
-High Sierra 10.13.4.
-
-## Use npm to install Yeoman and the Blockstack App Generator
-
-You use `npm` to install Yeoman. Yeoman is a generic scaffolding system that
-helps users rapidly start new projects and streamline the maintenance of
-existing projects.
-
-1. Install Yeoman.
-
- ```bash
- npm install -g yo
- ```
-
-2. Install the Blockstack application generator.
-
- ```bash
- npm install -g generator-blockstack
- ```
-
-
-
-## Generate and launch the public application
-
-In this section, you build an initial React.js application called Publik.
-
-1. Create a the `publik` directory.
-
- ```bash
- mkdir publik
- ```
-
-2. Change into your new directory.
-
- ```bash
- cd publik
- ```
-
-3. Use Yeoman and the Blockstack application generator to create your initial
- `publik` application.
-
- ```bash
- yo blockstack:react
- ```
-
- You should see several interactive prompts.
-
- ```bash
- $ yo blockstack:react
- ? ==========================================================================
- We're constantly looking for ways to make yo better!
- May we anonymously report usage statistics to improve the tool over time?
- More info: https://github.com/yeoman/insight & http://yeoman.io
- ========================================================================== No
-
- _-----_ ╭──────────────────────────╮
- | | │ Welcome to the │
- |--(o)--| │ Blockstack app │
- `---------´ │ generator! │
- ( _´U`_ ) ╰──────────────────────────╯
- /___A___\ /
- | ~ |
- __'.___.'__
- ´ ` |° ´ Y `
-
- ? Are you ready to build a Blockstack app in React? (Y/n)
- ```
-
-4. Respond to the prompts to populate the initial app.
-
- After the process completes successfully, you see a prompt similar to the
- following:
-
- ```bash
- [fsevents] Success:
- "/Users/theuser/repos/publik/node_modules/fsevents/lib/binding/Release/node-v59-darwin-x64/fse.node"
- is installed via remote npm notice created a lockfile as package-lock.json.
- You should commit this file. added 1060 packages in 26.901s
- ```
-
-5. Run the initial application.
-
- ```bash
- npm start
- ```
-
- The system prompts you to accept incoming connections.
-
- ![Network Connection](./images/network-connections.gif)
-
-6. Choose **Allow**.
-
-7. Open your browser to `http://localhost:8080`.
-
- You should see a simple React app.
-
- ![](images/initial-app.gif)
-
-8. Choose **Sign In with Blockstack**.
-
- The application tells you it will **Read your basic info**.
-
- ![](images/login.png)
-
-Leave your new application running and move onto the next section.
-
-## Add the `publish_data` scope to sign in requests
-
-Every app that uses Gaia storage must add itself to the user's `profile.json`
-file. The Blockstack browser does this automatically when the `publish_data`
-scope is requested during authentication. For this application, the user files
-stored on Gaia are made visible to others via the `apps` property in the user's
-`profile.json` file.
-
-Modify your authentication request to include the `publish_data` scope.
-
-1. Open `src/components/App.jsx` file.
-
-2. Locate the `handleSignIn` handler method.
-
- ```javascript
- handleSignIn(e) {
- e.preventDefault();
- redirectToSignIn();
- }
- ```
-
-3. Modify the method to this:
-
- ```javascript
- handleSignIn(e) {
- e.preventDefault();
- const origin = window.location.origin
- redirectToSignIn(origin, origin + '/manifest.json', ['store_write', 'publish_data'])
- }
- ```
-
- By default, authentication requests include the `store_write` scope which
- enables storage. This is what allows you to store information to Gaia.
-
-4. Save your changes.
-5. Go back to your app at `http://localhost:8080/`.
-6. Log out and sign in again.
-
- The authentication request now prompts the user for permission to **Publish
- data stored for the app**.
-
- ![](images/publish-data-perm.png)
-
-## Understand Gaia storage methods
-
-Once you authenticate a user with `store_write` and `publish_data`, you can
-begin to manage data for your users. Blockstack JS provides two methods
-`getFile()` and `putFile()` for interacting with Gaia storage. The storage
-methods support all file types. This means you can store SQL, Markdown, JSON, or
-even a custom format.
-
-You can create a meaningful and complex data layer using these two methods.
-Before creating an application, consider fundamental data architecture and make
-some decisions about how you’re modeling data. For example, consider building a
-simple grocery list app. A user should be able to create, read, update, and
-delete grocery lists.
-
-A single file collection stores items as an array nested inside each grocery
-list:
-
-```js
-// grocerylists.json
-{
- "3255": {
- "items": [
- "1 Head of Lettuce",
- "Haralson apples"
- ]
- },
- // ...more lists with items
-}
-```
-
-This is conceptually the simplest way to manage grocery lists. When you read a
-`/grocerylists.json` file with `getFile()`, you get back one or more grocery
-lists and their items. When you write a single list, the `putFile()` method
-overwrites the entire list. So, a write operation for a new or updated grocery
-list must submit all existings lists as well.
-
-Further, because this runs on the client where anything can go wrong. If the
-client-side code encounters a parsing error with a user-input value and you
-could overwrite the entire file with:
-
-`line 6: Parsing Error: Unexpected token.`
-
-Further, a single file makes pagination impossible and if your app stores a
-single file for all list you have less control over file permissions. To avoid
-these issues, you can create an index file that stores an array of IDs. These
-IDs point to a name of another file in a `grocerylists` folder.
-
-![](images/multiple-lists.png)
-
-This design allows you to get only the files you need and avoid accidentally
-overwriting all lists. Further, you’re only updating the index file when you add
-or remove a grocery list; updating a list has no impact.
-
-## Add support for user status submission and lookup
-
-In this step, you add three `blockstack.js` methods that support posting of
-"statuses". These are the `putFile()`, `getFile()`, and `lookupProfile()`
-methods.
-
-1. Open the `src/components/Profile.jsx` file.
-
-2. Expand the `import from blockstack` statement with data methods.
-
- The `Person` object holds a Blockstack profile. Add `putFile`, `getFile`,
- and `lookupProfile` after `Person`.
-
- When you are done, the import statement should look like the following:
-
- ```javascript
- import {
- isSignInPending,
- loadUserData,
- Person,
- getFile,
- putFile,
- lookupProfile
- } from 'blockstack';
- ```
-
-3. Replace the `constructor()` initial state so that it holds the key
- properties required by the app.
-
- This code constructs a Blockstack `Person` object to hold the profile. Your
- constructor should look like this:
-
- ```javascript
- constructor(props) {
- super(props);
-
- this.state = {
- person: {
- name() {
- return 'Anonymous';
- },
- avatarUrl() {
- return avatarFallbackImage;
- },
- },
- username: "",
- newStatus: "",
- statuses: [],
- statusIndex: 0,
- isLoading: false
- };
- }
- ```
-
-4) Locate the `render()` method.
-5) Modify the `render()` method to add a text input and submit button to the
- application.
-
- The following code echos the `person.name` and `person.avatarURL` properties
- from the profile on the display:
-
- ```javascript
- render() {
- const { handleSignOut } = this.props;
- const { person } = this.state;
- const { username } = this.state;
-
- return (
- !isSignInPending() && person ?
-
: null
- );
- }
- ```
-
- This code allows the application to post statuses. It also displays the
- user's Blockstack ID. To display this, your app must extract the ID from the
- user profile data.
-
-6) Locate the `componentWillMount()` method.
-7) Add the `username` property below the `person` property.
-
- You'll use the Blockstack `loadUserData()` method to access the `username`.
-
-
- ```javascript
- componentWillMount() {
- this.setState({
- person: new Person(loadUserData().profile),
- username: loadUserData().username
- });
- }
- ```
-
-7. Add two methods to handle the status input events:
-
- ```javascript
- handleNewStatusChange(event) {
- this.setState({newStatus: event.target.value})
- }
-
- handleNewStatusSubmit(event) {
- this.saveNewStatus(this.state.newStatus)
- this.setState({
- newStatus: ""
- })
- }
- ```
-
-8. Add a `saveNewStatus()` method to save the new statuses.
-
- ```javascript
- saveNewStatus(statusText) {
- let statuses = this.state.statuses
-
- let status = {
- id: this.state.statusIndex++,
- text: statusText.trim(),
- created_at: Date.now()
- }
-
- statuses.unshift(status)
- const options = { encrypt: false }
- putFile('statuses.json', JSON.stringify(statuses), options)
- .then(() => {
- this.setState({
- statuses: statuses
- })
- })
- }
- ```
-
-9. Save the `Profile.jsk` file.
-
- After the application compiles successfully, your application should appears
- as follows:
-
- ![](images/display-complete.png)
-
-10. Enter your status in the text box and press the **Submit** button.
-
- At this point, nothing is blogged. In the next section you add code to
- display the statuses back to the user as a blog entry.
-
-## Fetch and display statuses
-
-Update `Profile.jsx` again.
-
-1. Go back to the `render()` method.
-2. Locate the `
` containing the text input and
- **Submit** button.
-3. Right after this opening `div` element, add this block.
-
- ```javascript
-
- ```
-
- This loads existing state. Your code needs to fetch statuses on page load.
-
-4. Add a new method called `fetchData()` after the `statuses.unshift(status)`
- section.
-
- ```javascript
-
- fetchData() {
- this.setState({ isLoading: true })
- const options = { decrypt: false }
- getFile('statuses.json', options)
- .then((file) => {
- var statuses = JSON.parse(file || '[]')
- this.setState({
- person: new Person(loadUserData().profile),
- username: loadUserData().username,
- statusIndex: statuses.length,
- statuses: statuses,
- })
- })
- .finally(() => {
- this.setState({ isLoading: false })
- })
- }
- ```
-
-5. Call `fetchData()` from the `componentDidMount()` method
-
- ```javascript
-
- componentDidMount() {
- this.fetchData()
- }
- ```
-
-6. Save the file.
-
- After the application compiles successfully, users are able to **Submit**
- multiple statuses and review them in the app.
-
- ![](images/saving-status.png)
-
-## Change the style
-
-1. Edit the `src/styles/style.css` file.
-2. Replace the content with the following:
-
-
- ```css
- /* Globals */
- a,a:focus,a:hover{color:#fff;}
- html,body{height:100%;text-align:center;background-color:#191b22;}
- body{color:#fff}
- .hide{display:none;}
- .landing-heading{font-family:'Lato',Sans-Serif;font-weight:400;}
-
- /* Buttons */
- .btn{font-family:'Lato',Sans-Serif;padding:0.5625rem 2.5rem;font-size:0.8125rem;font-weight:400;line-height:1.75rem;border-radius:0!important;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}
- .btn-lg{font-size:1.5rem;padding:0.6875rem 3.4375rem;line-height:2.5rem;}
- .btn:focus,.btn:active:focus,.btn.active:focus{outline:none;}
- .btn-primary{color:#fff;border:1px solid #2C96FF;background-color:#2C96FF;}
- .btn-primary:hover,.btn-primary:focus,.btn-primary:active{color:#fff;border:1px solid #1a6ec0;background-color:#1a6ec0;}
-
- /* Avatar */
- .avatar{width:100px;height:100px;}
- .avatar-section{margin-bottom:25px;display:flex;text-align:left;}
- .username{margin-left:20px;}
-
- /* Scaffolding */
- .site-wrapper{display:table;width:100%;height:100vh;min-height:100%;}
- .site-wrapper-inner{display:flex;flex-direction:column;justify-content:center;margin-right:auto;margin-left:auto;width:100%;height:100vh;}
- .panel-authed{padding:0 0 0 0;}
-
- /* Home button */
- .btn-home-hello{position:absolute;font-family:'Source Code Pro',monospace;font-size:11px;font-weight:400;color:rgba(255,255,255,0.85);top:15px;left:15px;padding:3px 20px;background-color:rgba(255,255,255,0.15);border-radius:6px;-webkit-box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);-moz-box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);}
-
- /* Input */
- input, textarea{color:#000;padding:10px;}
- .input-status{width:100%;height:70px;border-radius:6px;}
- .new-status{text-align:right;}
-
- /* Statuses */
- .statuses{padding-top:30px;}
- .status{margin:15px 0px;padding:20px;background-color:#2e2e2e;border-radius:6px}
- ```
-
-3. Save and close the `src/styles/style.css` file.
-
- After the application compiles, you should see the following:
-
- ![Multi-reader storage authentication](images/multi-player-storage-status.png)
-
-At this point, you have a basic micro-blogging app that users can use to post
-and view statuses. However, there's no way to view other users' statuses. You'll
-add that in the next section.
-
-## Lookup user profiles
-
-Let's now modify the `Profile.jsx` file to display profiles of other users.
-You'll be using the `lookupProfile()` method that you added to the `import`
-statement earlier. `lookupProfile()` takes a single parameter that is the
-Blockstack ID of the profile and returns a profile object.
-
-### Add a new route
-
-Make some changes to the routing structure of your app so that users can view
-other users' profiles by visiting `http://localhost:8080/other_user.id`
-
-1. Make sure you are in the root of your `publik` project.
-2. Install `react-router`:
-
- ```bash
- npm install --save react-router-dom
- ```
-
-3. Edit `src/index.js` file.
-4. Add an `import` to the file at the top:
-
- ```javascript
- import {BrowserRouter} from 'react-router-dom';
- ```
-
-5. Change the `ReactDOM.render()` method in `src/index.js` to:
-
- ```javascript
- ReactDOM.render(
-
-
- ,
- document.getElementById('root')
- );
- ```
-
-6. Save and close the `src/index.js` file.
-7. Edit the `src/components/App.jsx` file.
-8. Add the new route by importing the `Switch` and `Route` components from
- `react-router-dom`:
-
- ```javascript
- import {Switch, Route} from 'react-router-dom';
- ```
-
-9. Locate this line below in the `render()` method:
-
- ```javascript
- :
- ```
-
-10. Replace it with the following:
-
- ```javascript
- :
-
-
- }
- />
-
- ```
-
- This sets up a route and captures the route parameter the app will use as
- the profile lookup username.
-
-11. Save and close the `src/components/App.jsx` file.
-
-### Add a rule to process URL paths with . (dot)
-
-You also need to add a rule to your webpack config so that you can properly
-process URL paths that contain the `.` (dot) character for example,
-`http://localhost:8080/other_user.id`
-
-**NOTE**: In a production app, you must ensure the web server is configured to
-handle this.
-
-1. Open `webpack.config.js` in the root project directory and locate the
- following line:
-
- ```javascript
- historyApiFallback: true,
- ```
-
-2. Replace it with this:
-
- ```javascript
- historyApiFallback: {
- disableDotRule: true
- },
- ```
-
- You will need to run `npm start` again for this change to take effect. Don't
- worry, there is a later step for that to remind you.
-
-3. Save and close the `webpack.config.js` file.
-
-4. Edit the `src/components/Profile.jsx` file.
-5. Add a single method that determines if the app is viewing the local user's
- profile or another user's profile.
-
- ```javascript
- isLocal() {
- return this.props.match.params.username ? false : true
- }
- ```
-
- You use `isLocal()` to check if the user is viewing the local user profile
- or another user's profile. If it's the local user profile, the app runs the
- `getFile()` function you added in an earlier step. Otherwise, the app looks
- up the profile belonging to the `username` using the `lookupProfile()`
- method.
-
-6. Modify the `fetchData()` method like so:
-
- ```javascript
- fetchData() {
- this.setState({ isLoading: true })
- if (this.isLocal()) {
- const options = { decrypt: false }
- getFile('statuses.json', options)
- .then((file) => {
- var statuses = JSON.parse(file || '[]')
- this.setState({
- person: new Person(loadUserData().profile),
- username: loadUserData().username,
- statusIndex: statuses.length,
- statuses: statuses,
- })
- })
- .finally(() => {
- this.setState({ isLoading: false })
- })
- } else {
- const username = this.props.match.params.username
-
- lookupProfile(username)
- .then((profile) => {
- this.setState({
- person: new Person(profile),
- username: username
- })
- })
- .catch((error) => {
- console.log('could not resolve profile')
- })
- }
- }
- ```
-
- **NOTE**: For `https` deployments, the default Blockstack Core API endpoint
- for name lookups should be changed to point to a core API served over
- `https`. Otherwise, name lookups fail due to browsers blocking mixed
- content. Refer to the
- [Blockstack.js documentation](http://blockstack.github.io/blockstack.js/#getfile)
- for details.
-
-7. Add the following block to `fetchData()` right after the call to
- `lookupProfile(username)... catch((error)=>{..}` block:
-
- ```javascript
- const options = {username: username, decrypt: false};
- getFile('statuses.json', options)
- .then(file => {
- var statuses = JSON.parse(file || '[]');
- this.setState({
- statusIndex: statuses.length,
- statuses: statuses
- });
- })
- .catch(error => {
- console.log('could not fetch statuses');
- })
- .finally(() => {
- this.setState({isLoading: false});
- });
- ```
-
- This fetches the user statuses.
-
- Finally, you must conditionally render the logout button, status input
- textbox, and submit button so they don't show up when viewing another user's
- profile.
-
-8. Replace the `render()` method with the following:
-
- ```javascript
- render() {
- const { handleSignOut } = this.props;
- const { person } = this.state;
- const { username } = this.state;
-
- return (
- !isSignInPending() && person ?
-
: null
- );
- }
- ```
-
- ### This checks to ensure that users are viewing their own profile, by wrapping the **Logout** button and inputs with the `{isLocal() && ...}` condition.
-
-### Put it all together
-
-1. Stop the running application by sending a CTL-C.
-2. Restart the application so that the disabling of the `.` (dot) rule takes
- effect.
-
- ```bash
- npm start
- ```
-
-3. Point your browser to `http://localhost:8080/your_blockstack.id` to see the
- final application.
-
-## Wrapping up
-
-Congratulations, you are all done! We hope you've enjoyed learning a bit more
-about Blockstack. To use a working version of the app go
-[here](http://publik.ykliao.com).