Assemble your own micro frontend framework
Published: 2022-07-24 21:30:00

There was a time when it was common to assemble your own PC.
You chose your MotherBoards, Graphic Cards and so on.
Those times are gone for the vast majority of us...

But nothing prevents us to do the same from or with our favorites libraries.

I am very found of the Model/View/Update a.k.a Sam Pattern.

There are great libraries that take this approach ELM, HyperApp, AppRun, Meiosis (more a pattern than a library)...

But none of them satisfied me entirely, so I, decided to assemble one which fits my needs, and easily used by my colleagues who 'hate' Javascript and don't know nothing about node.js

For that I used : [SinuousJS](https://github.com/luwes/sinuous) and [Unistore](https://www.npmjs.com/package/unistore) and I create MVU.js

I created a very simple project with vite.js, and I included the following lines in the main script

```js
import htm from 'sinuous/htm';
import { observable, subscribe } from 'sinuous/observable';
import  { render, context }  from './src/render';
import createStore from 'unistore';

const r = context()
function html() {
  return htm.apply(r, arguments);
}

const MVU =  { render, html, observable, subscribe, createStore };
window.MVU = MVU;
```
The main goal was to make the View a function of the State (or Model) and nothing else.

Here is the demo of the traditional Counter

```js
const {html, render, observable, createStore} = MVU;

const State = observable({});

const Model = createStore({
  counter : 0
});

const inc = Model.action ((model, value = 1) => {
  return ({counter : model.counter + value}); 
})
 
Model.subscribe(store => State(store));

function View () {
  let state = State();
  return html `
    <h1>Counter ${state.counter} </h1>
    <button id="incer">INC</button>
  `
}

function startApp () {
  
  Model.setState();
  
  render(View, document.body);
  
  document.getElementById("incer")
          .addEventListener("click", () => inc(1));
}

startApp()

```
You can test it here : [MVUCounter](https://flems.io/#0=N4IgZglgNgpgziAXAbVAOwIYFsZJAOgAsAXLKEAGhAGMB7NYmBvEAXwvW10RCwDcArvgBWCKnQZNieCXGIACAMIBeMALTViEegAoAlMFkKYygCa1qAnA3zUATjAyMAorGvEdAHRBQIaANbeevgOUAAyEHIA3BBgOjAAZAkw+HACAA7ptHbEcEkpaZnZuV68tKYCsOmhtBimQXoOxAJ2aFFg2TpG8mjytGDy5pbu+ACOAjB2AJ4AyjCwmtkAglBQOgDkvgHIocreWOWVMNXztfUgALrreo06aHpRaDAA7vIAsgLETtpoAPIARnBJnxJndlAA+YAdOxdehyeQQPoDe6xHQQfDEKbpEzKPY0QjQUwRORBaGwtDwqBIhH4OqmGCmABy5XgeigGIwAHNGVxcXiwgBJRkAaW8SXZu1x+0OVRqdTFCRhUD0rGCtEBwJgOiGVikHGoBKgRMixEQAEIAAwUNL-YgOGDmi2q9rqTQ-Pp3AzdCDKYCsKJNFq9ND4PyMTl2CCYpJo0OSCNRqbKENhmAJzF6CghhxgSYOOxZXzUKYx9E5vOTAAKtCLSezMFzdnzhYgxczIfstDgcGyEE5fj53gEQIAtPYGVIIBgoHBvAB+dHj+kMKczvF+ahQAT07yIDt2Ls9yP9tCDkAYND0KYHYfzxcOZdaadwPG0LBR3f3icr594uBcEdexPbwKAgVg1A0LR6HkGF7mAVEQ2ORoYGaVpHnwY5lEtKJvWUWhPXaFCDTuIgc1AlV-UUfQolgBR-GUHRiAoGAKFoCg7D0CFgFonpfX9MkeJ9ABGGIAB4UlgNBOWIQgYgAajkgweKgZQYGQCALgoahlExbF+nkFS8TQKx-kmedaGQKALkQKAKAEVTkAUjSYjiezcSExpkAtC5lGoKJ5iBBFXL5ABmTyhJ8gFhBgTRaW7Ps0B0OxkAigAfVK-S0h4ApgIKdDc5QAFY9CSlKfOStKMtVZA1Kci4fL8nK8oKgA2JSUPkDAHLqihCAYiryrK9K-T0ZAME09JkzGi4onSdLdJgfTqDNPEILdegFQW-TCBW7w1qgtBvHSnRJsIJJkEIC50uQTSBum1RXQO-RuI60w8W8dpOj4DA7HkJMLSiKZRPSfBJOk2SpgUvRTDknSsUWgZ0mQKYfNWx6fnnJGUdsac1hkyI9EQLGZsDVpBlVCh0jnEH0mHQgukJu7xth6g5O8bxWCa1EBHahQuv0CFiFpTIoCmO5Kls-xGK01iKGQdnKGM1YLhuAN8FpuB6a2gZku8qVwHRjaQDnDBEAwfQVSaux1bphnWFJ3o7HYJYHsgn5GN5+QWLYuxlCErN3soH0FYoFSvM07T7MhX33JjARjtPet0igDBqC1AB6AA9TxPDgAAqHPDtzvPUpz-PC7LvOABJ085CgFZuPQ53ZDX6fj1K0AoC1GdCuP0vuOcdBb23287jz2OUAAmHvcUnpJT31-Al4VARm5tzX8ooMLEBjqf56SM1V+HjfLQoQqs0Z8EipjO50sPpJd+KmNj-pzu7FYzNfbauzn-Xtv2I-hPNq7ZA78U6DxeyAMBCiSFmDGSUQBBQ2AAIGMu8hJJGoPoLS+VVYCQ6l1AGGAYHIAEBcUGTBwZRAwFDEwxASEXGmhPdyc4cR4lEvOLoWCw5WQntvNAsMHS7wACxzgXniEcI4FSsO8OCDhvt-angbnuVSck0Dh0QBAFhfJNHBxALufhqlECsPWN4dY6VpEgBMcbH0DoLGyONpwz+ftGYxgsXiQevtz60GTAHJRFj04KiSqJQq816FjTkhFM89im6OKYcoEKz9lBQHDk42yQ8kkpL-klCg08J7dyMWeeQR1UoWM8MQYprCAAGng0CVPMWeHOdgOGYKcdPPcAinG4gSQkMR3gzQSMCb7IRocMneRVA7eQLTQ7sAAPrJheO8DA6QKAzFdutRKxBPYmBmfgTkKFGIEjgA8CZMBjomCeK8N4SyKA7KBB4fGcBmI3GYsoKWDzmK7P2Zss5qQvkvKWB7TMMBMw-U5LqBgjybpAvIVJGS4IhIsKMeHdgAAPNZT1PbEGUDMYWycxbvNBeC3IDxUSbImUsJsGApihjgBSuwVKPZzgeR7RA2t5BYtfP8aKmh5ymmZcgYgKt2DCHRe7TFygUX4H+H4UwByCYBhQkGOVcB8DPHpXNVKmzcWi2loS9wRz2BhGUDdCgYAXRu2gr8D2L1jCqFYgxTikJ+J4QoP8HQtAHg8V9h4AWkIsDuszGAZQfBaAQFMPIJ0xzFVkyDSxJ2+13SVmtTxEwZqg0hrDRGmiHVvEeCjahXosbWLgUNr0AAYtahN0EtQevgnEPVUgVVwL6ribuEywAHxSDMmZtAiAYDgDoMAehXH4G7b2ukg7A34CEK3eIzziBRCxbQbNChfZmvbcG0N4arQpG8Rc+QcwPBdp7dC3t0JnCp1fhCFMWFx67vwOey9YJIQpn7voCmQb37EHttG3oKQq7eP9sevdCzD0fKxWEZiJaLW9AACrS2BVCUtHpPannXb++QHaEhgFHTM6gWSPUUH9YR3tPpT5BrYrQudpqfEwGg+smCz0JmkbnFh3tQhH3EVPOCRKNwCn4SBT+gt7LQYurdSRrB1sAN+3YvRg68gAAi1r21JBw3wLJmyKDfqrb0Z4ymMPwc076-1sCVQ6fkCZgwQtu34c4-TLAmYhYceyBe4iJhITAfwPSWiWpNO7vyPgXt3mUK+ZVI5-A6m7PxAhFqZ5brNlyfdPFqz07jWaWs3htLWmItpdYDxF8mVhRpfNQxvg+nhMPIxEkSrdChYLQuB7VgKq+o6CXhiR1Nqvb2t9pCVEdgVpK2VKS+G+kY7eDkJGKSQQYBzhVROuNhMTAqrgHOHUIxxxOBgK4GA7hGQzFKCQYg6REDp3Ts8c7qqQqBbsJydOk8LQPfTnAPgnIQIcUQGtqQtgHCbe2+4JK2UZy5VRHSqlNLQdiw4noU5qVoufZsBtxgCmLBErLfSzk-3nnWyix6-yQO8q-T8HIC8ad9LMnpND2btJTCyoWwUuwePArDb0jrfW6puXlJAHoFV1RaDYhyGLONWYJbWlSIDpncQ2VjYNjBoIqJEM8VPHNmn8R656K51EFVRPJhHoAfcTm+OTDWyWXi8WqxstwGTq2LUHlxe5WV7TtX3g5IcX9BMoWOPBOi+1zkBiTFvZ68dYxPCSRe3pB+lIcnMOmKJ3SoTikXwNAI3kFHh+LzcR2GOnYarI2da7RABNvwr2QB30Yrnr2+tC9TZL5q8vOJvDGSwKZJpIBXGwwbk3Nl9eZfrPnMtgQgJ7AQFMjoX1wBfZa4pDrhDONVg6GAPMVlzE0CmCuXYfwiBaAUx9hfVUiB3VzmzwkW+sPTzW1oA-QL+AngouIDMYfWxOTpTDw4Pg2hhz3-+I-zMKq7AmazB-ITHVjALfooPQIwAwIHBPINsxPkCtFhBaKgsoA7ghoAYTElANhLNVg+hAHYHIIoIaKYHOLQIPC-jAG-rQB-g-kXvNKDP2sQAQYSMEKYE4F1A6B7rgfgYQV5qwYYiQSgf7h-KyhiCAQweAVIKpBPMCp-D-urAePzpiH7sxLLO-PcFxPLpgasHoKiGaLQM-meE4HaLOK3sfr7JaDcGSLQAiH+tznIXzjrvisxMgLQJpDvvcIzrlBZN5PAd4LQMUhZBFD4SAIdDXv+iQV3vrDpn3qkAPnAEPiPmPjzvIQ4TPtQLjPPovjHlwJvtvoHnvmgEyqkJiLAL8sQJWMkQLu6k8jvM-qkEWFqFaMVGeCwV8JIjXr2nAPUToI0ZxPrD9FOG0YUXcksMQHaMPp8DWtUd4pXsUTALynXjMZNsXkMbMbYN2LBqIYYkkfYZUYITAe-OYfvtMXiJuP2sYTGLQO3iADyDgEEFps4T5MCvvmiKHFlFxCpOyJ0dbjoNPBiLQGELQM8JMIoP2rFlpAuNTqYM4CCAwMSBAaCLZHwITGWDtrQCCNCVIHCUwAiRQEiRQLGMQMdOiFiiNKNFZL5KqNLJRiqKLnSEod7B1l6gxNxoYHCMQIYIQVHnABoqwMmC5GiPPNfiyLBvDHyEJB5BMuiM2qJJPAuOosALQIgCgZ3CHBACkqwJSSYM+mygvONmMdXqtijutj9owBsbflHp6HuNYcTknmTiyKIkqUQDoMKBfCVNIeYgqhVnGECDkAAEINjZBajeyh7qwR4MCp4JCEZOyi5-70kfxcRkj+RwG4jLqey+wpA3537UFSSLp8gpDh4ODhksjYEOAHAgiMFGjUZG4ami42hxGRimTKDPCi6biODGSTQKYxm0C0BYq-C1nYDJwmCVii6EAvitZLybLvEdRLapCa6pAIErp9DKAACq457WnpQY8gy2khW+i5y5DEbWk54IzW2qYszWWmmYnIJW8mAAaqgbWkyTps9EYAvlAHuFmNkRAMvqvj9BvlALye8tpJvBgL1JTB1qiC2oNp7G9BgOlAIFQkkBgBiHyBmtukkBxpwQwYQXyEICnFwYSOhTgXgVhYSHyBgDGEhVig3BQKYMhZPj6R4AIJTBQCBbRQlk1NsQoWLExcsoQCqDhIFj4vhvZLZPhipF+fhj6ExPhlgJIfhpNGxJyFktQPxRMlJt4pPLJuZqMAhp7N4leZyMVkyXmgHAZXhIuT6NbBIBAYSalNbAWZHsWYqDEESWYEaV9ojjAMjsMFIGjlyJjqBLikwKYBWbKlDoueJbYFAPQDABaeYdee6JgkxRgAYBgPAWaOggkGlbiJaGcsoClYuX1JlOkBuWTDNrGEsEkOiEsA+i5k+m9OCOiCbsFaFdqM8pNBAITJNOyJuDFXFd3JTERfhUaDGCDJAMRaFXYekC+DzFmLVXYK5vTA1cALRYZTNrRYqc4CdDRUQJmLRSKutdOh9vgP4EkFtatTtf4GFnNVFstXNustqHZL1CVLRV+bRcqBTNVcoBDg+geP6ouJySyEcpTEJpuTDiGFFlHMgkQMoIyC8UIIRkIPREICggkHDQjXZNOtdfhlXFiqfNQIltBHDf7npRPDdJ9DCFEO6qpKGYWcQFHnoPAULA5UWfSFEI0NOhSASGAB4D9WAH9e6rYIDfSEcnGPSCir8HENIS8sumpYTb0FtSTePhhikDjoLDpELYSFyQ8Y5k1rSOsnGR6lOauhrVeQ7HcORMbQZA5GgDNFAJoVANVtkkLMIKBKHOFlgBccgLbcdBZLbVllFDFELPSJAE8OUTsZiKrp3MAHsqaL6szQuNYTBIfupNZHYDZNaPsipdxL5KxN7WQpDRCAIAzBRM8n7WQrOkLNKivmbrZF+iIORDcBqThGyfIFXHxAldBL6dat0FqcQFTqOY6XxVKjKtRCcqquqqKroF6K3bmochPHzQLQ2hCiArrJpJZXUd8R5BTUPB1NpCJNQKJNbM2jhFDMlNQD5AAEpdAjjb3mZrAz0J4L4r5r4b4E06SHLDTsD2QhjCChqJTsyeAWhBCLldRVz0JULHRdQ6W+rjoixiz7HPLgOkL5WZjsgzLBWv1JKjqYO-npR+Q8R9TUDig4Mv2-nwF+QTJIUYNkPr5zh9TUO4Pr4UNmykM-nr653mxflmh8Wg1kz-lQbmYCi6UL5sNYNdpMP+DpQoEsTUVdqWBNgSH0XT4sT+5iO-kfJ4YtB01mbIbX2bLK3CZ3kJbmZvAiNkjfS-RWF+Bex6B0IuEOQuGlW9DabIYABe1qljFe5N5m+EcEFjP0CIWWKkAMUA4kMKlCUANClkqMyYoiyYEsGiWSakVk2UygYE5msEbtyowAWKmiaAiAZjZjmUmm7hATv02kLEkCCCokYlFC8CiCik1A9C0sH17uOkX9HAqcB0iAT5-jyGEAQ8BgSoFAGVu+7apaz05T1ty9uQWkxqgqdkygUCokszTa9TskjTeg8ltsySpCDwXjXUIYJuOqgFJK9aDtyEwmlFhATAJsGItziUnVGiOgKVNZdyMwXwjAO81osR8RDofTwzKtWS9wpqkzBgfjFEdkFIfzDZDoilKEnzm2vT4Lhjm536Gp3QAA4soN3Q8OZgABJMYYbCCnk6BYssU3ZEoGrdAABSvohZ9I6dAovUpAb5BLrEGodg30X+DoZavzg+cLiAzZnlnzgZiAbj-ozwMqgJ+AbwN5+5tLUQNSlABe8wQdPwCAPAk8iAFobAHAwRXAeAIgYgNA4hzAPA3QwAJAZAFAMEwVkwdr6oPpPLsAdrorxAgZrA8gyg7wCryrh0GgrdSLjAPrfQXLrrWoI0AbNS3QbwLIVIvrHrgZ8+NS8gkylBkgv0iAEaNSzoNSsbrdG4Yb8b3m+t8mo+Bw3mdr30W4uUvrHkPr4I8gwAab9rwm8+dA6gjA2bFmCbtgmbPb8gck8gtbEwzoRSaAqoabNSpb8wMRgrw+WocggZTbB6Xzy7nrDgqsBbaA5mN5EACy+gLbbb+WG7YbIbsWAb6bEyNrVI1SvQ6b8gokhAQk4IYB3bkwbdwAxOjAA7n7Tsz76cr7sij76bok-wnwnrvQYa64SeLe4IQoigok6ckHox9AoH6bD7rAu75mxOOQSwmQ8gx7rbj7bbc7nxiLG71EbbbbjLoIB7Lwdr8OVd5QUwDwtHj7LHnyxAf2UgvpUwAosq3gG4ZkXObbT7kn8gkJGJsJJo2JMI3gm4rYgQlAxHega7G4OgtuAbOHgb+HxAhH6Q+gu7qrQICwB0WrIAIUIUurI4Four+rnAOAxr1A3Yqr1lUgLArAmkhrLnPA8ry5bAQAA)

See how the counter is updated, while the button is not recreated and so, we don't loose the 'click listener' on it...thanks to SinuousJS.

Unistore allows to 'react' and 'call' subscribers whenever the Model changes.

In this model, there is a clean separation from the Model and the View.
The actions are centralized in one unique point and not messing around all your code

Let's refactor a bit :

```js
import { State } from "./state.js"
import { Actions } from "./actions.js"
import { Model } from "./model.js"

const {html, render} = MVU;

function View () {
  let state = State();
  return html `
    <h1>Counter ${state.counter || 0} </h1>
    <button onclick=${() => Actions.inc(1)}>INC</button>
  `
}
 
render(View, document.body);
``` 
You can test it here [SAMCounter](https://flems.io/#0=N4Igxg9gdgzhA2BTEAucD4EMAONEBMQAaEAMwEskZUBtUKTAW2TQDoALAF0fmPSk6IBqECAC+RekxYgYnTINYAraiUgChnEerkACYLogAjPACcAbpiNJdY3QF5dAWQBqAVQDcAHSg+dnXQBleUEHQxNECyskAApgMQBKb18oRAAPbAhTAINghURbPjwkME5yaGo0AAYUACYAdnFJEAZmEUYIfER4ZVV+QWE0ckZM7P0gkIK7UlMIRl0vEFYAejl83sWfPwqAp07usNc3VjBTRHzgrMQ4n11dSABXDVNdFF0qoh9E5IWoPa6ejAHiZTuQjNc5FcHAA+Cb5GKQs4JJJbVIZLIBcb-A5iIrdRClcqwEQAZhQAEYACxNKRtNCYQkVXp8dQDLRDEYYrH7eB2XQzOYLJbLDoAjYgVH+XTkKBgO6OGKi7pEXSWeAPAqOckJGG6OKPZ6vXRKnoGwQvADUqsw6sQiW2sACMrAmAenAgYUVPJVao1OvssLirvdZsibxNrGDEFDlt05PtKR8pCejKg9zO+QAgqm9QyytAdcBbrozpwHqY09ienmibnUwkvpKdrps-nYGEi2npbKjadzoJW0SYs6Ep8u86o72MwPU8PZVGG1AxKiq6w8Jw8oIYov0qMci3UzBbKjB0yJ26IHiSm3KiBaih6lUaS1pO1zA9mWpoGztM2AML2MmspttuwBSog9j4NGDzMAIJzTogACiSCwZwMSLPAMoANaLAkrBnPAAAy5ByB45CkDEiAAGRUYga4PNge4wDRdFAoxGIwOhICig8SDYARECYPguEJKW5ZQB4pBZDEUpphApC6FBYAwZorAAI4aqYACegT4qUWSZvA8AxAA5JhUBYTQBH2IsPF8QJQmLAAuiZyKmDEUBJKkADuzhugoRIAPIRBYkQeQGwBSe5UrkIYCmeeRw6sJwWnYBB9g2eA7CUPgxFyLhUUyc28BxdKkb4F0+AAHL7DACQ9PIADmVXSBlmWEQAklVADSiw0T01kZbZnS8Yg-HdIJwkgDR7nwAkiSsMYZjmNcSkqQIkhgNl8C5SRnAoAAhB8QJGJwZyIIdVTfEBOYQB5CRgc25D2PEHhiRWuhQKwMqCI1pjkClNFJT9iB-QDWn2F9INgylo5fWcpCRGcpiZJhYBaUD5D4YgiOmMjAAKCDkOjkPY7jyOo8TWlw-BEAwHA-2NTKbWLA8eAALR9l0AjkDaMCLAA-FjXOaLz8AwJlzrql0iwoF9px0wz5BM1ALMgJgUDQFpHRs4LwtnNzZR85lcwA7L+sEKLxuLDA0js1kysyosRDkGIN1tiW93AIlX1jaJiBlhWHi+9g9hHR4MX2HdnmSQHW0eRwCMu-NYgeH+24eEgARYfYMScEQiBEBARCmAkEVZ59L2p4VFfPeSZEADx0UgUCNZw7BkRaFoPRX8D2IgNDkE5RBgPYKVpfJuh95lUAweCpiCxANDwE5KDwEQDz9zQXdD2RFGbxl2qmDQVROfYYAeN0eDSvvbUkqJNDkmfwVKASnCRvTytQDEx9PwAPn-eII8khXwKIlA+9gACsCQf6PzPr-JyAD4gJBoAPHeTkz4X1ATfGIECABsPcA66EwFvdBRB2C5wQfYBBSDEg0EwMPUOUB6FOQ8NgAB49ECTzAAdTK7siR9Sopwye7BeGLH4dARYACYih3YDRGg7BEF-xoMPBBLDAIphAoQgI+BMqLEktJSwLwIZVA8FpBu2BWAtzbh3LSXcEj4AtGPVKXCFLYBoFpM+fDNECJAALdxniTg2mMu3EiCQUABNYe9NM+BEhEGwP41g2A2bsBkuEtRDCnFgAtJscQ2DwHaOIbnMu0J344GwPALSHleLrywnnEeRciA0FyUQWeRknLIjekklJecXGT2PqfIaZAfGSL8ZgFAmBtzzWwaYbpMBUlgHmtEksEhMwaOAkOTghTC7F1MPYckrS9HEGei0vuJ9h6j03tCYAezD5AweNI1W8MxpYDANcZYAA9LwXgYAACpvm+B+b8v+3y-kAtBb8gAJMsRqnwJQgGRAkAWPRknzNwQAqARAqjpLvvcjFSKYgop6Q8v+mLtQl3sLUHFGVag0VVkM1gjLBEPGRXM1JDwiD3xQLcyldKaIHRZUStFR0iCQNaek6EUCgYeQAQKmabVoFAyFakzFpgi6jj2QQjeSq2W4JLuqilBC4ZHOrtJCum9TEPAbu-ax7cPAPHscAB4QMeXkhomAbcI9cGdJrkQkhpjMDWpoA8JyVihA2I8JgexEFODBqciwilh8BbpUyg3QWMlPVnJXhSrlUAnEXR5ZSAW9LMrs3ZoIlNixoTpr2Qc1WuTwmq0QBaZhp8UDkGTW1DtJz4Vy3zSgFNJlFgmQAZWkAQ6-HPQumO6tfiM0av2ekoGY7MoCx-lAoukNDkNoHWrZYgif4N0gRwuN9CLRPzVrOglHqF0ZRJEq+w8BzkLvXoSx9z7dVqqpRS7Fu6hlClHWrLwnApF-xTQAAx8OBwDQzvkLznTeilVK+391vfYe9VES2LAOmWg9ezKRED7k+0+SyA7iXuJmiQAB9SGiBfJOBwEQQI6zZxbOABXCCVHWCNQDnnbKdU3pkY+ogaREEfLOEY1x9cfGSIF2RAXewdTQkwALtx3jWzRNrnUwpzMed5OIFHJgUwjV1qcBUyo0czdw3t2hOSZNA7zkSDSCxrR7GiGcHsIESMjFKkyZU0ZkzqEBOJS2cszMeNMBaW+jAcLphIt6YFspvTKBhEKQ8ybIwr9SiC32klmgnAOkSCUC5ochSPNpFYEYGU+A-NJGiX51g3k4vsL-ls7zFSqn5wC6ZuqEhCL2BUUQUgkkRlpkCnptzAQIKkE3duCK1co5ECMDECASQK57LQnN65jAVujlIPYcwEByD4HeN8ZZ+3C6mDdqN3Q+MJsccApJA7R2TumIrhAMeGdzv9yLtdjZ0BdAADEJsSLTNcVb3sKLdaC2G1u7c2rYvO-yuiVGqMQA4JgTipAEjLtYKj9HQkavY6G6wD8qLUkGdHJwDwHmICZyIXs4b33DvHfeKpj74ndJoRR2jyzi1WBRUQgyFVAYoZh3JXRdHgvhfhWuVDDF244n7bVZwMQyy6KQo+wcnnHO6NBADqpjzhEC5-ZzAAFXqQZyKN27qFNVkzoTaZSA0VIHjqjYBdWraIDtr36Pnoiv28XGNlE9tbrtKDz2D1ll+4Fs7qi6OPzS-jqraE39kS7ttyb5ZNrFvLd9562Zmv9kl1Nx7AAIhNpHVFXfmF1VsogquI-eUr473QFv69bZ2za+aEeu8PXfqjj3SfUmMCp6TgXWQhfxwgtcnXrAAQB2uPXyXLF+cL63FsuJ79a-D8ogGa48nlub4j0f-vpOBvDwH+7i-DfWDmAv2ICuEsgHdQvyN-7aZzAt8DmmZTyUaJ-6xrvycJOR6ZiAwAcC5yMrJQlKTa6A7LUIRSJSmC8JtJzQhZ9IKS3I2xnQyiNS4SIACwQGE6UQlzhIQQQEwACxrSoTwT9hIQoSaBVSBBcRcCcDYAoDLDLDeQ8GNYkiLTGbLC1BVAiGrDmD4HEClwoA0GqR9j5DISICoQ-wgLixgIUSxaRbRYaFVKlwJAiZ-x74yFwRyGCBl7QSoSA5xaNRKHyazK76raXyqE4IvAyhrCyiuK6A1RdB6FEHlQ1aXbkHUKOHXwYETxYFDLGBZYgYIoQH8QQBpTZBVKXatI1JECUEqEhEUSpYlhDKg64SJRW4VyqzEEVSkENoeAQGuGRDc76qeRiDYIQSzLlK+ZoG34wAVLEzXDagZEFAlH+FwqLAWilypzZ4T6mBT6pJe52hpHfSwDVG5z5w7K1ElJ5xRw0To7YBGZMH7AcKHJQAAIuGOgaxvKTxeHURURqopqmDSKmAAGYElhiKyC4GtygYHS9JhHwFDJyD-QvEgAcL3HpSLCzyMDzwHrNpHLIiJYAm5GjaCyUHAgwCgjggxBbY3L2CVFzHZCW5BJGRxDdApYFxQD4AMamBYQoAQBxK7LiqJAoArYCy3FUQyoGGqyzIQAzT85ogbhgjmSNQAIbFnDmDlBsyBDcl4GjgQGmBd6tLqrhLAHpCcB-jfiaBHIUqtHnGIC8JhxVAurol+GW4ynhI-yoE1IAEC7kCmByB-jbT4ACwQBrr8mICCkQDCmimtwcJWKY4KnWl4T4AKAkIXTvwUAWlek5Tz5+n9zkm+EkGLHqopbJTymKkaACA-Z7KU5kEzFxEJEpQLEFyNJqqeRIEUQamQw1IJCJQHQQB8lqwKBnT8zTSMl7JHTIiFQegyjwEJCxGzBZmdYFw0AQDDxUkxzYJLynyamLAQCgZLxPxjktCgYa52nZGAnDIf5wn0Qgj-TImomdnxHVE9l0Qui4nAD4n5ytAXQUmjiDnzSNqJZrgpRIBaacD4xdm7krZybcp8lrhozXAfDQJqy+nyDlp-F-zo4wBfkxA-llxDJGa8yAU3nriZicC4FGBujg5vkfZfF3mIA5bQmZTfF4E5a3laT3lgD0xm7ykRnbndn6mtFqpNm0noWZRgBYD0wHoQBOKLAtTMC4QN59lnwGa0nDiEbALlyPqfmdExBUrJQQCEQQDeSRB-iY4H4jxCx+GIQrQCB5QDBhTrzmDhJYxnAdArRqWaCaVCDaVEC6VEBJScDSJYwebIIoIrznyJD1JB7zQzGE45k7KwHra5wp6PSOhgTWlnEwDtpiCQx7zDh0qsCaxdBm4uJtTkhHyt5Yy2rsANy1BCznIoDAAQAoB9EeQDHHLPpiAuUQSy7ZH0o4E-ESHUHmGyEIRkVpCcBnH3RyzdhuEnEKRnHFr5UcAxDdTiowKU6jqCY-66DvxVHZAABCOMVwpBbJ8eSSWxAgZx6xGqEgEpjAXl6qEUhUl8LEmpdOhSqZMV8pIp1geBNObUdEmxZwq1+wppBlEAK0VpOUIeCmV2m1a5iJG5EE3kMxTF5ws8ocZeMxswEAHmgUMxtsIwSA9g+MMx7AEsMQ0BWy5cRCFBa4FRa4Wp9OAQH2bgqNjKWyY15GlBP2FJ+NugbgUBJNJSEB7A7WvmjNDeo4jU7+OYLg+pEOvloOoE-gR58AcsrS0g7ahJxJRmZJvIY8-GI8ucHKmA5C8SsBiUFCJZRkhSuimAACDwkaNEmAyUbULOr2NEie5plp1pbUH4zFIZO0ZtZpwZb1O0bUmAQMhtHmDaRA+ARtGJZgaEHK2ARAStPtm+2ClFL5gd5C80Eci0W6Hum868Hufc5AI830Y8ad21hcHuocxcjUuqiyIxreheH2tQJeEeakluhSH2HNjUb+vlaExqtdUc1Nz0syrImgBxy191LVj1FxZEtlkE9VxhCEZhykFhVhNhLs7WQg+AztNWuh1NKdJw8A0AiArVTZnNHsHqitD0mAmpB0bqVE+9GUR0om9gmAa2RCFCQC2AZNwma6WMmYNET9YxExMQui0IWM5Ss989H98moc5A4Socpoq9qQG92K8SjtltOUQMliQZMDO0SSXZEsDwNMu+n9wAPtddhBPteViEMi3tHAo4PtxWuDpO0hrAWENEBD2DRDWEV5rSb9MumDxBs4+AG80dH930RDc0cST99g2hAuswO2wswVtUo42Aaure+hX0u+VyTqkBVUglH4XuH4OcH4zqVEyjqjG8pOjDHukKHmIqYApetYyjix1dFKKiBi7kHgK2-c3d2x3hmp78d1zjiAHgokpOsA2UpAaEQjAoPuJw4jXQdUsxXQaQgURZ+mLdyyV2EeBDljNyMjzD8cH2pSY8ITOUIVvFVO4BkYqYO1q2GNAQG23G9938mKQDpTU8W8UArC8AxpRkABP8t+SgLshGY+jAQMS8DT0ifTZ8g2L8b88+OMMoiAT5O5iRpBmKwAPG+0W2bjQs3YJY9Jg8q8pga8aRvGiy7G58RcNADTaT7KAYDwaSKc8mgzdelW1W1SRk+q78HTQDyIpVEczYkKVcW9tY01E24ECxvhyNfV7AeEVWRJX2qTTWOAJW0AAtzYH2ymFKgTIjMQ0OmgdUhyAyw8bdYlbyMQ2otjhKRCo89cYADcsyaVEc9ix8YAZ8AASjJOzASxHsZA9ILbPSSWSaY7LSRLQhvKTEoEdt-JsF4FULhNTSQpCnGpGtIiQpXVtgTj5lUjRfJlKyGhfaOD0FRhy1LaJdq0SZywAhfBXBQmAP1Hjjq6SZqRfMsobfq5LaSQLBQna5a1hNaxMhawa7q2AMHYJQdCC9I+NbyCbhHh1FXUeZ6w6znCjq6wAgVYXF7SjspHjMqX7dUaQYsZG5y6pu7uWD3T3jdgy2xsstzcfjdk4OG4VEYoYKswZrGv2VvP2ZUxNWYwDgAF4TbVsQQ2MR7RwPRVtGbSg359xvZNyw4RrwDRrLxeKQzFoa3C1Yzk6UTTsgL2CuwR7uTVNdPAAeYdpQAoAVsVtAL14xwDsvCjyFwWr2oNzJ3WYdwOrdxgBxr1J8PZ5jx8vAA1jQAoD82eTW4f7SiEpR6EpECH3UnnajagRnt1NosCAqajz5bDxXtWqwdmbjt2oPsJA509JPohpJDVskJfTNGdZy2LKRUn1oH+zjUe3sBCACw0dCDDh6Wospw7MbiTDcppEIlIkXS-tR6pNLueRDaQcPR9ulUbywDcd-XklEALObi8cicpPjWq6lVSgADi9gvzSQEeAAEqBMskoMzVUmp8HcZj1vNFKAAFIvT3VdBbMdTkLcDC06dFwhSWDWAXSA5cfrlggXQA0mGICXBnAoBtupzeTVayWsBHD2CWfJBXhvxEi3j3hPgSC0gyCfj9CaAiDDB7jjDye2D8giNCgrBrCKAqCbBQA5dcgGCnjtjTBFeLArBfuwDig+BVdjAGBVgFdBPFcig8itcpBSjABcA8Aqi2eRB2COBHDJBJg3YuDkB67bj6DFhP6TBhDycZzFjLIjclSQZdh3ANzsDkjQiKlPDmi6CQrAClf7nOmGgAKna6ANzLBHfVr7ePfIWIUA7QBMXEw5yXdLcBgHg3izEerahiDQhdR-hPcffuhQCvd3B7fLhpg+DjfuTzd0YqhGHvxGCdDUwzeJgpDxeHgiBUh1AAAc7MNQKXzQp5IgJw9MLISpgwogYgw8L4dIIARwgQmYTg4gQAA)

Go and assemble yours (or not), and tell us why you created it :-)