UI Development

The Holochain tool comes with a way to automatically generate an API for your Holochain application, and to serve static files.

It exposes the functions which are marked in your DNA as Exposure: publicover HTTP and Websockets endpoints. You can either choose to develop a UI in a separate folder using your preferred tools, and calling the Holochain webserver API, or you can put your files in the UI directory and leverage the built in static file server. If you want to just develop some simple HTML, CSS, and JS, continue to follow these instructions. Other instructions will be provided for more sophisticated setups that use front end frameworks such as React.

 

HoloWorld Tutorial: Adding a User Interface

 

Setting up your files

Create a UI folder, under the root directory of your Holochain app, if there isn't one already.

In the UI folder, add an index.html file.

In the UI folder, add some JavaScript files, under a src folder if you want, but it's up to you.

In the UI folder, add some CSS files, under a css folder if you want, but it's up to you.

Start developing your HTML, JS and CSS.

 

Starting (and restarting) the web server

Whenever you reach the point where you need visual feedback, run the $ hcdev web command.  Note that if you have a UPnP router you can have have it searched for to open a port automatically with The hcdev --upnp=true web.  By default, the webserver will run on port 4141, but if you need it to run elsewhere, you can pass a port afterwards, such as

$ hcdev web 4142

If you used the default port, now you can navigate to http://localhost:4141 to view your index.html file, and your app.

If you make updates to your HTML, CSS, or JavaScript, you will have to kill, and restart your webserver process. Type ctrl-c in your terminal to kill your server, then use the up arrow key on your keyboard to re-use the last command, hit enter to restart it, which is necessary to see your updated files.

Sidenote: if this bugs you, and you are developing using a mac, you can use these instructions to enable the auto-restarting of your webserver when you change your UI files

expand_more webserver auto restart
Currently MAC only. a way to get the webserver to restart when files under the UI folder change
$ brew install fswatch
 
then create ...

 

Using JavaScript to communicate with the webserver API

TLDR: 

  • every request must be a POST request
  • data/body should be a string, so if JSON, use JSON.stringify
  • pattern is /fn/zomeName/functionName
  • pattern for bridging is /bridge/<token-from-getBridges>/zomeName/functionName
  • endpoint for connecting to websocket is /_sock/
  • exposure: public must be set in the DNA for the function

Now HTML and CSS you can learn about elsewhere, if you don't already know them. And JavaScript too. What you WON'T know, is how the Holochain webserver API works, so let's talk about that.  

For EVERY publicly exposed function defined in your dna.json and in your Zome code, the webserver will mount an endpoint for that function, namespaced by its Zome. Let's see that in action...

Say that there is a function called getPost in a Zome called posts. For that function, there will a reachable endpoint at http://localhost:4141/fn/posts/getPost. The fn is kind of like a namespace for the API, as opposed to the static files. The posts is a reference to the name property of the Zome you are calling. The getPost is the function name within that Zome that you are trying to call. We can contrast this with another theoretical function in the Zome called createPost, which would be called at http://localhost:4141/fn/posts/createPost.There's more...

For EVERY function call that you make, the http request type must be of type POST. Any data which the function expects as an input, should be passed as a string. So if it is JSON, first use JSON.stringify before sending.

function send(fn,data,resultFn) { 
console.log("calling: " + fn+" with "+JSON.stringify(data));
$.post( "/fn/cointoss/"+fn, JSON.stringify(data), function(response) {
console.log("response: " + response);
resultFn(response);
})
.error(function(response) {
console.log("response failed: " + response.responseText);
});
};

We generally recommend writing a function which somehow abstracts away this messiness, and provides a simple function that accepts a callback for when the response is received from the server. 

This can be seen in the simple Cointoss holochain app, for example: https://github.com/Holochain/cointoss/blob/master/ui/hc.js

If our convenience function was called send, elsewhere in the JavaScript this allows us to call this simpler method:

send("confirmToss", toss, function (result) { console.log(result); });

Using this pattern, you can call any exposed function from the Zomes in your Holochain app!

With this knowledge, you've learned all the basics that you need to start building a UI for your Holochain app. Good luck!

 

Bonus: Using a framework like React

Some Holochain apps under development have been built using React for the front end. Clutter is one example. See: https://github.com/Holochain/clutter/tree/develop/ui-src. You will notice that the directory is ui-src. Using the out-of-the-box create-react-app $ npm run build step, and the copy-to-ui.js file,  static files are published into the ui folder, for serving with the hcdev web server. The script is defined in the package.json as "build": "react-scripts build && node copy-to-ui.js", so that it is possible to just call $ npm run build from the command line. 

When developing, it is also possible to use the create-react-app server, using npm start. For this to work, you must set the proxy value in your package.json equal to the hcdev web server. So it may look like this in your package.json:

"proxy": "http://localhost:4141"

This will forward (proxy) requests made to the react server, which is likely on port 3000, to port 4141. By doing this, you can make calls in your react app to localhost:3000 as if it was localhost:4141 and avoid CORS issues. 

If you like to use the Redux library with React, there is a Redux middleware written which makes dispatching actions to a holochain web server very easy. It can be found at https://github.com/Holochain/hc-redux-middleware