diff --git a/paprika.cabal b/paprika.cabal
--- a/paprika.cabal
+++ b/paprika.cabal
@@ -1,5 +1,5 @@
 name:                paprika
-version:             0.1.0.0
+version:             0.1.0.1
 synopsis:            The Haskell library and examples for the kids programming robot paprika
 description:         Please see README.md
 homepage:            https://github.com/mitsuji/paprika#readme
@@ -11,8 +11,20 @@
 category:            System
 build-type:          Simple
 cabal-version:       >=1.10
--- extra-source-files:
-
+extra-source-files:
+  static/ctrl/default.htm
+  static/ctrl/default.js
+  static/ctrl/default.css
+  static/ctrl/qr.htm
+  static/ctrl/qr.js
+  static/cutter/viewer.htm
+  static/cutter/viewer.js
+  static/cutter/viewer.css
+  static/cutter/reporter.htm
+  static/cutter/reporter.js
+  static/cutter/qr.htm
+  static/cutter/qr.js
+  
 library
   hs-source-dirs:      src
   exposed-modules:     System.Paprika
diff --git a/static/ctrl/default.css b/static/ctrl/default.css
new file mode 100644
--- /dev/null
+++ b/static/ctrl/default.css
@@ -0,0 +1,25 @@
+table.ctrl-table {
+    margin-left: auto;
+    margin-right: auto;
+}
+
+table.ctrl-table tr td {
+    padding: 10px 10px 10px 10px;
+}
+
+table.ctrl-table tr td input[type="button"] {
+    width: 50px;
+    height: 50px;
+    font-size: 2em;
+}
+
+table.arm-table {
+    margin-left: auto;
+    margin-right: auto;
+    margin-bottom: 20px;
+}
+
+table.arm-table tr td {
+    padding: 0px 20px 0px 20px;
+}
+
diff --git a/static/ctrl/default.htm b/static/ctrl/default.htm
new file mode 100644
--- /dev/null
+++ b/static/ctrl/default.htm
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8"/>
+    <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no, minimum-scale=1.0,maximum-scale=1.0" />
+    <title>ctrl</title>
+    <script src="./default.js"></script>
+    <link rel="stylesheet" href="./default.css"/>
+  </head>
+  <body>
+    <h2 id="title">ctrl</h2>
+    <form>
+      <table class="arm-table">
+	<tr>
+	  <td>
+	    <input type="range"  step="1" min="-1" max="1" id="al"/>
+	  </td>
+	  <td>
+	    <input type="range"  step="1" min="-1" max="1" id="ar"/>
+	  </td>
+	</tr>
+      </table>
+      <table class="ctrl-table">
+	<tr>
+	  <td>
+	    <input type="button" id="fl" value="!|">
+	  </td>
+	  <td>
+	    <input type="button" id="f" value="||">
+	  </td>
+	  <td>
+	    <input type="button" id="fr" value="|!">
+	  </td>
+	</tr>
+	<tr>
+	  <td>
+	    <input type="button" id="tl" value="&amp;|">
+	  </td>
+	  <td>
+	    <input type="button" id="s" value="!!">
+	  </td>
+	  <td>
+	    <input type="button" id="tr" value="|&amp;">
+	  </td>
+	</tr>
+	<tr>
+	  <td>
+	    <input type="button" id="bl" value="!&amp;">
+	  </td>
+	  <td>
+	    <input type="button" id="b" value="&amp;&amp;">
+	  </td>
+	  <td>
+	    <input type="button" id="br" value="&amp;!">
+	  </td>
+	</tr>
+      </table>
+    </form>
+  </body>
+</html>
diff --git a/static/ctrl/default.js b/static/ctrl/default.js
new file mode 100644
--- /dev/null
+++ b/static/ctrl/default.js
@@ -0,0 +1,68 @@
+window.addEventListener( 'load', function(event){
+
+    var commands = new Array('s','f','b','fl','fr','bl','br','tl','tr');
+    var ws = new WebSocket('ws://' + window.location.host + '/default');
+    
+    document.getElementById('title').style.background = '#FF0000';
+    ws.onopen = function() {
+	document.getElementById('title').style.background = '#00FF00';
+    };
+	
+    ws.onclose = function(event) {
+	document.getElementById('title').style.background = '#FF0000';
+    };
+	
+    ws.onmessage = function(event) {
+	console.log('onmessage: ' + event.data);
+	var json = JSON.parse(event.data);
+	if(json.type === 'command') {
+	    if (json.name === 'al') {
+		document.getElementById('al').value = json.level;
+	    } else if(json.name === 'ar') {
+		document.getElementById('ar').value = json.level;
+	    } else {
+	    for(var i = 0; i < commands.length; i++) {
+		var cmd = commands[i];
+		var elem = document.getElementById(cmd);
+		if(cmd === json.name){
+		    elem.style.background = '#FF9090';
+		}else{
+		    elem.style.background = '';
+		}
+	    }
+	    }
+	}
+    };
+
+    function clickListenerGen(cmd){
+	var listener = function(event) {
+	    var data = { type: 'command', name: cmd};
+	    var json = JSON.stringify(data);
+	    ws.send(json);
+	}
+	return listener;
+    }
+    
+    for(var i = 0; i < commands.length; i++) {
+	var cmd = commands[i];
+	document.getElementById(cmd).addEventListener('click', clickListenerGen(cmd));	
+    }
+    
+
+    document.getElementById('al').addEventListener('change', function(event){
+	var lev  = parseInt(document.getElementById('al').value);
+	var data = { type: 'command', name: 'al', level: lev};
+	var json = JSON.stringify(data);
+	ws.send(json);
+    });
+    
+    document.getElementById('ar').addEventListener('change', function(event){
+	var lev  = parseInt(document.getElementById('ar').value);
+	var data = { type: 'command', name: 'ar', level: lev};
+	var json = JSON.stringify(data);
+	ws.send(json);
+    });	
+    
+}, false );
+
+
diff --git a/static/ctrl/qr.htm b/static/ctrl/qr.htm
new file mode 100644
--- /dev/null
+++ b/static/ctrl/qr.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8"/>
+    <title>qr code</title>
+    <script src="./qr.js"></script>
+  </head>
+  <body>
+
+    <h2>qr code</h2>
+    
+    <div>
+      <div id="rep-url"></div>
+      <img id="rep-qr" src=""/>
+    </div>
+    
+  </body>
+</html>
diff --git a/static/ctrl/qr.js b/static/ctrl/qr.js
new file mode 100644
--- /dev/null
+++ b/static/ctrl/qr.js
@@ -0,0 +1,9 @@
+window.addEventListener( 'load', function(event){
+    
+    var reporter_url = 'http://' + location.host + '/';
+    var reporter_qr_url = 'https://chart.googleapis.com/chart' + '?chs=300x300&cht=qr&chl=' + reporter_url;
+
+    document.getElementById('rep-url').innerHTML = reporter_url;
+    document.getElementById('rep-qr').setAttribute('src',reporter_qr_url);
+    
+}, false );
diff --git a/static/cutter/qr.htm b/static/cutter/qr.htm
new file mode 100644
--- /dev/null
+++ b/static/cutter/qr.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8"/>
+    <title>reporter qr code</title>
+    <script src="./qr.js"></script>
+  </head>
+  <body>
+
+    <h2>reporter qr code</h2>
+    
+    <div>
+      <div id="rep-url"></div>
+      <img id="rep-qr" src=""/>
+    </div>
+    
+  </body>
+</html>
diff --git a/static/cutter/qr.js b/static/cutter/qr.js
new file mode 100644
--- /dev/null
+++ b/static/cutter/qr.js
@@ -0,0 +1,9 @@
+window.addEventListener( 'load', function(event){
+    
+    var reporter_url = 'http://' + location.host + '/reporter.htm';
+    var reporter_qr_url = 'https://chart.googleapis.com/chart' + '?chs=300x300&cht=qr&chl=' + reporter_url;
+
+    document.getElementById('rep-url').innerHTML = reporter_url;
+    document.getElementById('rep-qr').setAttribute('src',reporter_qr_url);
+    
+}, false );
diff --git a/static/cutter/reporter.htm b/static/cutter/reporter.htm
new file mode 100644
--- /dev/null
+++ b/static/cutter/reporter.htm
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8"/>
+    <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no, minimum-scale=1.0,maximum-scale=1.0" />
+    <title>reporter</title>
+    <script src="./reporter.js"></script>
+  </head>
+  <body>
+    <h2 id="title">reporter</h2>
+    <form style="text-align:center;">
+      <input type="button" id="send-button" style="width:250px;height:250px;font-size:4em;"/>
+    </form>
+  </body>
+</html>
diff --git a/static/cutter/reporter.js b/static/cutter/reporter.js
new file mode 100644
--- /dev/null
+++ b/static/cutter/reporter.js
@@ -0,0 +1,36 @@
+window.addEventListener( 'load', function(event){
+
+    var ws = new WebSocket('ws://' + window.location.host + '/reporter');
+	
+    document.getElementById('title').style.background = '#FF0000';
+    ws.onopen = function() {
+	document.getElementById('title').style.background = '#00FF00';
+    };
+	
+    ws.onclose = function(event) {
+	document.getElementById('title').style.background = '#FF0000';
+    };
+	
+    ws.onmessage = function(event) {
+	console.log('onmessage: ' + event.data);
+	var json = JSON.parse(event.data);
+	if(json.type === 'side') {
+	    if(json.content === 'left'){
+		document.getElementById('send-button').value = 'Left';
+	    } else if(json.content === 'right') {
+		document.getElementById('send-button').value = 'Right';
+	    }
+	}
+    };
+
+    if ('ontouchend' in window) {
+	document.getElementById('send-button').addEventListener('touchend', function(event){
+	    ws.send('');
+	});
+    } else {
+	document.getElementById('send-button').addEventListener('click', function(event){
+	    ws.send('');
+	});
+    }    
+    
+}, false );
diff --git a/static/cutter/viewer.css b/static/cutter/viewer.css
new file mode 100644
--- /dev/null
+++ b/static/cutter/viewer.css
@@ -0,0 +1,37 @@
+html, body {
+    height: 100%;
+}
+
+
+table.hist-table {
+    width:  100%;
+    height: 80%;
+}
+
+
+tr.hist-caption {
+    height: 20px;
+}
+
+
+tr.hist-count {
+    height: 20px;
+}
+
+
+tr.hist-row {
+    height: 100%;
+}
+
+
+td.hist-cell {
+    vertical-align: bottom;
+}
+
+
+div.hist-div {
+    width:  100%;
+    background-color: #FF0000;
+}
+
+
diff --git a/static/cutter/viewer.htm b/static/cutter/viewer.htm
new file mode 100644
--- /dev/null
+++ b/static/cutter/viewer.htm
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8"/>
+    <title>viewer</title>
+    <script src="./viewer.js"></script>
+    <link rel="stylesheet" href="./viewer.css"/>
+  </head>
+  <body>
+    
+    <h2 id="title">viewer</h2>
+
+    <div>
+      threshold:
+      <button id="threshold-5">5</button>
+      <button id="threshold-10">10</button>
+      <button id="threshold-20">20</button>
+      <button id="threshold-40">40</button>
+      <button id="threshold-80">80</button>
+      <button id="threshold-100">100</button>
+      <button id="threshold-120">120</button>
+      <button id="threshold-140">140</button>
+    </div>
+    
+    <table class="hist-table">
+      <tr class="hist-caption">
+	<td id="left-members">0 members</td>
+	<td id="right-members">0 members</td>
+      </tr>
+      <tr class="hist-count">
+	<td id="left-counts">0 taps</td>
+	<td id="right-counts">0 taps</td>
+      </tr>
+      <tr class="hist-row">
+	<td class="hist-cell">
+	  <div id="left-hist" class="hist-div" style="height:0%;"></div>
+	</td>
+	<td class="hist-cell">
+	  <div id="right-hist" class="hist-div" style="height:0%;"></div>
+	</td>
+      </tr>
+    </table>
+    
+  </body>
+</html>
diff --git a/static/cutter/viewer.js b/static/cutter/viewer.js
new file mode 100644
--- /dev/null
+++ b/static/cutter/viewer.js
@@ -0,0 +1,74 @@
+window.addEventListener( 'load', function(event){
+
+    var thresholds = new Array(5,10,20,40,80,100,120,140);
+    var ws = new WebSocket('ws://' + window.location.host + '/viewer');
+    var current_threshold = 10;
+	
+    document.getElementById('title').style.background = '#FF0000';
+    ws.onopen = function() {
+	document.getElementById('title').style.background = '#00FF00';
+    };
+	
+    ws.onclose = function(event) {
+	document.getElementById('title').style.background = '#FF0000';
+    };
+	
+    ws.onmessage = function(event) {
+	console.log('onmessage: ' + event.data);
+	var json = JSON.parse(event.data);
+	if(json.type === 'freq') {
+	    var lc = json.content.left;
+	    var rc = json.content.right;
+	    document.getElementById('left-counts').innerHTML  = lc + ' taps';
+	    document.getElementById('right-counts').innerHTML = rc + ' taps';
+	    if( current_threshold <= lc ){
+		document.getElementById('left-hist').style.height = '100%';
+		document.getElementById('left-hist').style.background = '#00FF00';
+	    }else{
+		var h = Math.floor((lc / current_threshold) * 100);
+		console.log(h);
+		document.getElementById('left-hist').style.height = h + '%';
+		document.getElementById('left-hist').style.background = '#FF0000';
+	    }
+
+	    if( current_threshold <= rc ){
+		document.getElementById('right-hist').style.height = '100%';
+		document.getElementById('right-hist').style.background = '#00FF00';
+	    }else{
+		var h = Math.floor((rc / current_threshold) * 100);
+		console.log(h);
+		document.getElementById('right-hist').style.height = h + '%';
+		document.getElementById('right-hist').style.background = '#FF0000';
+	    }
+	    
+	} else if(json.type === 'members') {
+	    document.getElementById('left-members').innerHTML  = json.content.left + ' members';
+	    document.getElementById('right-members').innerHTML = json.content.right + ' members';
+	} else if(json.type === 'threshold') {
+	    current_threshold = json.content;
+	    for(var i = 0; i < thresholds.length; i++) {
+		var thr = thresholds[i];
+		var elem = document.getElementById('threshold-' + thr);
+		if(thr === json.content){
+		    elem.style.background = '#FF9090';
+		}else{
+		    elem.style.background = '';
+		}
+	    }
+	}
+    };
+
+
+    function clickHandlerGen(thr){
+	var handler = function(event) {
+	    ws.send(thr);
+	}
+	return handler;
+    }
+    
+    for(var i = 0; i < thresholds.length; i++) {
+	var thr = thresholds[i];
+	document.getElementById('threshold-' + thr).addEventListener('click', clickHandlerGen(thr));	
+    }
+    
+}, false );
