Building Hangman with Hyperapp - Part 1
Tags: hyperapp, javacript, games, functional
Published: 2020-01-21 23:25:01

---
title: Building Hangman with Hyperapp - Part 1
published: true
description: Learn how to use Hyperapp to build Interactive UIs
tags: #hyperapp, #javacript, #games, #functional
---
## Building Hangman with Hyperapp
Building interactive UIs on the modern web can be a daunting task. If you're a junior developer, making the jump from jQuery to a ‘full’ Javascript UI is massive. For seasoned developers, keeping your application architecture error free and simple is hard-work, and there are as many different best practices for React, Angular and Vue as I've had hot dinners.

Things don’t have to be this way.

Let’s build a version of Hangman in Hyperapp, and see another way user interfaces can be build in Javascript. Even if you don’t want to switch your applications over to Hyperapp, you’ll learn something that will make you a better Javascript UI developer in your existing framework of choice.

## Why Hyperapp?
### Putting the “Hype” into Hyperapp
Hyperapp is a Javascript framework for building user interfaces. It uses a ‘Virtual DOM’ to update the page, as you might be familiar with in other Javascript UI Frameworks, such as React, Vue, Angular, etc. The Virtual DOM is the method by which these frameworks update the page, and Hyperapp has it's own VDOM, written from the ground up for speed and size.

### So what’s the difference?
For my money, Hyperapp has a few key advantages over React, Angular & Co.
1. It’s 1KB. That’s under 1/20th the size of React, Vue, and Angular, and a third of the size of Preact, which is  a “fast 3KB alternative to React”.
2. A functional paradigm. Some big words here, but the way Hyperapp conceptualizes your UI and application is a delight to work with. It keeps things very simple and clear and allows you to create powerful interfaces in a way that keeps them robust and manageable in size. More on that later.
3. This is a bonus feature, if you like Elm, you’ll love Hyperapp. For me,
Hyperapp is essentially Elm-architecture without the different language. If you don’t know what Elm is, don’t worry, you don’t need to - it's a language and framework for building front-end UIs, just like React, Vue and Angular. I've always enjoyed it for the way it conceptualies your app as a big function, but was put off of writing in a language that only compiled to Javascript - it's a learning curve for me, and anyone on my team.


## Let’s dive in.
To get you started with Hyperapp, we’re going to build a version of the popular word game /Hangman/, in Hyperapp.

Our game has the following spec:
* The Computer picks a random word for us to guess
* The Player inputs letters to guess the word
* Like the paper version, correct letters get inserted into the word, incorrect letters get listed elsewhere
* 8 incorrect guesses and the Player loses
*  If the Player fills in the word correctly, they win.

We may add to this spec as we go on, but this is the nuts and bolts of a game of hangman.

## Minimum Viable Hangman
We’re going to build our Hangman game up in layers. We’ll start with something that barely counts as hitting our spec - so that we can play Hangman, and then we’ll improve and refine the user experience.

### What you’ll need:
* Node.js
* A node package manager (either `npm` or `yarn`).
* A code editor
* A browser.

### Installation
Let’s dive in, get hyperapp installed and get working on our game then.
Create a new folder called `hyperapp-hangman`, and add a Javascript and HTML file:
```bash
mkdir hyperapp-hangman
touch hyperapp-hangman/index{.js,.html}
```

Let’s add a package manager, you can use `npm` or `yarn`, whatever floats your boat:

```bash
cd hyperapp-hangman

npm init . -y
# OR
yarn init . -y
```

This allows us to add Javascript packages to our application from the inter web, so let’s go ahead and add hyperapp. After all, /that’s why we’re here!/
```bash
yarn add hyperapp@beta
```

OR

```bash
npm install hyperapp@beta —save
```

Great, now we need some HTML.

Our HTML is really simple, we have a `div#app` for putting all of our UI in, and we import our Javascript file:
```html
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div id="app"></div>
<script src="./index.js"></script>
</body>
</html>
```

### To the Javascript
We're going to start by importing two things from Hyperapp. `h`, and `app`:

```js
import {h, app} from 'hyperapp';
```

Let me quickly explain both.

`app` is a function that's going to basically 'start' Hyperapp. We're going to pass it an object in a minute, with three keys: `init`, `view` and `node`:
* `init` - this is an object that describes the starting _state_ of our application. We'll put the word we need to guess here.
* `view` - the function we give this will take the state and return our UI. It'll end up as HTML on the page.
* `node` - the part of the DOM we want to insert our application into, we could write that now if we wanted:

```js
app({
init: {}, // ? - We don't know yet, maybe our guessable word
view: () => {}, // ?  - We don't know how to write views in Hyperapp yet.
node: document.getElementById('app'), // our app div in index.html
});
```

### Views

In Hyperapp, what we're actually doing is creating _virtual DOM nodes_. This is a virtual representation of the UI we want to see in the browser. Hyperapp compares this virtual representation under the hood to the real DOM and makes any necessary changes.

But how do we write it? Enter `h`.

### Updating the DOM
To explain what `h` does, it's worth thinking about how you'd add something to the DOM in Javascript. Let's try and add the following HTML to `app` using pure Javascript:

```html
<div class="pure-javascript">
<h1>This was added with pure Javascript, check me out!</h1>
</div>
```

To create our div, we do this:
```js
const div = document.createElement('div');
div.classList = 'pure-javascript';
```

and we append it to our `#app` div like so:
```js
document.addEventListener('DOMContentLoaded', () => {
    // wait for the DOM to load
    const div = document.createElement('div');
    div.classList = 'pure-javascript';
    const app = document.getElementById('app');

    app.appendChild(div);
    });
})
```

Now, we need to add our `<h1>` to our div.
```js
const h1 = document.createElement('h1');
h1.appendChild(
    document.createTextNode('This was added with pure Javascript, check me out!'),
    );

div.appendChild(h1);
```

Success! We have inserted some DOM with Javascript. This is a perfectly fine way of building a UI in Javascript, but it is _ugly_ to work with.

To counter this, Javascript wizards invented 'hyperscript', an `h` function that takes the name of an element and some children.

A basic version, without attributes looks like this:

```js
const h = (tagName, children) => {
  const element = document.createElement(tagName);

  if (typeof children === 'string') {
    element.appendChild(document.createTextNode(children));
  } else {
    children.forEach(child => {
        element.appendChild(child);
        });
  }

  return element;
};
```

You don't need to understand exactly what this is doing, but it allows us to use it like this:

```js
const container = h('div', [
    h('h1', 'Hello, World!'),
    h('p', 'This is a paragraph about the app'),
]);

app.appendChild(container);
```

We pass our child elements in to `h` as an array, and `textNodes` in as text. Lovely.

We could extend this to include an object of attributes to add to our elements, so we could use it like this.

```js
h('div', {class: 'pure-javascript'}, [
    h('h1', {}, 'This was added with pure Javascript, check me out!'),
]);
```

And there we have it.

This is actually exactly what the syntax of hyperapp's `h` looks like, except, under the hood, in creates a _Virtual_ DOM rather than editting the real DOM directly.

Let's do the same thing with hyperapp:

```js
import {h, app} from 'hyperapp';

app({
init: {}, // we don't have a state here
view: () =>
h('div', {class: 'pure-javascript'}, [
    h('h1', {}, 'This was added with pure Javascript, check me out!'),
]),
node: document.getElementbyId('app'),
});
```

### Running Hyperapp

With our basic Javascript examples, we could just open `index.html` to view our code, but `hyperapp` is install as a node module, so we need to start things a bit differently.

The easiest way, is with [Parcel JS](https://parceljs.org/)


After [installing the package](https://parceljs.org/getting_started.html), we can run `parcel` to start a server:

```bash
parcel index.html
```

Now open your browser at http://localhost:1234


### Improving on `h()`
We have a couple more options available to tidy up this view:

1) @hyperapp/html

You may have noticed another pattern available to us. `h('div',...)` is always going to be the same for every `div`. We could create a `div` function to handle this.

```js
const div = (attributes, children) => h('div', attributes, children);
```

We could do the same for `h1`, but it'd be time consuming.

That's what `hyperapp/html` has already done, We can use it to tidy up this view:

```bash
yarn add @hyperapp/html
```

```js
import {app} from 'hyperapp';
import {div, h1} from '@hyperapp/html';

app({
init: {}, // we don't have a state here
view: () =>
div({class: 'pure-javascript'}, [
    h1({}, 'This was added with pure Javascript, check me out!'),
]),
node: document.getElementById('app'),
});

```

Our other option is to use JSX, which allows you to write your view in a way that looks like HTML. You may have seen this in React.

There is a small piece of extra configuration requried if you choose to use JSX, and your view will now look like this:

```js
app({
init: {}, // we don't have a state here
view: () => (
    <div className="pure-javascript">
    <h1>This was added with pure Javascript, check me out!
    </div>
    ),
node: document.getElementById('app'),
});
```

There are some obvious benefits to JSX. If you already have written some HTML, it makes the conversion to VDOM painless. It also represents what you're actually adding to the DOM.

However, it is important to remember that underneath, both of our enhancements here are calling `h()` under the hood.

They're both doing:
```js
{
view: () =>
        h('div', {class: 'pure-javascript'}, [
            h('h1', {}, 'This was added with pure Javascript, check me out!'),
        ]),
};
```

If you're familiar with JSX, by all means get it setup and follow along. If you're new to JS UI Frameworks, stick with `h()` and `@hyperapp/html` for this tutorial. It'll help you remember you're not writing HTML, you're writing functions that create a virtual DOM.

Now that we know a bit of what's going on, we'll get stuck into building Hangman in [Part 2](https://dev.to/adamdawkins/an-introduction-to-hyperapp-part-2-492h).

* [Code for Part 1](https://github.com/adamdawkins/hyperapp-hangman-part-1)
* [Part 2](https://dev.to/adamdawkins/an-introduction-to-hyperapp-part-2-492h)

---
This tutorial was originally posted on [adamdawkins.uk](https://adamdawkins.uk) on [7th October 2019](https://adamdawkins.uk/2019/10/7/an-introduction-to-hyperapp-part-1)