diff --git a/dependencies/THREE2STL.js b/dependencies/THREE2STL.js
index 3bb790948b8350ce896ccc0849d1dd93a95a904f..e63b0bb551c42bce888bd3deac52d3b1692594fc 100755
--- a/dependencies/THREE2STL.js
+++ b/dependencies/THREE2STL.js
@@ -1,86 +1,91 @@
-function stlFromGeometry( geometry, options ) {
-
-	// calculate the faces and normals if they are not yet present
-	geometry.computeFaceNormals()
-
-	var addX = 0
-	var addY = 0
-	var addZ = 0
-	var download = false
-
-	if ( options ) {
-		if ( options.useObjectPosition ) {
-			addX = geometry.mesh.position.x
-			addY = geometry.mesh.position.y
-			addZ = geometry.mesh.position.z
-		}
-
-		if ( options.download ) {
-			download = true
-		}
-	}
+function stlFromGeometry( geometryArray, options ) {
 
-	
-	var facetToStl = function( verts, normal ) {
-		var faceStl = ''
-		faceStl += 'facet normal ' + normal.x + ' ' + normal.y + ' ' +  normal.z + '\n'
-		faceStl += 'outer loop\n'
-
-		for ( var j = 0; j < 3; j++ ) {
-			var vert = verts[j]
-			faceStl += 'vertex ' + (vert.x+addX) + ' ' + (vert.y+addY) + ' ' + (vert.z+addZ) + '\n'
-		}
-
-		faceStl += 'endloop\n'
-		faceStl += 'endfacet\n'
-	
-		return faceStl
-	}
+    var addX = 0
+    var addY = 0
+    var addZ = 0
+    var download = false;
 
-	// start bulding the STL string
-	var stl = ''
-	stl += 'solid\n'
-	
-	for ( var i = 0; i < geometry.faces.length; i++ ) {
-		var face = geometry.faces[i]
-
-		// if we have just a griangle, that's easy. just write them to the file
-		if ( face.d === undefined ) {
-			var verts = [
-				geometry.vertices[ face.a ],
-				geometry.vertices[ face.b ],
-				geometry.vertices[ face.c ]
-			]
-
-			stl += facetToStl( verts, face.normal )
-
-		} else {
-			// if it's a quad, we need to triangulate it first
-			// split the quad into two triangles: abd and bcd
-			var verts = []
-			verts[0] = [
-				geometry.vertices[ face.a ],
-				geometry.vertices[ face.b ],
-				geometry.vertices[ face.d ]
-			]
-			verts[1] = [
-				geometry.vertices[ face.b ],
-				geometry.vertices[ face.c ],
-				geometry.vertices[ face.d ]
-			]
-			
-			for ( var k = 0; k<2; k++ ) {
-				stl += facetToStl( verts[k], face.normal )
-			}
-			
-		}
-	}
+    if ( options ) {
+//            if ( options.useObjectPosition ) {
+//                addX = geometry.mesh.position.x
+//                addY = geometry.mesh.position.y
+//                addZ = geometry.mesh.position.z
+//            }
+
+        if ( options.download ) {
+            download = true;
+        }
+    }
+
+    // start bulding the STL string
+    var stl = '';
+    stl += 'solid\n';
+
+    var facetToStl = function( verts, normal ) {
+        var faceStl = '';
+        faceStl += 'facet normal ' + normal.x + ' ' + normal.y + ' ' +  normal.z + '\n';
+        faceStl += 'outer loop\n';
+
+        for ( var j = 0; j < 3; j++ ) {
+            var vert = verts[j];
+            faceStl += 'vertex ' + (vert.x+addX) + ' ' + (vert.y+addY) + ' ' + (vert.z+addZ) + '\n';
+        }
+
+        faceStl += 'endloop\n';
+        faceStl += 'endfacet\n';
+
+        return faceStl;
+    };
+
+
+    for (var index=0;index<geometryArray.length;index++){
+
+        var geometry = geometryArray[index];
+//        geometry.computeFaceNormals();    // calculate the faces and normals if they are not yet present
+
+        console.log(geometry);
+
+        for ( var i = 0; i < geometry.faces.length; i++ ) {
+            var face = geometry.faces[i];
+
+            // if we have just a griangle, that's easy. just write them to the file
+            if ( face.d === undefined ) {
+                var verts = [
+                    geometry.vertices[ face.a ],
+                    geometry.vertices[ face.b ],
+                    geometry.vertices[ face.c ]
+                ];
+
+                stl += facetToStl( verts, face.normal );
+
+            } else {
+                // if it's a quad, we need to triangulate it first
+                // split the quad into two triangles: abd and bcd
+                var verts = [];
+                verts[0] = [
+                    geometry.vertices[ face.a ],
+                    geometry.vertices[ face.b ],
+                    geometry.vertices[ face.d ]
+                ];
+                verts[1] = [
+                    geometry.vertices[ face.b ],
+                    geometry.vertices[ face.c ],
+                    geometry.vertices[ face.d ]
+                ];
+
+                for ( var k = 0; k<2; k++ ) {
+                    stl += facetToStl( verts[k], face.normal );
+                }
+
+            }
+        }
+    }
 
-	stl += 'endsolid'
+	stl += 'endsolid';
 
 	if ( download ) {
-		document.location = 'data:Application/octet-stream, ' + encodeURIComponent( stl )
+		document.location = 'data:Application/octet-stream, ' + encodeURIComponent( stl );
 	}
 
-	return stl
+	return stl;
 }
diff --git a/index.html b/index.html
index 8808cde8e06689345557255bba57605f13feda37..404dc4db8eddbc7cd9ef7f6f62b5376296beeb26 100644
--- a/index.html
+++ b/index.html
@@ -83,6 +83,8 @@
                     </li>
                 </ul>
               </li>
+              <li class="divider"></li>
+              <li><a id="exportSTL" href="#">Export STL</a></li>
           </ul>
         </li>
         <li><a data-menu-id="navDesign" class="menuHoverControls" href="#">Design</a></li>
diff --git a/js/cells/DMACell.js b/js/cells/DMACell.js
index fc4230e20b8b0aa33061f0587d7e8c60e96722f1..4fd8903ef5db0bac224ccf454c50da6cdf13c847 100644
--- a/js/cells/DMACell.js
+++ b/js/cells/DMACell.js
@@ -349,6 +349,27 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'globals', '
         return this.superCell === null || this.superCell === undefined;
     };
 
