---
description: A quick introduction to Melody, looking at some code, discussing some basics.
---

# Tutorial

## Setting up a demo project

To make it quick and easy to get up and running with Melody, we've prepared a tool to create a new project.

```
$ npx create-melody-app myapp
```

{% hint style="info" %}
&#x20;[npx](https://blog.npmjs.org/post/162869356040/introducing-npx-an-npm-package-runner) is a tool that comes bundled with npm since version 5.2.0. It offers a very fast way to temporarily install a command line tool through npm and run it directly.
{% endhint %}

create-melody-app will respond with a message along these lines:

```
Create Melody App

Creating a new Melody app named test-app 

Downloading template. This might take a couple of minutes...

✨  Success! Created myapp in /Users/pago/Development/myapp

Inside that directory, you can run these commands:
  yarn
    Installs the project dependencies.
  yarn start
    Starts the development server.
  yarn build
    Bundles the app into static files in the /public folder.

To start, run:
  cd myapp
  yarn
  yarn start
```

Follow the instructions and switch to the `myapp` directory.

## Looking at a first component

{% hint style="warning" %}
`create-melody-app` has not been updated to use the new `melody-streams`API yet and - to be very honest with you - Melody has not been designed to look great in a tutorial. The API shown below scales to incredibly complex cases but when used in a demo context their complexity shines through heavily.

So please don't shy away. A few lines down we will rewrite it using a lighter, more modern, API.
{% endhint %}

When you open up `src/counter/index.js` you'll find a basic component, written using the `melody-component` and `melody-hoc` API.

{% tabs %}
{% tab title="src/counter/index.js" %}
```javascript
// import the component API
import { createComponent, RECEIVE_PROPS } from 'melody-component';
// import a higher order component for dealing with event handling
import { bindEvents } from 'melody-hoc';
// import the tempalte
import template from './index.twig';

// the initial state of the component
const initialState = { count: 0 };

// some actions for increasing or decreasing the counter
const INC = 'INC';
const DEC = 'DEC';

const increaseCounter = () => ({ type: INC });
const decreaseCounter = () => ({ type: DEC });

// a reducer for handling state updates
const stateReducer = (state = initialState, action) => {
  switch(action.type) {
    case RECEIVE_PROPS:
      return {
        ...state,
        ...action.payload
      };
    case INC:
      return {
        ...state,
        count: state.count + 1
      };

    case DEC:
      return {
        ...state,
        count: state.count - 1
      };
  }
  return state;
}

// create a higher order component which binds click event handlers
// to some elements
const withClickHandlers = bindEvents({
  // "incrementButton" is available in the template and can be used
  // as a "ref"
  incrementButton: {
    click(event, {dispatch}) {
      // dispatch an increase counter event to the component
      dispatch(increaseCounter());
    }
  },
  decrementButton: {
    click(event, {dispatch}) {
      dispatch(decreaseCounter());
    }
  }
});

// create the actual component
const component = createComponent(template, stateReducer);

// and enhance it with the higher order component
export default withClickHandlers(component);

```
{% endtab %}

{% tab title="src/counter/index.twig" %}
```markup
<div class="counter">
  <h3>Counter: {{ count }}</h3>
  <button ref="{{ incrementButton }}"> + </button>
  <button ref="{{ decrementButton }}"> - </button>
</div>
```
{% endtab %}
{% endtabs %}

One thing you'll likely notice immediately with Melody is that it splits the UI from the state related logic.

## Using `melody-streams` instead

When starting a new project, we advise to consider the `melody-streams` API instead of `melody-component`, `melody-hoc` and `melody-redux`. `melody-streams` offers a more direct state handling with less boilerplate. We've learned over time that the Redux approach employed by `melody-component` delivers very beautiful code when we invest sufficient effort. However, if insufficient care is taken, it can easily become complex and hard to read - the example above is a pretty good proof for that assumption.

To install `melody-streams`, please execute the following command in your terminal:

```
$ npm install melody-streams --save
```

Now start the application by running

```
$ npm run start
```

