diff --git a/files.html b/files.html
index fe08aa44e3d175c3130a58a130eaa9333b732359..c53497cd89c57b44d79382584dde955fb3730d3e 100644
--- a/files.html
+++ b/files.html
@@ -147,6 +147,22 @@
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/object/set'>set</a><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/object/string'>string</a><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/object/view'>view</a><br>
+<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;path</i><br>
+<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;formats</i><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/path/formats/dxf'>dxf</a><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/path/formats/g-code'>g-code</a><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/path/formats/svg'>svg</a><br>
+<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;machines</i><br>
+<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Roland</i><br>
+<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;milling</i><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/path/machines/Roland/milling/MDX-20'>MDX-20</a><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/path/machines/Roland/milling/SRM-20'>SRM-20</a><br>
+<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vinyl cutter</i><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/path/machines/Roland/vinyl%20cutter/GX-24'>GX-24</a><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/path/machines/ShopBot'>ShopBot</a><br>
+<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;laser cutter</i><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/path/machines/laser%20cutter/Epilog'>Epilog</a><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/path/view'>view</a><br>
 <i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;processes</i><br>
 <i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cut</i><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/processes/cut/raster'>raster</a><br>
@@ -171,21 +187,6 @@
 <i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string</i><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/string/format'>format</a><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/string/variables'>variables</a><br>
-<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;toolpath</i><br>
-<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;formats</i><br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/toolpath/formats/dxf'>dxf</a><br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/toolpath/formats/g-code'>g-code</a><br>
-<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;machines</i><br>
-<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Roland</i><br>
-<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;milling</i><br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/toolpath/machines/Roland/milling/MDX-20'>MDX-20</a><br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/toolpath/machines/Roland/milling/SRM-20'>SRM-20</a><br>
-<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vinyl cutter</i><br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/toolpath/machines/Roland/vinyl%20cutter/GX-24'>GX-24</a><br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/toolpath/machines/ShopBot'>ShopBot</a><br>
-<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;laser cutter</i><br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/toolpath/machines/laser%20cutter/Epilog'>Epilog</a><br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/toolpath/view'>view</a><br>
 <i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ui</i><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/ui/bar%20graph'>bar graph</a><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/ui/button%20window'>button window</a><br>
diff --git a/modules/index.js b/modules/index.js
index db95be7ad8060621ec6faf0e438092f1fc636c72..7cc0da1ceac3425c5506123e84000d891de56a8b 100644
--- a/modules/index.js
+++ b/modules/index.js
@@ -117,6 +117,22 @@ module_menu('   download','modules/object/download')
 module_menu('   set','modules/object/set')
 module_menu('   string','modules/object/string')
 module_menu('   view','modules/object/view')
+module_label('path')
+module_label('   formats')
+module_menu('      dxf','modules/path/formats/dxf')
+module_menu('      g-code','modules/path/formats/g-code')
+module_menu('      svg','modules/path/formats/svg')
+module_label('   machines')
+module_label('      Roland')
+module_label('         milling')
+module_menu('            MDX-20','modules/path/machines/Roland/milling/MDX-20')
+module_menu('            SRM-20','modules/path/machines/Roland/milling/SRM-20')
+module_label('         vinyl cutter')
+module_menu('            GX-24','modules/path/machines/Roland/vinyl%20cutter/GX-24')
+module_menu('      ShopBot','modules/path/machines/ShopBot')
+module_label('      laser cutter')
+module_menu('         Epilog','modules/path/machines/laser%20cutter/Epilog')
+module_menu('   view','modules/path/view')
 module_label('processes')
 module_label('   cut')
 module_menu('      raster','modules/processes/cut/raster')
@@ -141,21 +157,6 @@ module_menu('   websocket','modules/socket/websocket')
 module_label('string')
 module_menu('   format','modules/string/format')
 module_menu('   variables','modules/string/variables')
-module_label('toolpath')
-module_label('   formats')
-module_menu('      dxf','modules/toolpath/formats/dxf')
-module_menu('      g-code','modules/toolpath/formats/g-code')
-module_label('   machines')
-module_label('      Roland')
-module_label('         milling')
-module_menu('            MDX-20','modules/toolpath/machines/Roland/milling/MDX-20')
-module_menu('            SRM-20','modules/toolpath/machines/Roland/milling/SRM-20')
-module_label('         vinyl cutter')
-module_menu('            GX-24','modules/toolpath/machines/Roland/vinyl%20cutter/GX-24')
-module_menu('      ShopBot','modules/toolpath/machines/ShopBot')
-module_label('      laser cutter')
-module_menu('         Epilog','modules/toolpath/machines/laser%20cutter/Epilog')
-module_menu('   view','modules/toolpath/view')
 module_label('ui')
 module_menu('   bar graph','modules/ui/bar%20graph')
 module_menu('   button window','modules/ui/button%20window')
