diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 0000000..a17cbe2
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+12.2.0
\ No newline at end of file
diff --git a/package.json b/package.json
index 0efdbb4..1cbb66d 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,8 @@
     },
     "homepage": "https://github.com/neverix/html5-game-template#readme",
     "devDependencies": {
+        "@types/file-saver": "^2.0.1",
+        "@types/toastr": "^2.1.37",
         "css-loader": "^2.1.0",
         "extract-text-webpack-plugin": "^4.0.0-beta.0",
         "file-loader": "^3.0.1",
@@ -34,11 +36,14 @@
         "webpack-dev-server": "^3.2.0"
     },
     "dependencies": {
+        "@eix/input": "git+https://github.com/eix-js/input.git",
         "@eix/utils": "git+https://github.com/eix-js/utils.git",
+        "file-saver": "^2.0.2",
         "haunted": "^4.3.0",
         "lit-html": "^1.0.0",
         "lit-rx": "0.0.2",
         "prelude-ts": "^0.8.2",
-        "rxjs": "^6.5.2"
+        "rxjs": "^6.5.2",
+        "toastr": "^2.1.4"
     }
 }
diff --git a/src/scss/base.scss b/src/scss/base.scss
index 7e88921..487d817 100644
--- a/src/scss/base.scss
+++ b/src/scss/base.scss
@@ -1,3 +1,5 @@
+@import "./toastr.scss";
+
 html, body {
     padding: 0;
     margin: 0;
@@ -7,8 +9,52 @@ html, body {
 }
 
 svg {
-    background-color: #444444;
+    background-color: #222222;
     height: 100%;
     width: 100%;
     display: block;
+}
+
+.createBar {
+    z-index:10;
+    position: absolute;
+    top:0px;
+    left:0px;
+    width:100%;
+    height:100%;
+    background-color: rgba(0,0,0,0.5);
+    transition: all 0.6s ease-in-out 0s;
+    .topContainer {
+        height: 30%;
+        width: 100%;
+        display: flex;
+        justify-content: center;
+        flex-direction: column;
+        align-items: center;
+        div{
+            height:25%;
+            width:75%;
+            input{
+                background-color: #444444;
+                color: white;
+                border: none;
+                font-size: 250%;
+                height:100%;
+                width:100%;
+                padding: 1%;
+                font-family: "roboto";
+            }
+        }
+    }
+    opacity: 0;
+    visibility: hidden;
+}
+.createBar#shown{
+    opacity: 1;
+    visibility: visible;
+}
+
+.toasts{
+    background-color: #000000;
+    box-shadow: 0 0 0px black !important;
 }