Your application will be started at [http://localhost:8080/](http://localhost:8080/) and you'll be able to look at the counter component shown above and play a little with it.

Now that we've explored the demo application a little bit - and there's not too much to explore anyway - we can get to work. As mentioned before, the `melody-streams` API offers a better way to implement less complex components such as our `counter` component.

To convert our component, we need to adapt the code to look like this:

{% tabs %}
{% tab title="src/counter/index.js" %}
```javascript
import { createState, createComponent } from 'melody-streams';
import template from './index.twig';

// define the component function
function Counter({ props }) {
    // createState takes an initial state
    // and returns a stream of values and a mutator function
    const [count, setCount] = createState(props.value.count);
    // return the final state that will be available in the template
    return {
        count,
        increaseCounter: () => setCount(prev => prev + 1),
        decreaseCounter: () => setCount(prev => prev - 1)
    };
}

// combine the component function with the template and get a component back
export default createComponent(Counter, template);
```
{% endtab %}

{% tab title="src/counter/index.twig" %}
```markup
<div class="counter">
  <h3>Counter: {{ count }}</h3>
  <button onclick="{{ increaseCounter }}"> + </button>
  <button onclick="{{ decreaseCounter }}"> - </button>
</div>
```
{% endtab %}
{% endtabs %}

When using `melody-streams`, we declare a function which takes an observable of `props` of the component, which are provided by its parent, and returns an observable state. The latest value of that state stream is then available within the template.

Also note that we've replaced the usage of `refs` with more plain `onclick` event handlers. When using `melody-streams`, that is often sufficient when you want to use `createState`.

## Mounting components

The concept of embedding a component within another component is called **mounting** in Melody and is done by using a special Twig statement: `mount`.

{% code title="src/home/index.twig" %}
```markup
<div class="home">
    <div class="logo">
        <svg xmlns="http://www.w3.org/2000/svg" width="270" height="270" viewBox="0 0 270 270">
            <circle cx="135" cy="135" r="135" fill="#272361"></circle>
            <path d="M146.14 87.94a45 45 0 0 0-53.24 53.23L48.08 186a9 9 0 1 0 3.38 3l42.79-42.79a45 45 0 0 0 9.34 16l-24.05 24.03a9 9 0 1 0 3.19 3.18l24.05-24.05a45 45 0 0 0 16 9.34l-11.43 11.43a9 9 0 1 0 3.26 3.1l13.18-13.18a45 45 0 0 0 18.35-88.12z" fill="#6eceb2"></path>
            <circle cx="152.46" cy="100.5" r="13.5" fill="#fff"></circle>
            <circle cx="150.46" cy="102.5" r="4.5" fill="#272361"></circle>
            <circle cx="173.96" cy="117" r="9" fill="#fff"></circle>
            <circle cx="171.96" cy="117" r="3" fill="#272361"></circle>
            <path d="M140.2 34.39a4.45 4.45 0 0 1 0 6.36 4.62 4.62 0 0 1-6.47 0 4.45 4.45 0 0 1 0-6.36 4.62 4.62 0 0 1 6.47 0zM73.94 62.38a4.45 4.45 0 0 1 0 6.36 4.62 4.62 0 0 1-6.47 0 4.45 4.45 0 0 1 0-6.36 4.62 4.62 0 0 1 6.47 0zM206.45 62.38a4.45 4.45 0 0 1 0 6.36 4.62 4.62 0 0 1-6.47 0 4.45 4.45 0 0 1 0-6.36 4.62 4.62 0 0 1 6.47 0zM234.45 128.64a4.45 4.45 0 0 1 0 6.36 4.62 4.62 0 0 1-6.47 0 4.45 4.45 0 0 1 0-6.36 4.62 4.62 0 0 1 6.47 0zM200 201.62a4.45 4.45 0 0 1 0-6.36 4.62 4.62 0 0 1 6.47 0 4.45 4.45 0 0 1 0 6.36 4.62 4.62 0 0 1-6.47 0z" fill="#6eceb2"></path>
        </svg>
    </div>
    <h1 class="title">
        {{ message }}
    </h1>
    {# This is the mount tag #}
    {% mount '../counter' with { count: 5 } %}
</div>
```
{% endcode %}

The `mount` statement is overloaded to be useful in a few more cases, but the usage above is likely how most of your usages will look. Later chapters will explore additional usages.

## Mounting a top-level component

Now we're only missing a look at how our root component is mounted into the DOM. A "root" or "top-level" component is what we call a Melody component that has no parent component but is injected into the DOM directly.

{% code title="src/index.js" %}
```javascript
import { render } from 'melody-streams';
import home from './home';

const documentRoot = document.getElementById('root');
render(documentRoot, home, {
    message: 'Welcome to Melody!'
});
```
{% endcode %}