diff --git a/modules/path/formats/dxf b/modules/path/formats/dxf
new file mode 100644
index 0000000000000000000000000000000000000000..8fb7fb330e2f666224af4acd61b8e69005c5e679
--- /dev/null
+++ b/modules/path/formats/dxf
@@ -0,0 +1,279 @@
+//
+// path to DXF
+//
+// Neil Gershenfeld 
+// (c) Massachusetts Institute of Technology 2018
+// 
+// This work may be reproduced, modified, distributed, performed, and 
+// displayed for any purpose, but must acknowledge the mods
+// project. Copyright is retained and must be preserved. The work is 
+// provided as is; no warranty is provided, and users accept all 
+// liability.
+//
+// closure
+//
+(function(){
+//
+// module globals
+//
+var mod = {}
+//
+// name
+//
+var name = 'path to DXF (unfinished)'
+//
+// initialization
+//
+var init = function() {
+   mod.cutspeed.value = 20
+   mod.plungespeed.value = 20
+   mod.jogspeed.value = 75
+   mod.jogheight.value = 5
+   mod.spindlespeed.value = 10000
+   mod.tool.value = 1
+   mod.coolanton.checked = true   
+   }
+//
+// inputs
+//
+var inputs = {
+   path:{type:'',
+      event:function(evt){
+         mod.name = evt.detail.name
+         mod.path = evt.detail.path
+         mod.dpi = evt.detail.dpi
+         mod.width = evt.detail.width
+         mod.height = evt.detail.height
+         make_path()
+         }}}
+//
+// outputs
+//
+var outputs = {
+   file:{type:'',
+      event:function(str){
+         obj = {}
+         obj.name = mod.name+".nc"
+         obj.contents = str
+         mods.output(mod,'file',obj)
+         }}}
+//
+// interface
+//
+var interface = function(div){
+   mod.div = div
+   //
+   // cut speed
+   //
+   div.appendChild(document.createTextNode('cut speed: '))
+   var input = document.createElement('input')
+      input.type = 'text'
+      input.size = 6
+      div.appendChild(input)
+      mod.cutspeed = input
+   div.appendChild(document.createTextNode(' (mm/s)'))
+   div.appendChild(document.createElement('br'))
+   //
+   // plunge speed
+   //
+   div.appendChild(document.createTextNode('plunge speed: '))
+   var input = document.createElement('input')
+      input.type = 'text'
+      input.size = 6
+      div.appendChild(input)
+      mod.plungespeed = input
+   div.appendChild(document.createTextNode(' (mm/s)'))
+   div.appendChild(document.createElement('br'))
+   //
+   // jog speed
+   //
+   div.appendChild(document.createTextNode('jog speed: '))
+   var input = document.createElement('input')
+      input.type = 'text'
+      input.size = 6
+      div.appendChild(input)
+      mod.jogspeed = input
+   div.appendChild(document.createTextNode(' (mm/s)'))
+   div.appendChild(document.createElement('br'))
+   //
+   // jog height
+   //
+   div.appendChild(document.createTextNode('jog height: '))
+   var input = document.createElement('input')
+      input.type = 'text'
+      input.size = 6
+      div.appendChild(input)
+      mod.jogheight = input
+   div.appendChild(document.createTextNode(' (mm)'))
+   div.appendChild(document.createElement('br'))
+   //
+   // spindle speed
+   //
+   div.appendChild(document.createTextNode('spindle speed: '))
+   var input = document.createElement('input')
+      input.type = 'text'
+      input.size = 6
+      div.appendChild(input)
+      mod.spindlespeed = input
+   div.appendChild(document.createTextNode(' (RPM)'))
+   div.appendChild(document.createElement('br'))
+   //
+   // tool
+   //
+   div.appendChild(document.createTextNode('tool: '))
+   var input = document.createElement('input')
+      input.type = 'text'
+      input.size = 6
+      div.appendChild(input)
+      mod.tool = input
+   div.appendChild(document.createElement('br'))
+   //
+   // coolant
+   //
+   div.appendChild(document.createTextNode('coolant:'))
+   var input = document.createElement('input')
+      input.type = 'radio'
+      input.name = mod.div.id+'coolant'
+      input.id = mod.div.id+'coolanton'
+      div.appendChild(input)
+      mod.coolanton = input
+   div.appendChild(document.createTextNode('on'))
+   var input = document.createElement('input')
+      input.type = 'radio'
+      input.name = mod.div.id+'coolant'
+      input.id = mod.div.id+'coolantoff'
+      div.appendChild(input)
+      mod.coolantoff = input
+   div.appendChild(document.createTextNode('off'))
+   }
+//
+// local functions
+//
+function make_path() {
+   /*
+   var units = 1/25.4
+   var dx = mod.width/mod.dpi
+   var nx = mod.width
+   var scale = dx/(nx-1)
+   str = "999\nDXF written by mods\n"
+   str += "0\nSECTION\n"
+   str += "2\nHEADER\n"
+   str += "9\n$ACADVER\n1\nAC1009\n"
+   str += "9\n$EXTMIN\n"
+   str += "10\n%f\n",units*v->xmin
+   str += "20\n%f\n",units*v->ymin
+   if (v->path->dof == 3)
+      str += "30\n%f\n",units*(v->zmin)
+   str += "9\n$EXTMAX\n"
+   str += "10\n%f\n",units*(v->xmin+v->dx)
+   str += "20\n%f\n",units*(v->ymin+v->dy)
+   if (v->path->dof == 3)
+      str += "30\n%f\n",units*(v->zmin+v->dz)
+   str += "0\nENDSEC\n"
+   str += "0\nSECTION\n"
+   str += "2\nTABLES\n"
+   str += "0\nTABLE\n"
+   str += "2\nLTYPE\n70\n1\n"
+   str += "0\nLTYPE\n"
+   str += "2\nCONTINUOUS\n"
+   str += "70\n64\n3\n"
+   str += "Solid line\n"
+   str += "72\n65\n73\n0\n40\n0.000000\n"
+   str += "0\nENDTAB\n"
+   str += "0\nTABLE\n2\nLAYER\n70\n1\n"
+   str += "0\nLAYER\n2\ndefault\n70\n64\n62\n7\n6\n"
+   str += "CONTINUOUS\n0\nENDTAB\n"
+   str += "0\nENDSEC\n"
+   str += "0\nSECTION\n"
+   str += "2\nBLOCKS\n"
+   str += "0\nENDSEC\n"
+   str += "0\nSECTION\n"
+   str += "2\nENTITIES\n"
+   //
+   // follow segments
+   //
+   for (var seg = 0; seg < mod.path.length; ++seg) {
+
+      x = v->path->segment->point->first->value;
+      y = v->ny - v->path->segment->point->first->next->value;
+      if (v->path->dof == 3)
+         z = v->path->segment->point->first->next->next->value;
+      x0 = units*(v->xmin+scale*x);
+      y0 = units*(v->ymin+scale*y);
+      if (v->path->dof == 3)
+         z0 = units*(v->zmin+scale*z);
+
+      //
+      // move up to starting point
+      //
+      x = scale*mod.path[seg][0][0]
+      y = scale*mod.path[seg][0][1]
+      str += "Z"+jog_height.toFixed(4)+"\n"
+      str += "G00X"+x.toFixed(4)+"Y"+y.toFixed(4)+"Z"+jog_height.toFixed(4)+"\n"
+      //
+      // move down
+      //
+      z = scale*mod.path[seg][0][2]
+      str += "G01Z"+z.toFixed(4)+" F"+plunge_speed.toFixed(4)+"\n"
+      str += "F"+cut_speed.toFixed(4)+"\n" //restore xy feed rate
+
+      //
+      // follow points
+      //
+      for (var pt = 1; pt < mod.path[seg].length; ++pt) {
+      
+         x = v->path->segment->point->first->value;
+         y = v->ny - v->path->segment->point->first->next->value;
+         if (v->path->dof == 3)
+            z = v->path->segment->point->first->next->next->value;
+         x1 = units*(v->xmin+scale*x);
+         y1 = units*(v->ymin+scale*y);
+         if (v->path->dof == 3)
+            z1 = units*(v->zmin+scale*z);
+         str += "0\nLINE\n"
+         str += "10\n%f\n",x0
+         str += "20\n%f\n",y0
+         if (v->path->dof == 3)
+            str += "30\n%f\n",z0
+         str += "11\n%f\n",x1
+         str += "21\n%f\n",y1
+         if (v->path->dof == 3)
+            str += "31\n%f\n",z1
+         x0 = x1;
+         y0 = y1;
+         if (v->path->dof == 3)
+            z0 = z1;
+            
+         //
+         // move to next point
+         //
+         x = scale*mod.path[seg][pt][0]
+         y = scale*mod.path[seg][pt][1]
+         z = scale*mod.path[seg][pt][2]
+         str += "G01X"+x.toFixed(4)+"Y"+y.toFixed(4)+"Z"+z.toFixed(4)+"\n"
+
+         }
+      }
+   //
+   // finish
+   //
+   str += "0\nENDSEC\n"
+   str += "0\nEOF\n"
+   //
+   // output file
+   //
+   outputs.file.event(str)
+   */
+   }
+//
+// return values
+//
+return ({
+   mod:mod,
+   name:name,
+   init:init,
+   inputs:inputs,
+   outputs:outputs,
+   interface:interface
+   })
+}())
diff --git a/modules/path/formats/g-code b/modules/path/formats/g-code
index 6eb468269ee6b744ae682398f943f83cac0467e3..7364b012ceb257ef94f38b34f7fe5e4dff8f1529 100644
--- a/modules/path/formats/g-code
+++ b/modules/path/formats/g-code
@@ -1,8 +1,8 @@
 //