\ No newline at end of file
diff --git a/src/scss/toastr.scss b/src/scss/toastr.scss
new file mode 100644
index 0000000..064afd0
--- /dev/null
+++ b/src/scss/toastr.scss
@@ -0,0 +1 @@
+.toast-title{font-weight:700}.toast-message{-ms-word-wrap:break-word;word-wrap:break-word}.toast-message a,.toast-message label{color:#FFF}.toast-message a:hover{color:#CCC;text-decoration:none}.toast-close-button{position:relative;right:-.3em;top:-.3em;float:right;font-size:20px;font-weight:700;color:#FFF;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;opacity:.8;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);filter:alpha(opacity=80);line-height:1}.toast-close-button:focus,.toast-close-button:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=40);filter:alpha(opacity=40)}.rtl .toast-close-button{left:-.3em;float:left;right:.3em}button.toast-close-button{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.toast-top-center{top:0;right:0;width:100%}.toast-bottom-center{bottom:0;right:0;width:100%}.toast-top-full-width{top:0;right:0;width:100%}.toast-bottom-full-width{bottom:0;right:0;width:100%}.toast-top-left{top:12px;left:12px}.toast-top-right{top:12px;right:12px}.toast-bottom-right{right:12px;bottom:12px}.toast-bottom-left{bottom:12px;left:12px}#toast-container{position:fixed;z-index:999999;pointer-events:none}#toast-container *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#toast-container>div{position:relative;pointer-events:auto;overflow:hidden;margin:0 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#FFF;opacity:.8;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);filter:alpha(opacity=80)}#toast-container>div.rtl{direction:rtl;padding:15px 50px 15px 15px;background-position:right 15px center}#toast-container>div:hover{-moz-box-shadow:0 0 12px #000;-webkit-box-shadow:0 0 12px #000;box-shadow:0 0 12px #000;opacity:1;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);filter:alpha(opacity=100);cursor:pointer}#toast-container>.toast-info{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=)!important}#toast-container>.toast-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=)!important}#toast-container>.toast-success{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==)!important}#toast-container>.toast-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=)!important}#toast-container.toast-bottom-center>div,#toast-container.toast-top-center>div{width:300px;margin-left:auto;margin-right:auto}#toast-container.toast-bottom-full-width>div,#toast-container.toast-top-full-width>div{width:96%;margin-left:auto;margin-right:auto}.toast{background-color:#030303}.toast-success{background-color:#51A351}.toast-error{background-color:#BD362F}.toast-info{background-color:#2F96B4}.toast-warning{background-color:#F89406}.toast-progress{position:absolute;left:0;bottom:0;height:4px;background-color:#000;opacity:.4;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=40);filter:alpha(opacity=40)}@media all and (max-width:240px){#toast-container>div{padding:8px 8px 8px 50px;width:11em}#toast-container>div.rtl{padding:8px 50px 8px 8px}#toast-container .toast-close-button{right:-.2em;top:-.2em}#toast-container .rtl .toast-close-button{left:-.2em;right:.2em}}@media all and (min-width:241px) and (max-width:480px){#toast-container>div{padding:8px 8px 8px 50px;width:18em}#toast-container>div.rtl{padding:8px 50px 8px 8px}#toast-container .toast-close-button{right:-.2em;top:-.2em}#toast-container .rtl .toast-close-button{left:-.2em;right:.2em}}@media all and (min-width:481px) and (max-width:768px){#toast-container>div{padding:15px 15px 15px 50px;width:25em}#toast-container>div.rtl{padding:15px 50px 15px 15px}}
\ No newline at end of file
diff --git a/src/ts/common/component/component.ts b/src/ts/common/component/component.ts
index 1294ec4..cce6247 100644
--- a/src/ts/common/component/component.ts
+++ b/src/ts/common/component/component.ts
@@ -1,29 +1,98 @@
 import { Vector } from "prelude-ts"
-import { Subject, BehaviorSubject } from "rxjs";
-import { ComponentState } from "./interfaces";
-import { map } from "rxjs/operators";
+import { Subject, BehaviorSubject, Subscription, timer } from "rxjs";
+import { ComponentState, activationContext } from "./interfaces";
+import { map, debounce } from "rxjs/operators";
 import { Screen } from "../screen.ts";
+import { ComponentTemplateStore } from "../componentManager/componentTemplateStore";
+import { svg } from "lit-html";
+import { subscribe } from "lit-rx";
+import { Pin } from "../pin";
+import { success, error } from "toastr"
+import { alertOptions } from "../componentManager/alertOptions";
+import { WireManager } from "../wires";
+import { runCounter } from "./runCounter";
 
 export class Component {
+    private static store = new ComponentTemplateStore()
     private static screen = new Screen()
+    private static wireManager = new WireManager()
+    private static lastId = runCounter.get() + 1
 
     public position = new BehaviorSubject<number[]>(null)
     public scale = new BehaviorSubject<number[]>(null)
     public clicked = false
 
     private mouserDelta: number[]
+    private strokeColor = "#888888"
+    private inputs: number
+    private outputs: number
+    private activation: (ctx: activationContext) => any
+    private subscriptions:Subscription[] = []
 
-    constructor(public activationType: string,
+    public inputPins: Pin[] = []
+    public outputPins: Pin[] = []
+
+    public id: number
+
+    constructor(private template: string,
         position: [number, number] = [0, 0],
-        scale: [number, number] = [0, 0]) {
+        scale: [number, number] = [0, 0],
+        id? : number) {
+
+        //set initial props
         this.position.next(position)
         this.scale.next(scale)
+
+        //set the correct id
+        this.id = (typeof id === "number") ? id : Component.lastId++
+
+        //load template
+        const data = Component.store.store.get(template)
+
+        if (!data)
+            throw new Error(`Template ${template} doesnt exist`)
+
+        this.inputs = data.inputs
+        this.outputs = data.outputs
+
+        this.inputPins = [...Array(this.inputs)].fill(true).map(val => new Pin(false, this))
+        this.outputPins = [...Array(this.outputs)].fill(true).map(val => new Pin(true, this))
+
+        this.activation = new Function(`return (ctx) => {
+            try{
+                ${data.activation}
+            }
+            catch(err){
+                ctx.error(err,"",ctx.alertOptions)
+            }
+        }`)()
+
+        this.inputPins.forEach(val => {
+            const subscription = val.valueChanges.pipe(debounce(() => timer(1000 / 60)))
+                .subscribe(val => this.activate())
+            this.subscriptions.push(subscription)
+        })
+
+        this.activate()
     }
 
-    handleMouseUp(e: MouseEvent) {
+    public dispose(){
+        this.subscriptions.forEach(val => val.unsubscribe())
+    }
+
+    public handleMouseUp(e: MouseEvent) {
         this.clicked = false
     }
 
+    private activate() {
+        this.activation({
+            outputs: this.outputPins,
+            inputs: this.inputPins,
+            succes: (mes: string) => { success(mes, "", alertOptions) },
+            error: (mes: string) => { error(mes, "", alertOptions) }
+        } as activationContext)
+    }
+
     move(e: MouseEvent) {
         const mousePosition = Component.screen.getWorldPosition(e.clientX, e.clientY)
         this.position.next(mousePosition.map((value, index) =>
@@ -40,11 +109,16 @@ export class Component {
         this.clicked = true
     }
 
+    handlePinClick(e: MouseEvent, pin: Pin) {
+        Component.wireManager.add(pin)
+    }
+
     get state(): ComponentState {
         return {
             position: this.position.value as [number, number],
-            scale: this.position.value as [number, number],
-            activationType: this.activationType
+            scale: this.scale.value as [number, number],
+            template: this.template,
+            id: this.id
         }
     }
 
@@ -70,7 +144,57 @@ export class Component {
         ))
     }
 
-    static fromState(state:ComponentState){
-        return new Component(state.activationType, state.position, state.scale)
+    pinsSvg(pinScale: number, pinLength = 20, mode = "input") {
+        const stroke = 3
+
+        return ((mode === "input") ? this.inputPins : this.outputPins)
+            .map((val, index) => {
+                const y = subscribe(this.piny(mode === "input",index))
+
+                const x = subscribe(this.pinx(mode === "input",pinLength))
+
+                const linex = subscribe(this.x.pipe(map(val =>
+                    val + ((mode === "input") ? -pinLength : pinLength + this.scale.value[0])
+                )))
+
+                const middleX = subscribe(this.x.pipe(map(val =>
+                    val + this.scale.value[0] / 2
+                )))
+
+                return svg`
+                    <line stroke=${this.strokeColor} y1=${y} y2=${y}
+                    x1=${(mode === "input") ? linex : middleX}
+                    x2=${(mode !== "input") ? linex : middleX} 
+                    stroke-width=${stroke}></line>
+                    
+                    <circle fill=${subscribe(val.svgColor)} 
+                    stroke=${this.strokeColor}
+                    r=${pinScale}
+                    cx=${x}
+                    cy=${y} stroke-width=${stroke}
+                    @click=${(e: MouseEvent) => this.handlePinClick(e, val)}
+                    ></circle>
+                `})
+    }
+
+    public pinx(mode = true, pinLength = 15){
+        return this.x.pipe(
+            map(val => val + (
+                (mode) ?
+                    -pinLength :
+                    this.scale.value[0] + pinLength
+            ))
+        )
+    }
+
+    public piny(mode = true, index: number){
+        const space = this.scale.value[1] / (mode ? this.inputs : this.outputs)
+        return this.y.pipe(
+            map(val => val + space * (2 * index + 1) / 2)
+        )
+    }
+
+    static fromState(state: ComponentState) {
+        return new Component(state.template, state.position, state.scale, state.id)
     }
 }
\ No newline at end of file
diff --git a/src/ts/common/component/interfaces.ts b/src/ts/common/component/interfaces.ts
index 6b4ca7a..73db1cb 100644
--- a/src/ts/common/component/interfaces.ts
+++ b/src/ts/common/component/interfaces.ts
@@ -1,5 +1,15 @@
+import { Pin } from "../pin";
+
 export interface ComponentState {
     position: [number,number]
     scale: [number,number]
-    activationType: string
+    template: string
+    id: number
+}
+
+export interface activationContext {
+    inputs: Pin[]
+    outputs: Pin[]
+    succes: (mes: string) => any
+    error: (mes:string) => any
 }
\ No newline at end of file
diff --git a/src/ts/common/component/runCounter.ts b/src/ts/common/component/runCounter.ts
new file mode 100644
index 0000000..8bc0abc
--- /dev/null
+++ b/src/ts/common/component/runCounter.ts
@@ -0,0 +1,14 @@
+import { Store } from "../store";
+
+export const runCounter = {
+    store: new Store<number>("runCounter"),
+    get(){
+        return runCounter.store.get("main")
+    },
+    increase(){
+        runCounter.store.set("main", runCounter.store.get("main") + 1)
+    }
+}
+
+if (!runCounter.get())
+    runCounter.store.set("main",1)
\ No newline at end of file
diff --git a/src/ts/common/componentManager/alertOptions.ts b/src/ts/common/componentManager/alertOptions.ts
new file mode 100644
index 0000000..e36f379
--- /dev/null
+++ b/src/ts/common/componentManager/alertOptions.ts
@@ -0,0 +1,4 @@
+export const alertOptions = {
+    positionClass: "toast-bottom-right",
+    toastClass: "toasts"
+}
\ No newline at end of file
diff --git a/src/ts/common/componentManager/componentManager.ts b/src/ts/common/componentManager/componentManager.ts
index 21eb38e..50edc67 100644
--- a/src/ts/common/componentManager/componentManager.ts
+++ b/src/ts/common/componentManager/componentManager.ts
@@ -1,22 +1,222 @@
 import { Singleton } from "@eix/utils";
-import { Component } from "../component/component";
-import { Subject } from "rxjs";
+import { Component } from "../component";
+import { Subject, BehaviorSubject, fromEvent } from "rxjs";
 import { svg, SVGTemplateResult } from "lit-html";
 import { subscribe } from "lit-rx";
 import { Screen } from "../screen.ts";
-import { MnanagerState } from "./interfaces";
+import { ManagerState } from "./interfaces";
+import { Store } from "../store";
+import { KeyboardInput } from "@eix/input"
+import { success, error } from "toastr"
+import { ComponentTemplateStore } from "./componentTemplateStore";
+import { alertOptions } from "./alertOptions";
+import { WireManager } from "../wires";
+import { runCounter } from "../component/runCounter";
+import { Settings } from "../store/settings";
+import { download } from "./download";
 
 @Singleton
 export class ComponentManager {
     public components: Component[] = []
-    public svgs = new Subject<SVGTemplateResult[]>()
+    public svgs = new Subject<SVGTemplateResult>()
+    public placeholder = new BehaviorSubject("Create simulation")
 
+    private temporaryCommnad = ""
     private onTop: Component
     private clicked = false
+
     private screen = new Screen()
+    private wireManager = new WireManager()
+    private templateStore = new ComponentTemplateStore()
+    private settings = new Settings()
+
+    private commandHistoryStore = new Store<string>("commandHistory")
+    private store = new Store<ManagerState>("simulationStates")
+
+    private saveEvent = new KeyboardInput("s")
+    private createEvent = new KeyboardInput("m")
+    private closeInputEvent = new KeyboardInput("enter")
+    private ctrlEvent = new KeyboardInput("ctrl")
+    private palleteEvent = new KeyboardInput("p")
+    private shiftEvent = new KeyboardInput("shift")
+    private refreshEvent = new KeyboardInput("r")
+    private clearEvent = new KeyboardInput("c")
+    private upEvent = new KeyboardInput("up")
+    private downEvent = new KeyboardInput("down")
+
+    public name = "current"
+    public alertOptions = alertOptions
+
+    private commandHistory: string[] = []
+    private commands: {
+        [key: string]: (ctx: ComponentManager, args: string[], flags: string[]) => any
+    } = {
+            clear(ctx: ComponentManager) {
+                ctx.clear()
+            },
+            save(ctx: ComponentManager) {
+                ctx.save()
+            },
+            ls(ctx: ComponentManager) {
+                const data = ctx.store.ls()
+                const message = data.join("\n")
+
+                success(message, "", ctx.alertOptions)
+            },
+            help(ctx: ComponentManager) {
+                success(`Usage: &ltcommand> <br>
+            Where &ltcommand> is one of:
+                <ul>
+                ${Object.keys(ctx.commands).map(val => `
+                    <li>${val}</li>
+                `).join("")}
+                </ul>
+            `, "", ctx.alertOptions)
+            },
+            refresh(ctx: ComponentManager) {
+                ctx.refresh()
+            },
+            ctp: this.templateStore.commands.template,
+            settings: this.settings.commands,
+            download
+        }
+    private inputMode: string
+
+    public barAlpha = new BehaviorSubject<string>("0");
 
     constructor() {
+        runCounter.increase()
+
         this.svgs.next(this.render())
+
+        this.refresh()
+
+        fromEvent(document.body, "keydown").subscribe((e: KeyboardEvent) => {
+            if (this.barAlpha.value == "1") {
+                const elem = document.getElementById("nameInput")
+                elem.focus()
+            }
+            else {
+                e.preventDefault()
+            }
+        })
+
+        fromEvent(document.body, "keyup").subscribe((e: MouseEvent) => {
+            if (this.barAlpha.value === "1") {
+                if (this.closeInputEvent.value)
+                    this.create()
+                else if (this.inputMode === "command") {
+                    const elem = <HTMLInputElement>document.getElementById("nameInput")
+                    if (this.upEvent.value) {
+                        document.body.focus()
+                        e.preventDefault()
+                        const index = this.commandHistory.indexOf(elem.value)
+
+                        if (index) {
+                            //save drafts
+                            if (index === -1)
+                                this.temporaryCommnad = elem.value
+
+                            const newIndex = (index === -1) ? this.commandHistory.length - 1 : index - 1
+                            elem.value = this.commandHistory[newIndex]
+                        }
+                    }
+                    if (this.downEvent.value) {
+                        document.body.focus()
+                        e.preventDefault()
+                        const index = this.commandHistory.indexOf(elem.value)
+
+                        if (index > -1) {
+                            const maxIndex = this.commandHistory.length - 1
+                            elem.value = (index === maxIndex) ? this.temporaryCommnad : this.commandHistory[index + 1]
+                        }
+                    }
+                }
+            }
+            else {
+                if (this.ctrlEvent.value) {
+                    if (this.createEvent.value) {
+                        this.preInput()
+                        this.inputMode = "create"
+                        this.placeholder.next("Create simulation")
+                    }
+                    else if (this.shiftEvent.value && this.palleteEvent.value) {
+                        this.preInput()
+                        this.inputMode = "command"
+                        this.placeholder.next("Command palette")
+                    }
+                    else if (this.clearEvent.value) {
+                        this.clear()
+                    }
+                    else if (this.saveEvent.value) {
+                        this.save()
+                    }
+                    else if (this.refreshEvent.value) {
+                        this.refresh()
+                    }
+                }
+            }
+        })
+
+        this.wireManager.update.subscribe(val => this.update())
+    }
+
+    preInput() {
+        const elem = <HTMLInputElement>document.getElementById("nameInput")
+        elem.value = ""
+        this.barAlpha.next("1")
+    }
+
+    create() {
+        const elem = <HTMLInputElement>document.getElementById("nameInput")
+        this.barAlpha.next("0")
+
+        if (this.inputMode == "create")
+            success(`Succesfully created simulation ${elem.value}`, "", this.alertOptions)
+
+        else if (this.inputMode == "command")
+            this.eval(elem.value)
+    }
+
+    eval(command: string) {
+        if (!this.commandHistory.includes(command)) // no duplicates
+            this.commandHistory.push(command)
+
+        while (this.commandHistory.length > 10) // max of 10 elements
+            this.commandHistory.shift()
+
+        const words = command.split(" ")
+
+        if (words[0] in this.commands) {
+            const remaining = words.slice(1)
+            const flags = remaining.filter(val => val[0] == "-")
+            const args = remaining.filter(val => val[0] != "-")
+            this.commands[words[0]](this, args, flags)
+        }
+        else
+            error(`Command ${words} doesn't exist. Run help to get a list of all commands.`,
+                "", this.alertOptions)
+    }
+
+    clear() {
+        this.components = []
+        this.wireManager.dispose()
+        this.update()
+
+        success("Succesfully cleared all components", "", this.alertOptions)
+    }
+
+    refresh() {
+        if (this.store.get(this.name)) {
+            this.loadState(this.store.get(this.name))
+        }
+
+        for (const i of this.commandHistoryStore.ls())
+            this.commandHistory[Number(i)] = this.commandHistoryStore.get(i)
+
+        this.update()
+
+        success("Succesfully refreshed to the latest save", "", this.alertOptions)
     }
 
     update() {
@@ -64,25 +264,32 @@ export class ComponentManager {
     render() {
         let toRemoveDuplicatesFor: Component
 
+        const size = 10
         const result = this.components.map(component => svg`
-            <rect width=${ subscribe(component.width)}
-             height=${ subscribe(component.height)} 
-             x=${ subscribe(component.x)}
-             y=${ subscribe(component.y)}
-             fill="red"
-             stroke="black"
-             @mousedown=${ (e: MouseEvent) => component.handleClick(e)}
-             @mouseup=${ (e: MouseEvent) => {
+            <g>
+                ${component.pinsSvg(10, 20)}
+                ${component.pinsSvg(10, 20, "output")}
+
+                <rect width=${ subscribe(component.width)}
+                height=${ subscribe(component.height)} 
+                x=${ subscribe(component.x)}
+                y=${ subscribe(component.y)}
+                fill="red"
+                stroke="black"
+                rx=20
+                ry=20
+                @mousedown=${ (e: MouseEvent) => component.handleClick(e)}
+                @mouseup=${(e: MouseEvent) => {
                 component.handleMouseUp(e)
                 toRemoveDuplicatesFor = component
-            }}
-             >
+            }}></rect>
+            </g>
         `);
 
         if (toRemoveDuplicatesFor)
             this.removeDuplicates(toRemoveDuplicatesFor)
 
-        return result
+        return svg`${this.wireManager.svg} ${result}`
     }
 
     private removeDuplicates(component: Component) {
@@ -95,21 +302,47 @@ export class ComponentManager {
             .filter((val, index) => instances.indexOf(index) != -1)
     }
 
-    get state(): MnanagerState {
+    get state(): ManagerState {
         const components = Array.from((new Set(this.components)).values())
         return {
-            components: components.map(value => value.state)
+            components: components.map(value => value.state),
+            position: this.screen.position as [number, number],
+            scale: this.screen.scale as [number, number],
+            wires: this.wireManager.state
         }
     }
 
-    loadState(state:MnanagerState) {
+    public getComponentById(id: number) {
+        return this.components.find(val => val.id === id)
+    }
+
+    loadState(state: ManagerState) {
+        if (!state.wires) //old state
+            return
+
+        this.wireManager.dispose()
         this.clicked = false
         this.components = state.components.map(value => Component.fromState(value))
         this.onTop = null
+
+        state.wires.forEach(val => {
+            this.wireManager.start = this.getComponentById(val.from.owner).outputPins[val.from.index]
+            this.wireManager.end = this.getComponentById(val.to.owner).inputPins[val.to.index]
+            this.wireManager.tryResolving()
+        })
+
+        this.screen.scale = state.scale
+        this.screen.position = state.position
+
         this.update()
     }
 
-    save(){
-        //TODO: implement
+    save(name?: string) {
+        for (let i = 0; i < this.commandHistory.length; i++) {
+            const element = this.commandHistory[i];
+            this.commandHistoryStore.set(i.toString(), element)
+        }
+        this.store.set(name || this.name, this.state)
+        success("Saved the simulation succesfully!", "", this.alertOptions)
     }
 }
\ No newline at end of file
diff --git a/src/ts/common/componentManager/componentTemplateStore.ts b/src/ts/common/componentManager/componentTemplateStore.ts
new file mode 100644
index 0000000..2ed960e
--- /dev/null
+++ b/src/ts/common/componentManager/componentTemplateStore.ts
@@ -0,0 +1,105 @@
+import { Singleton } from "@eix/utils";
+import { Store } from "../store";
+import { ComponentTemplate } from "./interfaces";
+import { ComponentManager } from "./componentManager";
+import { success, error } from "toastr"
+
+@Singleton
+export class ComponentTemplateStore {
+    public store = new Store<ComponentTemplate>("componentTemplate")
+
+    public commands = {
+        template: (ctx: ComponentManager, args: string[], flags: string[]) => {
+            const command = args[0]
+            switch (command) {
+                case (undefined):
+                    for (let i of flags) {
+                        if (i === "--version" || i === "-v")
+                            return success("1.0.1", "", ctx.alertOptions)
+                    }
+
+                    error(`Welcome to the component template program! 
+                        To get started, try running this basic commands:
+                            ${["--version", "ls"].map(val => `${val}`).join(" ")}
+                    `, "", {
+                            ...ctx.alertOptions,
+                            timeOut: 7500
+                        })
+
+                    break
+                case ("ls"):
+                    success(`Here is a list of all the current registered component templates (including ics):
+                        <ul>
+                            ${this.store.ls().map(val => `
+                                <li>
+                                    ${val}
+                                </li>
+                            `).join(" ")}
+                        </ul>
+                    `, "", ctx.alertOptions)
+                    break
+                case ("info"):
+                    if (!args[1])
+                        return error("You need to specify a template name", "", ctx.alertOptions)
+
+                    const data = this.store.get(args[1])
+
+                    if (!data)
+                        return error(`Component ${args[1]} doesnt exist`, "", ctx.alertOptions)
+
+                    const showFunction = flags.find(value =>
+                        value === "-sf" || value === "--showFunctions"
+                    )
+
+                    success(`
+                        Name: ${data.name} <br>
+                        Inputs: ${data.inputs} <br>
+                        Outputs: ${data.outputs}
+                        ${showFunction ? `<br> Activation: ${data.activation}` : ""}
+                    `, "", ctx.alertOptions)
+                    break
+                default:
+                    error(`${command} is not a valid command for the template program`, "", ctx.alertOptions)
+            }
+        }
+    }
+
+    constructor() {
+        this.store.set("buffer", {
+            inputs: 1,
+            outputs: 1,
+            name: "buffer",
+            version: "1.0.0",
+            activation: `
+                ctx.outputs[0].value = ctx.inputs[0].value
+            `.trim()
+        })
+        this.store.set("not", {
+            inputs: 1,
+            outputs: 1,
+            name: "buffer",
+            version: "1.0.0",
+            activation: `
+                ctx.outputs[0].value = !ctx.inputs[0].value
+            `.trim()
+        })
+        this.store.set("and", {
+            inputs: 2,
+            outputs: 1,
+            name: "and",
+            version: "1.0.0",
+            activation: `
+                ctx.outputs[0].value = ctx.inputs[0].value && ctx.inputs[1].value
+            `.trim()
+        })
+        this.store.set("true", {
+            inputs: 0,
+            outputs: 1,
+            name: "true",
+            version: "1.0.0",
+            activation: `
+                ctx.outputs[0].value = true
+            `.trim()
+        })
+    }
+}
\ No newline at end of file
diff --git a/src/ts/common/componentManager/download.ts b/src/ts/common/componentManager/download.ts
new file mode 100644
index 0000000..938e944
--- /dev/null
+++ b/src/ts/common/componentManager/download.ts
@@ -0,0 +1,31 @@
+import { ComponentManager } from "./componentManager";
+import { success } from "toastr"
+import { saveAs } from "file-saver" 
+
+const version = "1.0.0"
+
+export const download = (ctx: ComponentManager, args: string[], flags:string[]) => {
+    //important flags
+    for (let i of flags) {
+        if (i === "--version" || i === "-v")
+            return success(`${version}`, "", ctx.alertOptions)
+        else if (i === "--help" || i === "-h")
+            return success(`Run "download" to download the save as a json file.
+            Flags:<ul>
+                <li>-v or --version to get the version.</li>
+                <li>-h or --help to get help (ou are reading that right now)</li>
+                <li>-s or --save to automatically save before downloading</li>
+            </ul>`,"",ctx.alertOptions)
+    }
+
+    const command = args[0]
+
+    if (command === undefined){
+        if (flags.includes("-s") || flags.includes("--save"))
+            ctx.save()
+
+        const data = JSON.stringify(ctx.state)
+        saveAs(new Blob([data]), `${ctx.name}.json`)
+
+    }
+} 
\ No newline at end of file
diff --git a/src/ts/common/componentManager/interfaces.ts b/src/ts/common/componentManager/interfaces.ts
index 54b1bc5..53023e4 100644
--- a/src/ts/common/componentManager/interfaces.ts
+++ b/src/ts/common/componentManager/interfaces.ts
@@ -1,5 +1,17 @@
 import { ComponentState } from "../component/interfaces";
+import { WireState } from "../wires/interface";
 
-export interface MnanagerState {
+export interface ManagerState {
     components: ComponentState[]
+    scale: [number,number]
+    position: [number,number]
+    wires: WireState
+}
+
+export interface ComponentTemplate {
+    name: string
+    version: string
+    activation: string
+    inputs: number
+    outputs: number
 }
\ No newline at end of file
diff --git a/src/ts/common/pin/index.ts b/src/ts/common/pin/index.ts
new file mode 100644
index 0000000..9e72fac
--- /dev/null
+++ b/src/ts/common/pin/index.ts
@@ -0,0 +1 @@
+export * from "./pin"
\ No newline at end of file
diff --git a/src/ts/common/pin/pin.ts b/src/ts/common/pin/pin.ts
new file mode 100644
index 0000000..be35394
--- /dev/null
+++ b/src/ts/common/pin/pin.ts
@@ -0,0 +1,65 @@
+import { BehaviorSubject, Subject, Subscription } from "rxjs";
+import { map } from "rxjs/operators"
+import clamp from "../clamp/clamp";
+import { Component } from "../component";
+
+export class Pin {
+    private static lastId = 0
+
+    public pair: Pin
+    private subscriptions: Subscription[] = []
+
+    public id: number
+    public _value = 0
+    public color = new BehaviorSubject<[number, number, number, number]>([0, 0, 0,0])
+    public memory: any = {}
+    public valueChanges = new Subject<number>()
+
+    public svgColor = this.color.pipe(map(val =>
+        `rgb(${val.join(",")})`
+    ))
+
+    constructor(public allowWrite = true, public of: Component) {
+        this.setValue(0)
+        this.id = Pin.lastId++
+    }
+
+    get value() {
+        return this._value
+    }
+
+    set value(value: number) {
+        if (!this.allowWrite) return
+        this.setValue(value)
+
+    }
+
+    public setValue(value: number) {
+        this._value = clamp(value, 0, 1)
+        this.valueChanges.next(this._value)
+
+        const color: [number, number, number, number] = (value > 0.5) ? 
+            [255, 216, 20, 1] : 
+            [90, 90, 90, 1]
+        
+            this.color.next((this.pair) ? color : [0,0,0,0])
+    }
+
+    public bindTo(pin: Pin){
+        this.pair = pin
+        const subscription = pin.valueChanges.subscribe(val => this.setValue(val))
+
+        this.subscriptions.push(subscription)
+    }
+
+    public unbind(pin: Pin) {
+        if (this.pair == pin){
+            this.pair = null
+            this.subscriptions.forEach(val => val.unsubscribe())
+        }
+    }
+
+    public update(){
+        this.setValue(this._value)
+    }
+}
\ No newline at end of file
diff --git a/src/ts/common/screen.ts/screen.ts b/src/ts/common/screen.ts/screen.ts
index a2ca841..775ad34 100644
--- a/src/ts/common/screen.ts/screen.ts
+++ b/src/ts/common/screen.ts/screen.ts
@@ -10,13 +10,13 @@ export class Screen {
     viewBox = combineLatest(this.width, this.height).pipe(map((values: [number,number]) =>
         this.getViewBox(...values)
     ));
-
-    private scrollStep = 1.3
-    private position = [0, 0]
+    
+    public position = [0, 0]
     public scale = [2, 2]
 
     private zoomLimits: [number,number] = [0.1,10]
 
+    private scrollStep = 1.3
     public mousePosition = [this.width.value / 2, this.height.value / 2]
 
     constructor() {
diff --git a/src/ts/common/store/index.ts b/src/ts/common/store/index.ts
new file mode 100644
index 0000000..017c10d
--- /dev/null
+++ b/src/ts/common/store/index.ts
@@ -0,0 +1 @@
+export * from "./store"
\ No newline at end of file
diff --git a/src/ts/common/store/settings.ts b/src/ts/common/store/settings.ts
new file mode 100644
index 0000000..e3a9a57
--- /dev/null
+++ b/src/ts/common/store/settings.ts
@@ -0,0 +1,29 @@
+import { Singleton } from "@eix/utils";
+import { ComponentManager } from "../componentManager";
+import { success, error } from "toastr"
+
+@Singleton
+export class Settings {
+    version = "1.0.0"
+
+    commands = (ctx: ComponentManager, args: string[], flags: string[]) => {
+        //important flags
+        for (let i of flags) {
+            if (i === "--version" || i === "-v")
+                return success(`${this.version}`, "", ctx.alertOptions)
+        }
+
+        const command = args[0]
+
+        if (command === undefined)
+            return success(
+                `Welcome to the settings cli. You can use this to tweak settings in any way imaginable!`,
+                "",
+                ctx.alertOptions)
+
+        //nothing here
+        error(`Commands ${args} couldnt be found`,"",ctx.alertOptions)
+    }
+
+    constructor() { }
+}
\ No newline at end of file
diff --git a/src/ts/common/store/store.ts b/src/ts/common/store/store.ts
new file mode 100644
index 0000000..284fe24
--- /dev/null
+++ b/src/ts/common/store/store.ts
@@ -0,0 +1,28 @@
+export class Store<T> {
+    constructor(private name: string){ }
+
+    get(key:string):T{
+        const data = localStorage[`${this.name}/${key}`]
+        
+        if(data)
+            return JSON.parse(data).value
+        
+        return null
+    }
+
+    set(key:string,value:T){
+        localStorage[`${this.name}/${key}`] = JSON.stringify({ value })
+        return this
+    }
+
+    ls() {
+        let keys = []
+        
+        for (const i in localStorage){
+            if (i.indexOf(this.name) == 0)
+                keys.push(i.substr(this.name.length + 1))
+        }
+
+        return keys
+    }
+}
\ No newline at end of file
diff --git a/src/ts/common/wires/index.ts b/src/ts/common/wires/index.ts
new file mode 100644
index 0000000..143b649
--- /dev/null
+++ b/src/ts/common/wires/index.ts
@@ -0,0 +1 @@
+export * from "./wireManager"
\ No newline at end of file
diff --git a/src/ts/common/wires/interface.ts b/src/ts/common/wires/interface.ts
new file mode 100644
index 0000000..3ee8f50
--- /dev/null
+++ b/src/ts/common/wires/interface.ts
@@ -0,0 +1,12 @@
+export interface WireStateVal {
+    from: {
+        owner: number
+        index: number
+    },
+    to: {
+        owner: number
+        index: number
+    }
+}
+
+export type WireState = WireStateVal[]
\ No newline at end of file
diff --git a/src/ts/common/wires/wire.ts b/src/ts/common/wires/wire.ts
new file mode 100644
index 0000000..9f6d5c7
--- /dev/null
+++ b/src/ts/common/wires/wire.ts
@@ -0,0 +1,15 @@
+import { Pin } from "../pin";
+
+export class Wire {
+    constructor (public input:Pin,public output:Pin){
+        this.output.bindTo(this.input)
+        this.input.pair = this.output
+        this.input.update()
+        this.output.update()
+    }
+
+    public dispose(){
+        this.output.unbind(this.input)
+        this.input.pair = null
+    }
+}
\ No newline at end of file
diff --git a/src/ts/common/wires/wireManager.ts b/src/ts/common/wires/wireManager.ts
new file mode 100644
index 0000000..05ba719
--- /dev/null
+++ b/src/ts/common/wires/wireManager.ts
@@ -0,0 +1,81 @@
+import { Singleton } from "@eix/utils";
+import { Pin } from "../pin";
+import { Wire } from "./wire";
+import { svg } from "lit-html";
+import { subscribe } from "lit-rx";
+import { ComponentManager } from "../componentManager";
+import { Observable, Subject } from "rxjs";
+import { WireState, WireStateVal } from "./interface";
+
+@Singleton
+export class WireManager {
+    public start: Pin
+    public end: Pin
+    
+    private wires: Wire[] = []
+
+    public update = new Subject<boolean>()
+
+    constructor() { }
+
+    public add(data: Pin) {
+        if (data.allowWrite) //output
+            this.start = data
+        else
+            this.end = data
+
+        this.tryResolving()
+    }
+
+    public dispose(){
+        for (let i of this.wires)
+            i.dispose()
+
+        this.wires = []
+    }
+
+    public tryResolving() {
+        if (this.start && this.end && this.start != this.end) {
+            if (this.canBind(this.start, this.end)) {
+                this.wires.push(new Wire(this.start, this.end))
+                this.start = null
+                this.end = null
+                this.update.next(true)
+            }
+        }
+    }
+
+    private canBind(start: Pin, end: Pin) {
+        if (this.wires.find(val => val.output === end))
+            return false
+        return true
+    }
+
+    get svg() {
+        return this.wires.map(val => {
+            const i = val.input.of
+            const o = val.output.of
+            return svg`
+            <line x1=${subscribe(i.pinx(false, 20))}
+                x2=${subscribe(o.pinx(true, 20))}
+                y1=${subscribe(i.piny(false,i.outputPins.indexOf(val.input)))}
+                y2=${subscribe(o.piny(true,o.inputPins.indexOf(val.output)))}
+                stroke=${subscribe(val.input.svgColor)}
+            >
+            </line>
+        `})
+    }
+
+    get state() {
+        return this.wires.map((val):WireStateVal => ({
+            from: {
+                owner: val.input.of.id,
+                index: val.input.of.outputPins.indexOf(val.input)
+            },
+            to: {
+                owner: val.output.of.id,
+                index: val.output.of.inputPins.indexOf(val.output)
+            }
+        }))
+    }
+}
\ No newline at end of file
diff --git a/src/ts/main.ts b/src/ts/main.ts
index 9e7449f..53789d3 100644
--- a/src/ts/main.ts
+++ b/src/ts/main.ts
@@ -4,37 +4,59 @@ import { Screen } from "./common/screen.ts";
 import { Component } from "./common/component";
 import { FunctionStore } from "./common/activation/activationStore";
 import { ComponentManager } from "./common/componentManager";
+import { map } from "rxjs/operators";
 
 const screen = new Screen()
 
-const test = new FunctionStore()
-test.register("buffer",(data) => {
-    return true;
-})
-
 const manager = new ComponentManager()
-manager.components.push(new Component("none",[200,100],[200,30]))
-manager.components.push(new Component("none",[300,100],[200,30]))
-manager.components.push(new Component("none",[400,100],[200,30]))
-manager.components.push(new Component("none",[500,100],[200,30]))
-manager.components.push(new Component("none",[600,100],[200,30]))
+manager.components.push(new Component("and",[200,100],[100,100]))
+manager.components.push(new Component("not",[200,500],[100,100]))
+manager.components.push(new Component("true",[200,500],[100,100]))
 manager.update()
 
-console.log(manager.state)
+
+const handleEvent = <T>(e:T,func:(e:T) => any) => {
+    if (manager.barAlpha.value == "0")
+        func(e)
+    else if (manager.barAlpha.value == "1"
+        && (e as unknown as MouseEvent).type == "mousedown"
+        && (e as unknown as MouseEvent).target != document.getElementById("nameInput"))
+        manager.barAlpha.next("0")
+}
 
 render(html`
-    <svg height=${ subscribe(screen.height) } width=${ subscribe(screen.width) }
-        @mousemove=${(e:MouseEvent) => {
+    <div @mousemove=${(e:MouseEvent) => handleEvent(e,(e:MouseEvent) => {
             manager.handleMouseMove(e)
             screen.updateMouse(e)
-        }}
-        viewBox=${subscribe(screen.viewBox)}
-        @mousedown=${(e:MouseEvent) => manager.handleMouseDown(e)}
-        @mouseup=${(e:MouseEvent) => manager.handleMouseUp(e)}
-        @wheel=${(e:WheelEvent) => screen.handleScroll(e)}
-    >
-        ${ subscribe(manager.svgs) }
-    </svg>
+        })}
+        @mousedown=${(e:MouseEvent) => handleEvent(e,(e:MouseEvent) => 
+            manager.handleMouseDown(e)
+        )}
+        @mouseup=${(e:MouseEvent) => handleEvent(e,(e:MouseEvent) => 
+            manager.handleMouseUp(e)
+        )}
+        @wheel=${(e:MouseEvent) => handleEvent(e,(e:WheelEvent) => 
+            screen.handleScroll(e)
+        )}>
+
+        <div id=${subscribe(manager.barAlpha.pipe(map(val => 
+            (val == "1") ? "shown" : ""    
+        )))}
+        class=createBar>
+            <div class="topContainer">
+                <div>
+                    <input name="ComponentName" id="nameInput"
+                        placeholder=${subscribe(manager.placeholder)}
+                    ></input>
+                </div>
+            </div>
+        </div>
+        <svg height=${ subscribe(screen.height) } 
+            width=${ subscribe(screen.width) }
+            viewBox=${subscribe(screen.viewBox)}>
+            ${ subscribe(manager.svgs) }
+        </svg>
+    </div>
 `, document.body)
 
 manager.update()
\ No newline at end of file