diff --git a/client/client.js b/client/client.js
index 59260d3d9d53ad66ff241b6ac33c2b14108d68af..27bc8ed90f9ea64dceb3cd13ab3c2b74c6acbcc6 100644
--- a/client/client.js
+++ b/client/client.js
@@ -58,35 +58,28 @@ function loadModule(rep) {
     return rep
 }
 
-// rn: get and load a module, complete that cycle w/ json tests? 
-
-function getModule(location) {
-    console.log('getting ', location)
-    var req = new XMLHttpRequest()
-    req.open('GET', location)
-    req.send()
-    req.onreadystatechange = function(res) {
-        if(this.readyState == 4 && this.status == 200){
-            console.log('req recv')
-        }
-    }
-}
 
 // return ul element with name and alt and link? 
-function buildMenu(elem, evt) {
+function buildMenu(tree, screenTarget) {
     var menuDom = document.createElement('div')
     menuDom.id = 'menu'
-    menuDom.style.left = evt.pageX + 'px'
-    menuDom.style.top = evt.pageY + 'px'
-    for (key in elem) {
+    menuDom.style.left = screenTarget.X + 'px'
+    menuDom.style.top = screenTarget.Y + 'px'
+    for (key in tree) {
         var ul = document.createElement('ul')
         ul.innerHTML = key.toString()
-        for (subkey in elem[key]) {
+        for (subkey in tree[key]) {
             var a = document.createElement('a')
             a.innerHTML = subkey.toString()
             a.addEventListener('click', function(evt) {
-                var location = 'modules/' + key + '/' + subkey
-                getModule(location)
+                var path = tree[key][subkey].path
+                console.log('sending req for module', path)
+                var data = {
+                    target: 'new module',
+                    path: path,
+                    screenTarget: screenTarget
+                }
+                socketSend('get', data)
                 document.body.removeChild(document.getElementById('menu'))
             })
             var li = document.createElement('li')
@@ -99,7 +92,7 @@ function buildMenu(elem, evt) {
 
     function rmListener(evt) {
         var findMenu = document.getElementById('menu')
-        if(findMenu !== null && findMenu.id == 'menu'){
+        if (findMenu !== null && findMenu.id == 'menu') {
             document.body.removeChild(findMenu)
         }
     }
@@ -110,25 +103,116 @@ function buildMenu(elem, evt) {
 // get json menu item and render
 // and ask for module at /obj/key
 oncontextmenu = function(evt) {
-    var req = new XMLHttpRequest()
-    req.open('GET', '/modules/list')
-    req.send()
-    req.onreadystatechange = function(res) {
-        if (this.readyState == 4 && this.status == 200) {
-            buildMenu(JSON.parse(this.response), evt)
+    var req = {
+        type: 'get menu',
+        data: {
+            screenTarget: {
+                X: evt.pageX,
+                Y: evt.pageY
+            }
         }
     }
+    sckt.send(JSON.stringify(req))
     // prevents propogation to the os 
     return false
 }
 
+
+// client globals
+
 var modules = new Array()
 
+var sckt = {}
+
+// client fns
+
+function socketSend(type, data) {
+    var msg = {
+        type: type,
+        data: data
+    }
+    sckt.send(JSON.stringify(msg))
+}
+
+function socketRecv(evt) {
+    var recv = JSON.parse(evt.data)
+    var type = recv.type
+    var data = recv.data
+    // tree banger
+    switch (type) {
+        case 'console':
+            console.log('recv console:', data)
+            break
+        case 'get':
+            get(data)
+            break
+        case 'put':
+            put(data)
+            break
+        case 'put menu':
+            console.log(data)
+            buildMenu(data.tree, data.screenTarget)
+            break
+        default:
+            console.log('recv with non recognized type', recv)
+            break
+    }
+}
+
+// init & hookup
+
 window.onload = function() {
+    const socket = new WebSocket('ws://localhost:8081')
+
+    socket.onopen = function(evt) {
+        // pass to global ref 
+        sckt = this
+        // say hello 
+        socketSend('console', 'hello server')
+        console.log('socket open')
+        // main socket entry point
+        this.onmessage = (evt) => {
+            socketRecv(evt)
+        }
+        // others
+        this.onerror = (err) => {
+            console.log('socket error', err)
+        }
+        this.onclose = (evt) => {
+            console.log('socket closed', evt)
+            sckt = null
+        }
+    }
+
     modules.push(loadModule(gcodeDummy))
     modules.push(loadModule(terminalDummy))
 
     for (index in modules) {
         document.body.append(modules[index].ui.domElem)
     }
-}
\ No newline at end of file
+}
+
+/*
+
+to prototype
+write example, has one state, a text box. load, connect, on event goes down thru and back up 
+
+*/
+
+/* a few things
+
+ / using
+ - get a list of available modules
+ - request a new module to be added to the program 
+ - push state / get state (of individual module)
+ - get state (on load, of existing modules)
+ - save state to json
+ - load state from json 
+
+ / dev
+ - rewrite module file at / and reload all instances
+  - (how to catch errors in runtime?) 
+ - reload all instances of module at /
+ - write new defaults into /  (same as edit file, don't ambiguate)
+
+*/
\ No newline at end of file
diff --git a/package.json b/package.json
index 69cfc641caf045517fc6afd02ebc69da75ce6a6f..2fb0e633c3b106b4c28e65247b879618a0f6e6e4 100644
--- a/package.json
+++ b/package.json
@@ -8,8 +8,10 @@
   },
   "dependencies": {
     "express": "^4.16.3",
+    "http": "0.0.0",
     "readline": "^1.3.0",
-    "serialport": "^6.2.2"
+    "serialport": "^6.2.2",
+    "ws": "^6.0.0"
   },
   "devDependencies": {},
   "scripts": {
diff --git a/run.js b/run.js
index 403dc7cedfe306c5827b9ad74b082982e8a4ec09..79ea9e306cb76af942a15c3735f09b24b2afbabb 100644
--- a/run.js
+++ b/run.js
@@ -1,5 +1,7 @@
-const Terminal = require('./lib/terminal.js')	
-const Gcode = require('./lib/gcode.js')
+
+
+const Terminal = require('./src/ui/terminal.js')	
+const Gcode = require('./src/parsing/gcode.js')
 
 var terminal = new Terminal()
 var gcode = new Gcode()
diff --git a/server.js b/server.js
index d66a2f0dd44b859dfe69c6a1fe591e424ac332ca..56100868dd78e3078b4d6b24c4b2e59c438228b7 100644
--- a/server.js
+++ b/server.js
@@ -1,74 +1,129 @@
-// require express and do things, serve static and then dish a json
+// file system to load / look at our available modules / edit them 
+const fs = require('fs')
 
-const express = require('express')
-const exp = express()
+// express serves files, http makes the connection
+const app = require('express')()
+const http = require('http').Server(app)
 
-// express will serve static files from the client folder 
-exp.use(express.static('client'))
+// websocket does websocket
+const WebSocket = require('ws')
 
-var jd = {
-    parsing: {
-        gcode: {
-            description: 'gcode parser',
-            hasUi: false
-        }
-    },
-    motion: {
-        planner: {
-            description: 'acceleration lookahead',
-            hasUi: true,
-            uiPath: 'src/motion/planner/'
-        },
-        kinematics: {
-            description: 'motion to actuator spaces',
-            hasUi: false
-        },
-        controller: {
-            description: 'machine state machine',
-            hasUi: true,
-            uiPath: 'src/motion/controller/'
-        }
-    },
-    motors: {
-        stepper: {
-            description: 'stepper motor rep',
-            hasUi: false
-        },
-        bldc: {
-            description: 'bldc motor rep',
-            hasUi: false
-        }
+// serving this handful of static files
+app.get('/', (req, res) => {
+    console.log('client req /')
+    res.sendFile(__dirname + '/client/index.html')
+})
+
+app.get('/:file', (req, res) => {
+    console.log('client req', req.params.file)
+    res.sendFile(__dirname + '/client/' + req.params.file)
+})
+
+// server globals 
+
+var sckt = {}
+
+function socketSend(type, data){
+    var msg = {
+        type: type,
+        data: data
+    }
+    sckt.send(JSON.stringify(msg))
+}
+
+function socketRecv(evt){
+    var recv = JSON.parse(evt)
+    var type = recv.type
+    var data = recv.data
+    // bang thru
+    switch(type){
+        case 'console':
+            console.log('recv console:', data)
+            break
+        case 'get':
+            get(data)
+            break
+        case 'put':
+            put(data)
+            break
+        case 'get menu':
+            var tree = buildMenu()
+            var msg = {
+                tree: tree,
+                screenTarget: data.screenTarget
+            }
+            socketSend('put menu', msg)
+            break
+        default:
+            console.log('server recv with non recognized type', recv)
+            break
     }
 }
 
-// can we express this in just a few f'ns?
-// 1st do a req module and place ... link thru run.js - how to place? eval - eval is evil, says most dev.. uses interpreter, not compile 
+function get(data){
+    switch(data.target){
+        case 'new module':
+            console.log('getting module at path', data.path)
+            if(fs.existsSync(data.path)){
+                console.log('module found at', data.path)
+                var mod = require(data.path)
+                console.log(mod)
+            } else {
+                console.log('no module found at', data.path)
+            }
+            break
+        default:
+            console.log('get req with no recognized type', data)
+    }
+}
 
-// can probably think through how to just place, hookup, and change state: altho: how to put async? has to be tied to existing link?
-// arch. now for managing multiple connections? module that does top-level linking, i.e. gets from another machine?
-// can even imagine how to build c and flash
-// but how to run code? put new file and reload with? kritical
+function put(data){
+    switch(data.target){
+        case 'state':
+            // match data.id
+            // check match data.rep.state on internal
+            break
+        default:
+            console.log('put req with no recognized type', data)
+    }
+}
 
-exp.get('/modules/list', (req, res) => {
-    res.send(jd)
-    console.log('get /modules')
-})
+// and listening for requests here
+const wss = new WebSocket.Server({port: 8081})
 
-// request for new module 
-exp.get('/modules/:moduleHeader/:module', (req, res) => {
-	console.log('req module', req.params)
+wss.on('connection', (ws) => {
+    sckt = ws
+    socketSend('console', 'hello client')
+    console.log('socket open')
+    ws.on('message', (evt) => {
+        socketRecv(evt)
+    })
 })
 
-// put state
-exp.put('/put/:moduleId', (req, res) => {
-
+// through this window
+http.listen(8080, () => {
+    console.log('listening on 8080')
 })
 
-// link or unlink modules
-exp.put('/:link/:moduleId/:output/:moduleId/:input', (req, res) => {
 
-})
 
-exp.listen(8080, () => console.log("listening on 8080"))
+function buildMenu (){
+    var tree = {} 
+    var dir = fs.readdirSync('./src')
+    for(i in dir){
+        tree[dir[i]] = {}
+        var subdir = fs.readdirSync('./src/' + dir[i])
+        for(j in subdir){
+            // find js files
+            if(subdir[j].slice(-3) === '.js'){
+                var obj = {}
+                obj.path = './src/' + dir[i] + '/' + subdir[j]
+                tree[dir[i]][subdir[j].slice(0, -3)] = obj
+            }
+        }
+    }
+    
+    return tree
+}
 
 // put
\ No newline at end of file
diff --git a/src/motion/planner.js b/src/motion/planner.js
new file mode 100644
index 0000000000000000000000000000000000000000..ecf537333ed4ba701cc2e09fe57156754130c77c
--- /dev/null
+++ b/src/motion/planner.js
@@ -0,0 +1,88 @@
+// boilerplate atkapi header
+const InOut = require('./lib/inout.js')
+let Input = InOut.Input
+let Output = InOut.Output
+
+function Gcode() {
+
+    // state
+    this.state = {
+    	mode: 'G0',
+    	speeds: {
+    		G0: 1200,
+    		G1: 400
+    	}
+    }
+
+    // local functions
+    var getKeyValues = (str) => {
+    	var kv = {}
+        for (var i = 0; i < str.length; i++) {
+            if (str[i].match('[A-Za-z]')) { // regex to match upper case letters
+                var lastIndex = str.indexOf(' ', i)
+                if (lastIndex < 0) {
+                    lastIndex = str.length
+                }
+                var key = str[i].toUpperCase()
+                kv[key] = parseFloat(str.slice(i + 1, lastIndex))
+            }
+        }
+        return kv
+    }
+
+    var parseGcode = (str) => {
+    	var instruction = {
+    		position: {},
+    		hasMove: false,
+    		speed: 0
+    	}
+
+    	kv = getKeyValues(str)
+    	// track modality
+    	if(kv.G == 0 | kv.G == 1){
+    		this.state.mode = 'G' + kv.G.toString()
+    	} else if (kv.G != null) {
+    		// no arcs pls
+    		console.log('unfriendly Gcode mode!', kv)
+    	}
+
+    	for(key in kv){
+    		if(key.match('[A-EX-Z]')){
+    			instruction.position[key] = kv[key]
+    			instruction.hasMove = true
+    		} else if (key.match('[F]')){
+    			this.state.speeds[this.state.mode] = kv.F
+    		}
+    	}
+
+    	instruction.speed = this.state.speeds[this.state.mode]
+    	// and this for help later?
+    	instruction.kv = kv
+
+    	return instruction
+    }
+
+    // input functions
+    var lineIn = (str) => {
+    	var instruction = parseGcode(str)
+    	if (instruction.hasMove){
+    		this.outputs.instructionOut.emit(instruction)
+    	} else {
+    		this.outputs.modeChange.emit(this.state.mode)
+    	}
+    }
+
+    // ins and outs
+    this.inputs = {
+    	lineIn: new Input('string input', 'string', lineIn)
+    }
+
+    this.outputs = {
+    	instructionOut: new Output('move instruction', 'object'),
+    	modeChange: new Output('mode change', 'string')
+    }
+}
+
+
+// export the module 
+module.exports = Gcode
\ No newline at end of file
diff --git a/lib/gcode.js b/src/parsing/gcode.js
similarity index 97%
rename from lib/gcode.js
rename to src/parsing/gcode.js
index 55e86307e67c85938f94f4e874bcc050407899bf..4a38f1e940830aae561c91f1ae2af37527ecae84 100644
--- a/lib/gcode.js
+++ b/src/parsing/gcode.js
@@ -1,5 +1,5 @@
 // boilerplate atkapi header
-const InOut = require('./inout.js')
+const InOut = require('../../lib/inout.js')
 let Input = InOut.Input
 let Output = InOut.Output
 
diff --git a/src/ui/panel.js b/src/ui/panel.js
new file mode 100644
index 0000000000000000000000000000000000000000..99f080fcf410e98cb0bdbecaffd0b67304862a66
--- /dev/null
+++ b/src/ui/panel.js
@@ -0,0 +1,43 @@
+// boilerplate atkapi header
+const InOut = require('../../lib/inout.js')
+let Input = InOut.Input
+let Output = InOut.Output
+
+// bonus reqs
+const readline = require('readline')
+
+// a constructor, a fn, a javascript mess
+function Panel(){
+
+	// object state
+	this.state = {
+		width: 64,
+		height: 48
+	}
+
+	// natural inputs / local functions
+	var rlInterface = readline.createInterface({
+		input: process.stdin,
+		output: process.stdout
+	})
+
+	rlInterface.on('line', (data) => {
+		this.outputs.lineOut.emit(data)
+	})
+
+	var post = (str) => {
+		console.log(str)
+	}
+
+	// ins and outs
+	this.inputs = {
+		lineIn: new Input('line input', 'string', post)
+	}
+
+	this.outputs = {
+		lineOut: new Output('line output', 'string')
+	}
+}
+
+// exports 
+module.exports = Panel
\ No newline at end of file
diff --git a/lib/terminal.js b/src/ui/terminal.js
similarity index 90%
rename from lib/terminal.js
rename to src/ui/terminal.js
index 84279e22e18181488a21618658e34b850d1f5fa8..5e445a9a31c1dd51bfcf1b976c1f926bed16c13d 100644
--- a/lib/terminal.js
+++ b/src/ui/terminal.js
@@ -1,5 +1,5 @@
 // boilerplate atkapi header
-const InOut = require('./inout.js')
+const InOut = require('../../lib/inout.js')
 let Input = InOut.Input
 let Output = InOut.Output
 
@@ -12,7 +12,8 @@ function Terminal(){
 	// object state
 	this.state = {
 		width: 64,
-		height: 48
+		height: 48,
+		text: 'one line'
 	}
 
 	// natural inputs / local functions