-// g-code
+// path to G-code
 //
 // Neil Gershenfeld 
-// (c) Massachusetts Institute of Technology 2017
+// (c) Massachusetts Institute of Technology 2018
 // 
 // This work may be reproduced, modified, distributed, performed, and 
 // displayed for any purpose, but must acknowledge the mods
@@ -20,7 +20,7 @@ var mod = {}
 //
 // name
 //
-var name = 'G-code'
+var name = 'path to G-code'
 //
 // initialization
 //
diff --git a/modules/path/formats/svg b/modules/path/formats/svg
new file mode 100644
index 0000000000000000000000000000000000000000..d07ae8096b69b1336802181c57664ad7ec3653a7
--- /dev/null
+++ b/modules/path/formats/svg
@@ -0,0 +1,232 @@
+//
+// path to SVG
+//
+// Neil Gershenfeld 
+// (c) Massachusetts Institute of Technology 2018
+// 
+// This work may be reproduced, modified, distributed, performed, and 
+// displayed for any purpose, but must acknowledge the mods
+// project. Copyright is retained and must be preserved. The work is 
+// provided as is; no warranty is provided, and users accept all 
+// liability.
+//
+// closure
+//
+(function(){
+//
+// module globals
+//
+var mod = {}
+//
+// name
+//
+var name = 'path to SVG (unfinished)'
+//
+// initialization
+//
+var init = function() {
+   mod.cutspeed.value = 20
+   mod.plungespeed.value = 20
+   mod.jogspeed.value = 75
+   mod.jogheight.value = 5
+   mod.spindlespeed.value = 10000
+   mod.tool.value = 1
+   mod.coolanton.checked = true   
+   }
+//
+// inputs
+//
+var inputs = {
+   path:{type:'',
+      event:function(evt){
+         mod.name = evt.detail.name
+         mod.path = evt.detail.path
+         mod.dpi = evt.detail.dpi
+         mod.width = evt.detail.width
+         mod.height = evt.detail.height
+         make_path()
+         }}}
+//
+// outputs
+//
+var outputs = {
+   file:{type:'',
+      event:function(str){
+         obj = {}
+         obj.name = mod.name+".nc"
+         obj.contents = str
+         mods.output(mod,'file',obj)
+         }}}
+//
+// interface
+//
+var interface = function(div){
+   mod.div = div
+   //
+   // cut speed
+   //
+   div.appendChild(document.createTextNode('cut speed: '))
+   var input = document.createElement('input')
+      input.type = 'text'
+      input.size = 6
+      div.appendChild(input)
+      mod.cutspeed = input
+   div.appendChild(document.createTextNode(' (mm/s)'))
+   div.appendChild(document.createElement('br'))
+   //
+   // plunge speed
+   //
+   div.appendChild(document.createTextNode('plunge speed: '))
+   var input = document.createElement('input')
+      input.type = 'text'
+      input.size = 6
+      div.appendChild(input)
+      mod.plungespeed = input
+   div.appendChild(document.createTextNode(' (mm/s)'))
+   div.appendChild(document.createElement('br'))
+   //
+   // jog speed
+   //
+   div.appendChild(document.createTextNode('jog speed: '))
+   var input = document.createElement('input')
+      input.type = 'text'
+      input.size = 6
+      div.appendChild(input)
+      mod.jogspeed = input
+   div.appendChild(document.createTextNode(' (mm/s)'))
+   div.appendChild(document.createElement('br'))
+   //
+   // jog height
+   //
+   div.appendChild(document.createTextNode('jog height: '))
+   var input = document.createElement('input')
+      input.type = 'text'
+      input.size = 6
+      div.appendChild(input)
+      mod.jogheight = input
+   div.appendChild(document.createTextNode(' (mm)'))
+   div.appendChild(document.createElement('br'))
+   //
+   // spindle speed
+   //
+   div.appendChild(document.createTextNode('spindle speed: '))
+   var input = document.createElement('input')
+      input.type = 'text'
+      input.size = 6
+      div.appendChild(input)
+      mod.spindlespeed = input
+   div.appendChild(document.createTextNode(' (RPM)'))
+   div.appendChild(document.createElement('br'))
+   //
+   // tool
+   //
+   div.appendChild(document.createTextNode('tool: '))
+   var input = document.createElement('input')
+      input.type = 'text'
+      input.size = 6
+      div.appendChild(input)
+      mod.tool = input
+   div.appendChild(document.createElement('br'))
+   //
+   // coolant
+   //
+   div.appendChild(document.createTextNode('coolant:'))
+   var input = document.createElement('input')
+      input.type = 'radio'
+      input.name = mod.div.id+'coolant'
+      input.id = mod.div.id+'coolanton'
+      div.appendChild(input)
+      mod.coolanton = input
+   div.appendChild(document.createTextNode('on'))
+   var input = document.createElement('input')
+      input.type = 'radio'
+      input.name = mod.div.id+'coolant'
+      input.id = mod.div.id+'coolantoff'
+      div.appendChild(input)
+      mod.coolantoff = input
+   div.appendChild(document.createTextNode('off'))
+   }
+//
+// local functions
+//
+function make_path() {
+   var dx = mod.width/mod.dpi
+   var nx = mod.width
+   var scale = dx/(nx-1)
+   var cut_speed = parseFloat(mod.cutspeed.value)/25.4
+   var plunge_speed = parseFloat(mod.plungespeed.value)/25.4
+   var jog_speed = parseFloat(mod.jogspeed.value)/25.4
+   var jog_height = parseFloat(mod.jogheight.value)/25.4
+   var spindle_speed = parseFloat(mod.spindlespeed.value)
+   var tool = parseInt(mod.tool.value)
+   str = "%\n" // tape start
+   str += "G17\n" // xy plane
+   str += "G20\n" // inches
+   str += "G40\n" // cancel tool radius compensation
+   str += "G49\n" // cancel tool length compensation
+   str += "G54\n" // coordinate system 1
+   str += "G80\n" // cancel canned cycles
+   str += "G90\n" // absolute coordinates
+   str += "G94\n" // feed/minute units
+   str += "T"+tool+"M06\n" // tool selection, tool change
+   str += "F"+cut_speed.toFixed(4)+"\n" // feed rate
+   str += "S"+spindle_speed+"\n" // spindle speed
+   if (mod.coolanton.checked)
+      str += "M08\n" // coolant on
+   str += "G00Z"+jog_height.toFixed(4)+"\n" // move up before starting spindle
+   str += "M03\n" // spindle on clockwise
+   str += "G04 P1\n" // give spindle 1 second to spin up
+   //
+   // follow segments
+   //
+   for (var seg = 0; seg < mod.path.length; ++seg) {
+      //
+      // move up to starting point
+      //
+      x = scale*mod.path[seg][0][0]
+      y = scale*mod.path[seg][0][1]
+      str += "Z"+jog_height.toFixed(4)+"\n"
+      str += "G00X"+x.toFixed(4)+"Y"+y.toFixed(4)+"Z"+jog_height.toFixed(4)+"\n"
+      //
+      // move down
+      //
+      z = scale*mod.path[seg][0][2]
+      str += "G01Z"+z.toFixed(4)+" F"+plunge_speed.toFixed(4)+"\n"
+      str += "F"+cut_speed.toFixed(4)+"\n" //restore xy feed rate
+      for (var pt = 1; pt < mod.path[seg].length; ++pt) {
+         //
+         // move to next point
+         //
+         x = scale*mod.path[seg][pt][0]
+         y = scale*mod.path[seg][pt][1]
+         z = scale*mod.path[seg][pt][2]
+         str += "G01X"+x.toFixed(4)+"Y"+y.toFixed(4)+"Z"+z.toFixed(4)+"\n"
+         }
+      }
+   //
+   // finish
+   //
+   str += "G00Z"+jog_height.toFixed(4)+"\n" // move up before stopping spindle
+   str += "M05\n" // spindle stop
+   if (mod.coolanton.checked)
+      str += "M09\n" // coolant off
+   str += "M30\n" // program end and reset
+   str += "%\n" // tape end
+   //
+   // output file
+   //
+   outputs.file.event(str)
+   }
+//
+// return values
+//
+return ({
+   mod:mod,
+   name:name,
+   init:init,
+   inputs:inputs,
+   outputs:outputs,
+   interface:interface
+   })
+}())
+