Hoodie

WebApp for Everyone

Why

Hoodie is a free and Open Source Software for building applications for the web and iOS. It is a complete backend for your apps, ready for you to get creative. It works immediately out-of-the-box: develop your frontend code, plug it into Hoodie’s frontend-friendly API and your app is ready.

 

 

 

Why

When you develop it, your app runs locally first, you can then deploy and host it wherever you want to. And if you want to extend Hoodie’s core features, you can check our list of currently available plugins or build plugins yourself.

 

 

 

 

Why

Hoodie is a noBackend technology — it's there for making the lives of frontend developers easier by abstracting away the backend and keeping you from worrying about backends. It gives you Dreamcode: a simple, easy-to-learn-and-implement frontend API built into it. Hoodie is also Offline First, which means that your app users’ data is stored locally by default so your Hoodie-based apps are accessible and usable anytime, independent from your users’ internet connection.

Prerequisites

For all OS, you'll need Node.js, CouchDB and Git installed.

Follow our guides for getting started Mac OS X, Windows or Linux.

Tutorial 1

  • Creating a new app
  • App, Admin and Futon URLs
  • Structure of a Hoodie Project
  • Including the Script
  • The global window.hoodie Object

1. Creating a new Hoodie app

Hoodie comes with a command line tool called Hoodie-CLI, which helps you with a lot of Hoodie-related tasks, like setting up and running an app. If you're unsure about anything concerning CLI, you can ask it for help:

 

 

hoodie -h

1. Creating a new Hoodie app

The very first step is using Hoodie-CLI to instantiate a new application. In your terminal, go to the directory you want your application to be in and enter:

 

 

hoodie new testapp

1. Creating a new Hoodie app

Result:

 

 

 

 

 

 

1. Creating a new Hoodie app

This is Hoodie downloading all of the libraries it needs to scaffold out your app, setting up the server code, and installing the default plugins. There will now be a folder called testapp, in which you'll find a simple demo application. Let's open the directory and start up the Hoodie server!

 

On the very first run, you'll be prompted to enter a password for the Admin Dashboard, just pick something simple for now, like "alpacas". Because alpacas are neat. Then, a bunch of URLs and additional info appear.

 

 

cd testapp
hoodie start

2. App, Admin and Futon URLs

Great, your app started up and is now telling you a bunch of things about itself, for example at which URL you can access the app and which plugins it is running. The first thing you'll notice though is that Hoodie opens a browser with the demo app already running in it.

Note: if you don't want Hoodie to open a new browser tab, start the Hoodie server with

 

 

 

The -n stands for "no new browser tab please, I've already got one."

 

 

 

hoodie start -n

2. App, Admin and Futon URLs

You get 3 Urls:

2. App, Admin and Futon URLs

You get 3 Urls:

CouchDB started: http://127.0.0.1:6098

It's what the Hoodie library talks to when it fetches and stores data. You can append /_utils to this URL to reach the CouchDB database admin tool (similar to phpMyAdmin for MySQL), which is called Futon (and will soon be called Fauxton). You can sign in to Futon (or Fauxton) with the admin password you set earlier. For now, you don't really have to bother with it, but in the future, it'll be nice for inspecting the database.

2. App, Admin and Futon URLs

You get 3 Urls:

WWW:    http://127.0.0.1:6096

This is the URL that Hoodie just opened in a browser for you, it's where your app is running.

Admin:  http://127.0.0.1:6097

We'll cover the dashboard in a later guide, but it's where you can see how many users you have, reset their passwords, check out plugin admin panels etc. Again, the admin password you previously set will get you in.

2. App, Admin and Futon URLs

You get 3 Urls:

WWW:    http://127.0.0.1:6096

This is the URL that Hoodie just opened in a browser for you, it's where your app is running.

Admin:  http://127.0.0.1:6097

We'll cover the dashboard in a later guide, but it's where you can see how many users you have, reset their passwords, check out plugin admin panels etc. Again, the admin password you previously set will get you in.

3.Structure of a Hoodie Project

List the files and folders in your current directory by typing

 

and you should see something like this:

 

README.md (file)

Let's get the easiest part out of the way first – the readme file. As the name suggests, you should read it, as it contains lots of useful information.

 

ls
data  node_modules  package.json  README.md  www

3.Structure of a Hoodie Project

package.json (file)

Every Hoodie app is a Node.js application and every Node.js application needs a package.json file. It defines the name of the app (testapp in this case) and its dependencies. It is used to install and declare the used versions of hoodie-server and all core plugins.

node_modules (folder)

This is where npm, the package management system for Node, keeps all its files. Hoodie uses it to manage its plugins and dependencies, and you might use it too to manage front- and backend modules in your app. The content of this folder is determined by the previously mentioned package.json file in the app folder. To learn more about npm, check out this introduction.

