diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2014, Daniel Bergey
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Daniel Bergey nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/STL.cabal b/STL.cabal
new file mode 100644
--- /dev/null
+++ b/STL.cabal
@@ -0,0 +1,38 @@
+-- Initial STL.cabal generated by cabal init.  For further documentation, 
+-- see http://haskell.org/cabal/users-guide/
+
+name:                STL
+version:             0.1.0.0
+synopsis:            STL 3D geometry format parsing and pretty-printing
+description:         STL is a simple file format for representing 3D
+                     objects as the triangles which form their
+                     surface.  It is common in 3D printing workflows.
+
+                     This library provides parsing and serialization
+                     to the ASCII STL format.  The binary STL format
+                     is not yet supported.
+homepage:            http://github.com/bergey/STL
+license:             BSD3
+license-file:        LICENSE
+author:              Daniel Bergey
+maintainer:          bergey@alum.mit.edu
+-- copyright:           
+category:            Graphics
+build-type:          Simple
+-- extra-source-files:  
+cabal-version:       >=1.10
+bug-reports:         http://github.com/bergey/STL/issues
+
+library
+  exposed-modules:  Graphics.Formats.STL,
+                    Graphics.Formats.STL.Types,
+                    Graphics.Formats.STL.Parser,
+                    Graphics.Formats.STL.Printer
+  -- other-modules:       
+  -- other-extensions:    
+  build-depends:    base >=4.6 && <4.7,
+                    pretty >= 1.1 && < 1.2,
+                    attoparsec >= 0.11 && < 0.12,
+                    text >= 1.0 && < 1.2
+  hs-source-dirs:   src     
+  default-language: Haskell2010
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/src/Graphics/Formats/STL.hs b/src/Graphics/Formats/STL.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Formats/STL.hs
@@ -0,0 +1,10 @@
+module Graphics.Formats.STL (
+      prettySTL
+    , stlParser
+    , STL(..), Triangle(..), Vector(..)
+    )
+    where
+
+import Graphics.Formats.STL.Printer (prettySTL)
+import Graphics.Formats.STL.Parser (stlParser)
+import Graphics.Formats.STL.Types
diff --git a/src/Graphics/Formats/STL/Parser.hs b/src/Graphics/Formats/STL/Parser.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Formats/STL/Parser.hs
@@ -0,0 +1,39 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Graphics.Formats.STL.Parser where
+
+import Prelude hiding (takeWhile)
+
+import Control.Applicative
+import Data.Attoparsec.Text
+import Data.Text (Text)
+
+import Graphics.Formats.STL.Types
+
+-- | A parser from 'Text' to the @STL@ type.  The parser should be
+-- fairly permissive about whitespace, but has not been tested enough
+-- against STL files in the wild.
+stlParser :: Parser STL
+stlParser = STL <$> nameParser <*> many' triangle
+
+nameParser :: Parser Text
+nameParser = text "solid" *> takeWhile (inClass " -~") <* skipSpace
+
+triangle = Triangle <$> ss normalParser <*> loop <* text "endfacet"
+
+loop = triple <$> (text "outer loop" *> ss vertex) <*> ss vertex <*> ss vertex <* text "endloop"
+
+normalParser :: Parser Vector
+normalParser = text "facet" *> text "normal" *> v3
+
+vertex :: Parser Vector
+vertex = text "vertex" *> v3
+
+v3 :: Parser Vector
+v3 = triple <$> ss double <*> ss double <*> ss double
+
+ss :: Parser a -> Parser a
+ss p = p <* skipSpace
+
+text :: Text -> Parser Text
+text t = string t <* skipSpace
diff --git a/src/Graphics/Formats/STL/Printer.hs b/src/Graphics/Formats/STL/Printer.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Formats/STL/Printer.hs
@@ -0,0 +1,30 @@
+module Graphics.Formats.STL.Printer where
+
+import Data.Text (Text, unpack)
+import Text.PrettyPrint
+
+import Graphics.Formats.STL.Types
+
+-- | Convert an @STL@ value to a @Doc@, which can be converted to a
+-- @String@ with 'render'
+prettySTL :: STL -> Doc
+prettySTL s = vcat [ text "solid " <> (text . unpack $ name s)
+                , vcat . map triangle $ triangles s
+                , text "endsolid " <> (text . unpack $ name s)
+                ]
+
+triangle :: Triangle -> Doc
+triangle (Triangle n (a, b, c)) =
+    vcat [ text "facet normal" <+> v3 n
+         , nest 4 $ vcat [ text "outer loop"
+                         , nest 4 $ vcat [vertex a, vertex b, vertex c]
+                         , text "endloop"
+                         ]
+         , text "endfacet"
+         ]
+
+vertex :: Vector -> Doc
+vertex v = text "vertex" <+> v3 v
+
+v3 :: Vector -> Doc
+v3 (x, y, z) = hsep [double x, double y, double z]
diff --git a/src/Graphics/Formats/STL/Types.hs b/src/Graphics/Formats/STL/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Formats/STL/Types.hs
@@ -0,0 +1,20 @@
+module Graphics.Formats.STL.Types where
+
+import Data.Text (Text)
+
+-- | A representation of an STL file, consisting of a (possibly empty)
+-- object name, and a list of triangles.
+data STL = STL { name :: Text
+               , triangles :: [Triangle]
+               }
+
+-- | A single triangle in STL is represented by a normal vector and
+-- three vertices.
+data Triangle = Triangle { normal :: Vector
+                         , vertices :: (Vector, Vector, Vector)
+                         }
+
+type Vector = (Double, Double, Double)
+
+triple :: a -> a -> a -> (a, a, a)
+triple a b c = (a, b, c)