+    DMACell.prototype.getVisibleGeometry = function(){//for save stl
+        var meshes = this.getVisibleMeshes();
+        var geometry = [];
+        _.each(meshes, function(mesh){
+            geometry.push(mesh.geometry);
+        });
+        return geometry;
+    };
+
+    DMACell.prototype.getVisibleMeshes = function(){
+        if (!this.object3D.visible) return [];
+        var meshes = _.filter(this.object3D.children, function(child){
+            return child.visible && child instanceof THREE.Mesh
+        });
+        if (meshes.length > 0) return meshes;
+        if (!this.cells) return [];
+        this._loopCells(function(cell){
+            if (cell) meshes = meshes.concat(cell.getVisibleMeshes());
+        });
+        return meshes;
+    };
 
 
 
diff --git a/js/main.js b/js/main.js
index 759a48870043d32ff3d4e6383026b4228702a030..8708ab9cc6e55cd7e8844ddc8d2af30d8d2d324c 100644
--- a/js/main.js
+++ b/js/main.js
@@ -23,6 +23,7 @@ require.config({
         three: '../dependencies/three',
         orbitControls: '../dependencies/OrbitControls',
         stlLoader: '../dependencies/loaders/STLLoader',
+        stlExport: '../dependencies/THREE2STL',
         threeModel: 'three/ThreeModel',
         threeView: 'three/ThreeView',
         fillGeometry: 'three/FillGeometry',
@@ -239,6 +240,9 @@ require.config({
             deps: ['three'],
             exports: 'THREE'
         },
+        stlExport: {
+            exports: 'stlFromGeometry'
+        },
         threeProjector: {
             deps: ['three'],
             exports: "THREE"
diff --git a/js/menus/Navbar.js b/js/menus/Navbar.js
index 7bc43847f9274762d0d94eec9b0c1f2d38b8e709..c102bb0984b68461ecb2e56acc4d4796cc155561 100644
--- a/js/menus/Navbar.js
+++ b/js/menus/Navbar.js
@@ -19,6 +19,7 @@ define(['jquery', 'underscore', 'backbone', 'fileSaver', 'navViewMenu', 'appStat
             "click .saveJSON":                                      "_save",
             "click .saveAsJSON":                                    "_saveAs",
 //            "change #saveAsFileName":                               "_saveAs",//detect enter key
+            "click #exportSTL":                                     "_saveSTL",
 
             "click .importJSON":                                    "_importJSON",
             "change #jsonInput":                                    "_selectJSONFiles",
@@ -122,6 +123,11 @@ define(['jquery', 'underscore', 'backbone', 'fileSaver', 'navViewMenu', 'appStat
             $('#saveAsModel').modal('hide');
         },
 
+        _saveSTL: function(e){
+            e.preventDefault();
+            fileSaver.saveSTL();
+        },
+
 
 
 
diff --git a/js/models/FileSaver.js b/js/models/FileSaver.js
index 500bf60a96b9ea2bf1a0d06a56c79455f5f2ca13..7ba3899cf0ff9409245e2771369c49d0a709198e 100644
--- a/js/models/FileSaver.js
+++ b/js/models/FileSaver.js
@@ -19,14 +19,14 @@ define(['underscore', 'fileSaverLib', 'lattice', 'materials', 'ribbon', 'menuWra
                 jsonString.replace(/\\"/g,"\uFFFF"); //U+ FFFF
                 jsonString = jsonString.replace(/\"([^"]+)\":/g,"$1:").replace(/\uFFFF/g,"\\\"");
                 var blob = new Blob([jsonString], {type: "text/plain;charset=utf-8"});
-                saveAs(blob, name + "-forAmanda" + extension);
+                saveAs(blob, name + "-forAmanda" + "." + extension);
             }
 //        });
     }
 
     function saveData(data, name, extension){
         var blob = new Blob([data], {type: "text/plain;charset=utf-8"});
-        saveAs(blob, name + extension);
+        saveAs(blob, name + "." + extension);
     }
 
 //    function save(name){
@@ -35,7 +35,7 @@ define(['underscore', 'fileSaverLib', 'lattice', 'materials', 'ribbon', 'menuWra
 //            lattice:_getLatticeDataToSave(),
 ////            assembler:_getAssemblerDataToSave()
 //        };
-//        _saveFile(data, name, ".json");
+//        _saveFile(data, name, "json");
 //    }
 
     function save(name){
@@ -44,7 +44,7 @@ define(['underscore', 'fileSaverLib', 'lattice', 'materials', 'ribbon', 'menuWra
             assembly:_getLatticeDataToSave(),
             materials:_getMaterialsDataToSave()
         };
-        _saveFile(data, name, ".json");
+        _saveFile(data, name, "json");
     }
 
     function saveAssembler(){
@@ -52,17 +52,17 @@ define(['underscore', 'fileSaverLib', 'lattice', 'materials', 'ribbon', 'menuWra
     }
 
     function saveSequences(seqArray, name){
-        _saveFile(seqArray, name || "seqs", ".txt", true);
+        _saveFile(seqArray, name || "seqs", "txt", true);
     }
 
     function saveMaterial(id, material){
         var data = {materials:{}};
         data.materials[id] = material || _getMaterialDataToSave(id);
-        _saveFile(data, data.materials[id].name, ".json");
+        _saveFile(data, data.materials[id].name, "json");
     }
 
     function saveMachineConfig(data){
-        _saveFile(data, "Machine Config", ".json");
+        _saveFile(data, "Machine Config", "json");
     }
 
     function _getAssemblerDataToSave(){
@@ -129,6 +129,18 @@ define(['underscore', 'fileSaverLib', 'lattice', 'materials', 'ribbon', 'menuWra
         object.trigger("change");
     }
 
+    function saveSTL(){
+        require(['stlExport'], function(stlFromGeometry){
+            //merge geometry first
+            var geoArray = [];
+            lattice.loopCells(function(cell){
+                if (cell) geoArray = geoArray.concat(cell.getVisibleGeometry());
+            });
+            var stlString = stlFromGeometry(geoArray);
+            saveData(stlString, "DMAssembly", "stl");
+        });
+    }
+
 
     return {//return public methods
 //        save: save,
@@ -138,6 +150,7 @@ define(['underscore', 'fileSaverLib', 'lattice', 'materials', 'ribbon', 'menuWra
         saveMachineConfig: saveMachineConfig,
 //        saveAssembler: saveAssembler,
         loadFile: loadFile,
-        saveSequences: saveSequences
+        saveSequences: saveSequences,
+        saveSTL: saveSTL
     }
 });
\ No newline at end of file
diff --git a/js/three/ThreeModel.js b/js/three/ThreeModel.js
index 031e7b0ba13cc919aa68c74e4af2ab8aaf8904f3..ba87d984f9cbc6f4e36140395d5fdb40ad64dd28 100644
--- a/js/three/ThreeModel.js
+++ b/js/three/ThreeModel.js
@@ -197,7 +197,7 @@ define(['underscore', 'three'], function(_, THREE){
             svgRenderer.render(scene, camera);
             var XMLS = new XMLSerializer();
             var svgfile = XMLS.serializeToString(svgRenderer.domElement);
-            fileSaver.saveData(svgfile, "screenshot", ".svg");
+            fileSaver.saveData(svgfile, "screenshot", "svg");
         })
     }