3.Structure of a Hoodie Project

The contents of this folder are essential for the Hoodie app to work, so there are two things to remember:

  1. Do not edit the contents of this folder manually (only through npm).
  2. Do not add this folder to source control.

All your changes to the files in this folder will be overwritten whenever you have to install or update dependencies, and it makes no sense to put this huge folder into source control, because everyone can restore it with a simple command:

 

 

 

npm install

3.Structure of a Hoodie Project

data (folder)

Yup, that's your database. It's not hidden away in usr/local/ somewhere, it's right there in your app folder. This setup makes it really easy to move the app and its data to another system without much hassle. Also, if you want to clear all of your test data during development, you can just delete or rename this folder, Hoodie will recreate it and you can start with a clean slate. In fact, this folder wasn't generated by hoodie new, but by running the app once. You'll want to leave this out of source control, too.

 

3.Structure of a Hoodie Project

www (folder)

This is where your app lives. It includes the usual index.html and all of the app's assets. If you're into task runners such as Grunt or Gulp, this is where you'd put your compiled code (it's practically your dist folder). Hoodie doesn't care about what else you add to the app folder, so feel free to throw in your source folder, tests, more documentation, whatever you like.

 

3.Structure of a Hoodie Project

Now of course, you won't want to start coding with the Hoodie demo application every single time, which is why hoodie new supports templates. Templates can either come in the form of npm packages

 

or github repositories:

 

 

 

hoodie new appname -t npm package
hoodie new appname -t githubusername/reponame

4. Including the Script

The demo app will already have this line in its index.html, but essentially, all you need to do to make your app Hoodie-ready is include a single js library:

 

You'll notice that this file isn't in node_modules or some vendor or lib folder, instead, it is served directly by the Hoodie server itself. This is cool because it automatically contains all of the installed plugins' frontend code, too. Less hassle for you!

And that's actually it! You're ready to go.

<script src="/_api/_files/hoodie.js"></script>

5. The global window.hoodie Object

Hoodie is designed to let you build frontends the way you like to build frontends. The only way you talk to Hoodie in the frontend of your app is through the Hoodie API, which lives in a global window object and is, unsurprisingly, called window.hoodie, or simply hoodie.

Go ahead, open the app in your browser, open the console in your browser's dev tools and type hoodie.. It'll show you all of the globally available methods, like hoodie.account and hoodie.store, which are the most important ones. We'll cover these two in the next part of this guide.

Good Job!

For now, congratulations! You've created a demo Hoodie app, learned about the basic structure of a Hoodie project, you know all about the endpoints and app URLs and how to include and use the Hoodie library in your project.

Tutorial 2

This guide will explain the code in the default Hoodie app, and then we'll modify the code a bit to add some new features. Afterwards, you should have a pretty good idea of how Hoodie works, and a good starting point for exploring the docs, the other tutorials, or just hacking away.

Tutorial 2

This guide will explain the code in the default Hoodie app, and then we'll modify the code a bit to add some new features. Afterwards, you should have a pretty good idea of how Hoodie works, and a good starting point for exploring the docs, the other tutorials, or just hacking away.

Prerequisites

You should make Tutorial 1.

If you wanna skipp it, run this code to start new app.

 

 

 

 

That should open the default Hoodie app in your browser.

hoodie new hoodietut
cd hoodietut
hoodie start

1. Features of the Default Hoodie App

It's a simple todo-app designed to show you some of the basics of Hoodie. It's built with jQuery and Bootstrap for speed and simplicity. You can sign up, in and out, you can add todo items, and you can check them off.

1.1 Signing Up / Anonymous Use

In the upper right, there is a drop down for Sign Up. Click on it and create an account with your desired username and password. After that you should be logged in automatically, and now your todos will be saved to the database. If you sign in from a different browser, your todos will appear there, too.

If you use the app without signing up and/or in, you're an anonymous user. Your todos will get saved locally, in your browser, and they'll still be there when you reload the page, but they won't get saved to the server, and you won't be able to see them from anywhere else. Also, they'll vanish forever when you clear your browser store.

You can use a Hoodie app as an anonymous user first, and once you decide to sign up, your data will automatically be moved to your proper account and synced.

Go ahead, add a couple of todos!

1.1 Signing Up / Anonymous Use

In the upper right, there is a drop down for Sign Up. Click on it and create an account with your desired username and password. After that you should be logged in automatically, and now your todos will be saved to the database. If you sign in from a different browser, your todos will appear there, too.

If you use the app without signing up and/or in, you're an anonymous user. Your todos will get saved locally, in your browser, and they'll still be there when you reload the page, but they won't get saved to the server, and you won't be able to see them from anywhere else. Also, they'll vanish forever when you clear your browser store.

You can use a Hoodie app as an anonymous user first, and once you decide to sign up, your data will automatically be moved to your proper account and synced.

Go ahead, add a couple of todos!

1.2 Syncing

Once you're signed in to a Hoodie app, Hoodie will constantly try to keep your user data in sync between the server and any client that user may be signed in to. To see this happening, open the app's URL in a different Browser, or in incognito mode (so you won't be signed in automatically). Sign in to the second instance of the app with the same credentials, and when you add a todo in either tab, it should appear in the other within a few seconds. Keep that second tab open for now.

1.3 Offline support

We strongly believe that apps shouldn't break just because they're offline. So naturally, this todo app also works offline. Give it a try:

In the terminal, turn off the Hoodie server with ctrl+c (Mac) or alt+c (Windows).

In one of the tabs, add a few todos. You'll notice two things:

  1. You were able to add new todos despite the app's server being down. No error messages! It just works. Yay!
  2. If you check the second tab, the new todos won't have shown up. They can't, since all the syncing happens through the server, which you just turned off. Boo you. But just for kicks, add some new todos here too.

1.3 Offline support

And now, let's turn the server back on again (the -n option prevents a new browser tab being opened):

 

Now observe the two tabs: they should sync up with the server, and both should show all the todos you entered while offline. Preeetty nice, we think.

Hoodie apps are super robust even in bad networks, and you get two big user experience bonuses:

  1. No frustrating error messages when going offline during use

  2. Your users can always access their own data, even when offline

The code to make this work must be super complex, right? You'll be surprised…

hoodie start -n

2. The Code

Let's take a look at how the todo app uses Hoodie. Open

 

in your editor of choice.

At the very top, we initialise Hoodie and assign it to a var, so we can call its methods:

 

 

 

 

www/assets/js/main.js
var hoodie  = new Hoodie();

2.1 Adding a New Todo Object

Now scroll to the end of the file, where we handle adding a new todo to the Hoodie store. This will save the todo in the currently logged in user's own little private database. It'll get synced to the server, and it'll get synced back whenever the user logs in to the app again.

 

 

 

 

 

$('#todoinput').on('keypress', function(event) {
  if (event.keyCode === 13 && event.target.value.length) {
    hoodie.store.add('todo', {title: event.target.value});
    event.target.value = '';
  }
});

2.1 Adding a New Todo Object

The inside of the if statement is where all the action is: we're calling Hoodie's store.add() method and passing two values:

  1. The type of the object we're adding to the store. The type is just an arbitrary string, in this case todo.
  2. The object itself. This is an arbitrary JavaScript object, with keys and values. Here, it has one key, title, which holds the actual todo text.

And that, fundamentally, is it.

 

One line. That stores your todo in the local browser store, and Hoodie will take care of syncing it to wherever it needs to be. Pretty simple, right? add() also returns some promises so you can check if it worked, but let's skip that for now.

hoodie.store.add(type, object);

2.2 A Short Aside: Understanding Type

Type is a fundamental convention to deal with the lack of schemas in CouchDB, which is the database system that Hoodie uses.

In CouchDB, the same database can contain a wide variety of different records, none of which have to be defined in advance. For example, you might have records on people and records on location. The type attribute is used to distinguish these… well, types of records from each other. Here are some (abridged and fictional) objects that Hoodie might write to CouchDB:

 

 

 

 

 

 

{
    type: 'person',
    name: 'Hans Hansson',
    spirit_animal: 'Otter'
}

{
    type: 'location',
    name: 'Berlin',
    is_often_quite_windy: true
}

2.2 A Short Aside: Understanding Type

You'll notice that these are, again, just JavaScript objects. Throughout your entire Hoodie app, all data is always just JavaScript objects. But back to type:

Type is essential to give your schemaless data some structure, so when you want to fetch all locations, for example, you can easily do so.

2.3 Updating the View

So far, we've only seen how the app stores the new todo after it's been entered, but not how it's actually being displayed. Take a look at the code right above the listener we just looked at, near the end of main.js:

// when a todo changes, update the UI.
hoodie.store.on('todo:add', todos.add);
hoodie.store.on('todo:update', todos.update);
hoodie.store.on('todo:remove', todos.remove);

2.3 Updating the View

What's happening here? We're listening to some events emitted by the Hoodie store. Look at the first one: todo:add. That gets fired whenever a new object with the type todo is added. Simple, hm? The others should be self-explanatory now. When this listener fires, it calls a method that updates the model (an array of objects called collection) and then the view. There is no direct connection between the todo input and the todo list.

So we've neatly decoupled adding a todo from displaying a new todo, and this gets us all the fancy syncing action we saw previously, for free. There's no extra code to make syncing work. When a new todo arrives in the in-browser storage, the todo:add event gets fired, and the view updates. With this code, you don't have to care about where the todo came from (the current client, or the one in that other tab, or another on a phone), the app will handle it regardless.

We strooooongly suggest you use this decoupled structure when building your own apps. It really unlocks the power of Hoodie!

3. Let's Modify the Todo App

In the next several steps our demo todo app will be modified to give todos a priority of urgent, normal or later.

3.1 Adding an Add-Button

The todo app lets you type in new todos and saves them when you hit the return key. This works fine for a single input, but as we will be adding another form input for the todo priority, a submit button will be more appropriate.

First add a button to the www/index.html file. Look for the text input with the id todoinput. In the line after it add a button with the id add-todo:

 

 

 

<button id="add-todo">Add New Todo</button>

3.1 Adding an Add-Button

Second, change the main.js file so a new todo is added when the button is clicked instead of when return is pressed. Replace the last code block in the file with this:

 

 

The first line binds to a click on our newly created button. When the button is clicked the second line adds a new todo using the hoodie.store.add method. The third line within our new function clears the input.

Save the two files and refresh your browser. Enter a new task. You should see it rendered after clicking the Add New Todo button.

Now we're ready to change the interface and the data model.

// handle creating a new task
$('#add-todo').on('click', function() {
  hoodie.store.add('todo', {title: $("#todoinput").val()});
  $("#todoinput").val('');
});

3.2. Adding Priority

Adding a priority requires a new input element. Insert this right above the new button we just added in www/index.html:

 

 

Now modify the click method in main.js to store the priority:

 

 

 

 

<select id="priorityinput" class="form-control">
  <option>Urgent</option>
  <option selected="selected">Normal</option>
  <option>Later</option>
</select>
<button id="add-todo">Add</button>
// handle creating a new task
$('#add-todo').on('click', function() {
  hoodie.store.add('todo', {
    title: $("#todoinput").val(),
    priority: $("#priorityinput").val()
  });
  $("#todoinput").val('');
});

3.2. Adding Priority

In the same file, modify the paint() function to display the priority:

Change

 

 

to:

 

Save everything and try it!

 

 

+ collection[i].title +
+ collection[i].priority + ': ' + collection[i].title +

3.2. Adding Priority

At this point you should start seeing that each new task is prefaced by a priority. Because there's no database schema, it's super simple to add new values to objects in Hoodie without having to think about the database or the data structure.

However, if you haven't ticked off all the tasks you created before we added the priority selector, those will now render "undefined:" in place of a priority. Not cool. This is the flipside of simply changing the data structure on the fly. In a traditional database, you'd do a data model migration in the database and add a priority of normal to all todos that don't already have one. But since we're running a system that distributes copies of each users' database to any number of devices, we can't do that. We don't even know how many databases there are, or where.

3.2. Adding Priority

One solution to this problem is to build a robust view that simply deals with missing fields:

 

 

 

 

 

 

 

 

 

 

If you're still in the prototyping/testing phase and you want to start with a fresh database, you could also just stop the server, delete the data folder in the project root, restart the server, and sign up in the app again.

var todo = collection[i];
todo.priority = todo.priority || 'Normal';

var $li = $('<li>' +
                 '<input type="checkbox">' +
                    '<label></label>' +
                 '</input>' +
                 '<input type="text"></input>' +
            '</li>'
            );


var label = todo.priority + ': ' + todo.title;

$li.data('id', todo.id);
$li.find('label').text(label);
$li.find('input[type="text"]').val(label);

$el.append($li);

4. Conclusion

We've only briefly touched hoodie.store.add and hoodie.store.on, but that should already give you a pretty good idea of how Hoodie works, and how your app could be structured. You've also seen that Hoodie's got your back with regard to cross-device syncing and offline support. You now know how users work, and if you spend a bit more time with main.js, you'll come across hoodie.store.findAll and learn how to load data from Hoodie, too.

How did it go?

We'd love to hear your feedback on this guide, and whether it helped you. Feel free to get in touch with us on IRC or Slack.

Thanks for your interest and time!

And here's your congratulatory chicken:

3.2. Adding Priority

Second, change the main.js file so a new todo is added when the button is clicked instead of when return is pressed. Replace the last code block in the file with this:

 

 

The first line binds to a click on our newly created button. When the button is clicked the second line adds a new todo using the hoodie.store.add method. The third line within our new function clears the input.

Save the two files and refresh your browser. Enter a new task. You should see it rendered after clicking the Add New Todo button.

Now we're ready to change the interface and the data model.

// handle creating a new task
$('#add-todo').on('click', function() {
  hoodie.store.add('todo', {title: $("#todoinput").val()});
  $("#todoinput").val('');
});

deck

By Max Fuchs

deck

Hoodie is a back-end for front-end developers who focus on building decentralized, off-line-first apps.

  • 506