diff --git a/CHANGES b/CHANGES
deleted file mode 100644
--- a/CHANGES
+++ /dev/null
@@ -1,3 +0,0 @@
-* 0.2.0.0: 26 August 2012
-
-  Initial release
diff --git a/CHANGES.markdown b/CHANGES.markdown
new file mode 100644
--- /dev/null
+++ b/CHANGES.markdown
@@ -0,0 +1,16 @@
+0.2.1.0: 11 December 2012
+-------------------------
+
++ new `diagrams-builder-svg` tool
++ deal properly with an empty list of sources ([\#2](https://github.com/diagrams/diagrams-builder/issues/2))
++ put cached diagrams in `.diagrams_cache` instead of `diagrams` by default
++ bug fix: cached files should use same extension as requested output, not "png"
++ bug fix: create output directory for cached images if it doesn't exist
++ new module `Diagrams.Builder.CmdLine`; factor out common utilities
+  for command-line tools
++ depend on 0.6 versions of diagrams libs
+
+0.2.0.0: 26 August 2012
+-----------------------
+
+Initial release
diff --git a/README.markdown b/README.markdown
new file mode 100644
--- /dev/null
+++ b/README.markdown
@@ -0,0 +1,31 @@
+[![Build Status](https://secure.travis-ci.org/diagrams/diagrams-builder.png)](http://travis-ci.org/diagrams/diagrams-builder)
+
+`diagrams-builder` provides backend-agnostic tools for dynamically
+turning code into rendered
+[diagrams](http://projects.haskell.org/diagrams), using the
+[hint](http://hackage.haskell.org/package/hint) wrapper to the GHC
+API.  It supports conditional recompilation using hashing of diagrams
+source code, to avoid recompiling code that has not changed.  It is
+useful for creating tools which compile diagrams code embedded in
+other documents.  For example, it is used by the
+[BlogLiterately-diagrams](http://hackage.haskell.org/package/BlogLiterately%2Ddiagrams)
+package (a plugin for
+[BlogLiterately](http://hackage.haskell.org/package/BlogLiterately))
+to compile diagrams embedded in
+[Markdown](http://daringfireball.net/projects/markdown/)-formatted
+blog posts.
+
+An executable specific to the
+[cairo backend](http://github.com/diagrams/diagrams-cairo) is included
+(more executables specific to other backends will be included in the
+future).  It takes an input file and an expression to render and
+outputs an image file, using the cairo backend.  If you want it you
+must explicitly enable the cairo flag with `-fcairo`.
+		     
+A LaTeX package, `diagrams-latex.sty`, is also provided in the
+`latex/` directory of the source distribution, which renders diagrams
+code found within `diagram` environments.  It makes use of the
+`diagrams-builder-cairo` executable, so if you want to use
+`diagrams-latex.sty` you should install `diagrams-builder` with the
+`-fcairo` option.  Note that `diagrams-latex.sty` is licensed under
+the GPL.
diff --git a/diagrams-builder.cabal b/diagrams-builder.cabal
--- a/diagrams-builder.cabal
+++ b/diagrams-builder.cabal
@@ -1,5 +1,5 @@
 name:                diagrams-builder
-version:             0.2.0.0
+version:             0.2.1.0
 synopsis:            hint-based build service for the diagrams graphics EDSL.
 
 description:         @diagrams-builder@ provides backend-agnostic tools for
@@ -14,13 +14,13 @@
                      plugin for @BlogLiterately@) to compile diagrams
                      embedded in Markdown-formatted blog posts.
                      .
-                     An executable specific to the cairo backend is
-                     included (more executables specific to other
-                     backends will be included in the future).  It
-                     takes an input file and an expression to render
-                     and outputs an image file, using the cairo
-                     backend.  If you want it you must explicitly
-                     enable the cairo flag with @-fcairo@.
+                     Executables specific to the cairo and SVG
+                     backends are included (more executables specific
+                     to other backends may be included in the future).
+                     Both take an input file and an expression to
+                     render, and outputs an image file.  If you want
+                     these executables you must explicitly enable the
+                     @-fcairo@ and/or @-fsvg@ flags.
                      .
                      A LaTeX package, @diagrams-latex.sty@, is also
                      provided in the @latex/@ directory of the source
@@ -34,12 +34,13 @@
 homepage:            http://projects.haskell.org/diagrams
 license:             BSD3
 license-file:        LICENSE
-extra-source-files:  CHANGES, latex/diagrams-latex.sty
+extra-source-files:  CHANGES.markdown, README.markdown, latex/diagrams-latex.sty
 author:              Brent Yorgey
 maintainer:          diagrams-discuss@googlegroups.com
 category:            Graphics
 build-type:          Simple
 cabal-version:       >=1.10
+tested-with:         GHC == 7.4.2, GHC == 7.6.1
 bug-reports:         https://github.com/diagrams/diagrams-builder/issues
 Source-repository head
   type:     git
@@ -48,15 +49,17 @@
 library
   exposed-modules:     Diagrams.Builder
                        Diagrams.Builder.Modules
+                       Diagrams.Builder.CmdLine
   build-depends:       base >=4.2 && < 4.7,
-                       diagrams-lib >=0.3 && < 0.6,
+                       diagrams-lib >=0.6 && < 0.7,
                        hint ==0.3.*,
                        directory,
                        filepath,
                        haskell-src-exts >= 1.13.1 && < 1.14,
-                       cryptohash >= 0.7.4 && < 0.8,
-                       bytestring >= 0.9.2 && < 0.10,
-                       base16-bytestring >= 0.1.1 && < 0.2
+                       cryptohash >= 0.7.4 && < 0.9,
+                       bytestring >= 0.9.2 && < 0.11,
+                       base16-bytestring >= 0.1.1 && < 0.2,
+                       cmdargs >= 0.6 && < 0.11
   hs-source-dirs:      src
   default-language:    Haskell2010
   other-extensions:    StandaloneDeriving,
@@ -67,13 +70,19 @@
 flag cairo
   description: install cairo-specific builder tool
   default:     False
+  manual:      True
 
+flag svg
+  description: install svg-specific builder tool
+  default:     False
+  manual:      True
+
 executable diagrams-builder-cairo
   main-is:             diagrams-builder-cairo.hs
   hs-source-dirs:      src/tools
   default-language:    Haskell2010
-  other-extensions:    StandaloneDeriving,
-                       DeriveDataTypeable
+  other-extensions:    DeriveDataTypeable
+                       RecordWildCards
 
   if !flag(cairo)
     buildable: False
@@ -83,6 +92,27 @@
                        filepath,
                        directory,
                        diagrams-builder,
-                       diagrams-lib >= 0.5 && < 0.6,
-                       diagrams-cairo >= 0.5 && < 0.6,
+                       diagrams-lib >= 0.6 && < 0.7,
+                       diagrams-cairo >= 0.6 && < 0.7,
+                       cmdargs >= 0.6 && < 0.11
+
+executable diagrams-builder-svg
+  main-is:             diagrams-builder-svg.hs
+  hs-source-dirs:      src/tools
+  default-language:    Haskell2010
+  other-extensions:    DeriveDataTypeable
+                       RecordWildCards
+
+  if !flag(svg)
+    buildable: False
+
+  if flag(svg)
+    build-depends:     base >= 4 && < 5,
+                       filepath,
+                       directory,
+                       diagrams-builder,
+                       diagrams-lib >= 0.6 && < 0.7,
+                       diagrams-svg >= 0.6 && < 0.7,
+                       blaze-svg >= 0.3.3 && < 0.4,
+                       bytestring >= 0.9.2 && < 0.11,
                        cmdargs >= 0.6 && < 0.11
diff --git a/src/Diagrams/Builder.hs b/src/Diagrams/Builder.hs
--- a/src/Diagrams/Builder.hs
+++ b/src/Diagrams/Builder.hs
@@ -30,9 +30,15 @@
        , setDiagramImports
        , interpretDiagram
 
+         -- * Tools for creating standalone builder executables
+
+       , Build(..)
+       , defaultBuildOpts
+
        ) where
 
 import Diagrams.Builder.Modules
+import Diagrams.Builder.CmdLine
 
 import Diagrams.Prelude hiding ((<.>), e)
 
@@ -67,7 +73,7 @@
                   -> [String]    -- ^ Additional necessary
                                  --   imports. @Prelude@,
                                  --   @Diagrams.Prelude@,
-                                 --   @Graphics.Rendering.Diagrams.Core@,
+                                 --   @Diagrams.Core.Types@,
                                  --   and @Data.Monoid@ are included
                                  --   by default.
                   -> m ()
@@ -76,7 +82,7 @@
     setTopLevelModules [takeBaseName m]
     setImports $ [ "Prelude"
                  , "Diagrams.Prelude"
-                 , "Graphics.Rendering.Diagrams.Core"
+                 , "Diagrams.Core.Types"
                  , "Data.Monoid"
                  ]
                  ++ imps
diff --git a/src/Diagrams/Builder/CmdLine.hs b/src/Diagrams/Builder/CmdLine.hs
new file mode 100644
--- /dev/null
+++ b/src/Diagrams/Builder/CmdLine.hs
@@ -0,0 +1,45 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Diagrams.Builder.CmdLine
+-- Copyright   :  (c) 2012 diagrams-lib team (see LICENSE)
+-- License     :  BSD-style (see LICENSE)
+-- Maintainer  :  diagrams-discuss@googlegroups.com
+--
+-- Tools for creating standalone command-line diagram builder utilities.
+--
+-----------------------------------------------------------------------------
+module Diagrams.Builder.CmdLine
+    ( Build(..)
+    , defaultBuildOpts
+    )
+    where
+
+import System.Console.CmdArgs
+
+-- | Record of command-line options.
+data Build = Build { width   :: Maybe Double
+                   , height  :: Maybe Double
+                   , srcFile :: String
+                   , expr    :: String
+                   , outFile :: String
+                   , dir     :: String
+                   }
+  deriving (Typeable, Data)
+
+-- | Default command-line options record.
+defaultBuildOpts :: Build
+defaultBuildOpts =
+  Build
+  { width    = def &= typ "INT"
+  , height   = def &= typ "INT"
+  , srcFile  = "" &= argPos 0 &= typFile
+  , expr     = "dia"
+               &= typ "EXPRESSION"
+               &= help "Expression to render (default: \"dia\")"
+  , outFile  = def &= typFile &= help "Output file"
+  , dir      = ".diagrams_cache"
+               &= typDir
+               &= help "Directory in which to store rendered diagrams by hash (default: \".diagrams_cache\")"
+  }
diff --git a/src/Diagrams/Builder/Modules.hs b/src/Diagrams/Builder/Modules.hs
--- a/src/Diagrams/Builder/Modules.hs
+++ b/src/Diagrams/Builder/Modules.hs
@@ -12,7 +12,7 @@
 module Diagrams.Builder.Modules where
 
 import Data.Function (on)
-import Data.List (foldl1', isPrefixOf, groupBy, sortBy, nub)
+import Data.List (foldl', isPrefixOf, groupBy, sortBy, nub)
 import Data.Ord  (comparing)
 
 import Language.Haskell.Exts
@@ -35,7 +35,6 @@
              -> [String]     -- ^ Imports to add
              -> [String]     -- ^ Source code
              -> Either String Module
-createModule _ _ _ [] = Left "createModule: no source code given"
 createModule nm langs imps srcs = do
   ms <- mapM doModuleParse srcs
   return
@@ -43,8 +42,11 @@
     . maybe id replaceModuleName nm
     . addPragmas langs
     . addImports imps
-    . foldl1' combineModules
+    . foldl' combineModules emptyModule
     $ ms
+
+emptyModule :: Module
+emptyModule = Module noLoc (ModuleName "Main") [] Nothing Nothing [] []
 
 -- | Run the haskell-src-exts parser on a @String@ representing some
 --   Haskell code, producing a @Module@ or an error message.
diff --git a/src/tools/diagrams-builder-cairo.hs b/src/tools/diagrams-builder-cairo.hs
--- a/src/tools/diagrams-builder-cairo.hs
+++ b/src/tools/diagrams-builder-cairo.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE StandaloneDeriving #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE RecordWildCards #-}
 
@@ -10,14 +9,15 @@
 
 import Diagrams.Builder
 
-import System.Directory (copyFile)
+import System.Directory (createDirectoryIfMissing, copyFile)
 import qualified System.FilePath as FP
 
 import System.Console.CmdArgs
 
 compileExample :: Build -> IO ()
 compileExample (Build{..}) = do
-  let fmt = case FP.takeExtension outFile of
+  let ext = FP.takeExtension outFile
+      fmt = case ext of
               ".png" -> PNG
               ".svg" -> SVG
               ".ps"  -> PS
@@ -26,50 +26,35 @@
 
   f   <- readFile srcFile
 
+  createDirectoryIfMissing True dir
+
   res <- buildDiagram
            Cairo
            zeroV
-           (CairoOptions outFile (mkSizeSpec width height) fmt)
+           (CairoOptions outFile (mkSizeSpec width height) fmt False)
            [f]
            expr
            []
            [ "Diagrams.Backend.Cairo" ]
            (hashedRegenerate
-             (\hash opts -> opts { cairoFileName = mkFile hash })
+             (\hash opts -> opts { cairoFileName = mkFile hash ext })
              dir
            )
   case res of
     ParseErr err    -> putStrLn ("Parse error in " ++ srcFile) >> putStrLn err
     InterpErr ierr  -> putStrLn ("Error while compiling " ++ srcFile) >>
                        putStrLn (ppInterpError ierr)
-    Skipped hash    -> copyFile (mkFile hash) outFile
-    OK hash (act,_) -> act >> copyFile (mkFile hash) outFile
+    Skipped hash    -> copyFile (mkFile hash ext) outFile
+    OK hash (act,_) -> act >> copyFile (mkFile hash ext) outFile
  where
-  mkFile base = dir FP.</> base FP.<.> "png"
-
-data Build = Build { width   :: Maybe Double
-                   , height  :: Maybe Double
-                   , srcFile :: String
-                   , expr    :: String
-                   , outFile :: String
-                   , dir     :: String
-                   }
-  deriving (Typeable, Data)
+  mkFile base ext = dir FP.</> base FP.<.> ext
 
 build :: Build
-build = Build { width    = def &= typ "INT"
-              , height   = def &= typ "INT"
-              , srcFile  = "" &= argPos 0 &= typFile
-              , expr     = "dia"
-                &= typ "EXPRESSION"
-                &= help "Expression to render (default: \"dia\")"
-              , outFile  = "out.png" &= typFile &= help "Output file (default: \"out.png\")"
-              , dir      = "diagrams"
-                &= typDir
-                &= help "Directory in which to store rendered diagrams by hash (default: \"diagrams\")"
-              }
-        &= summary "The diagrams-builder-cairo program, for dynamically rendering diagrams using the cairo backend.  Give it a source file and an expression to render (which may refer to things declared in the source file), and it outputs an image, using hashing to avoid rerendering images unnecessarily."
-        &= program "diagrams-builder-cairo"
+build =
+  defaultBuildOpts
+  { outFile  = "out.png" &= typFile &= help "Output file (default: \"out.png\")" }
+  &= summary "The diagrams-builder-cairo program, for dynamically rendering diagrams using the cairo backend.  Give it a source file and an expression to render (which may refer to things declared in the source file), and it outputs an image, using hashing to avoid rerendering images unnecessarily."
+  &= program "diagrams-builder-cairo"
 
 main :: IO ()
 main = do
diff --git a/src/tools/diagrams-builder-svg.hs b/src/tools/diagrams-builder-svg.hs
new file mode 100644
--- /dev/null
+++ b/src/tools/diagrams-builder-svg.hs
@@ -0,0 +1,54 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE RecordWildCards #-}
+
+module Main where
+
+import           Diagrams.Backend.SVG
+import           Diagrams.Builder
+import           Diagrams.Prelude hiding (width, height)
+
+import qualified Data.ByteString.Lazy as BS
+import           System.Console.CmdArgs
+import           System.Directory (createDirectoryIfMissing, copyFile)
+import qualified System.FilePath as FP
+import           Text.Blaze.Svg.Renderer.Utf8 (renderSvg)
+
+compileExample :: Build -> IO ()
+compileExample (Build{..}) = do
+  f   <- readFile srcFile
+
+  createDirectoryIfMissing True dir
+
+  res <- buildDiagram
+           SVG
+           zeroV
+           (SVGOptions (mkSizeSpec width height))
+           [f]
+           expr
+           []
+           [ "Diagrams.Backend.SVG" ]
+           (hashedRegenerate (\_ opts -> opts) dir)
+
+  case res of
+    ParseErr err    -> putStrLn ("Parse error in " ++ srcFile) >> putStrLn err
+    InterpErr ierr  -> putStrLn ("Error while compiling " ++ srcFile) >>
+                       putStrLn (ppInterpError ierr)
+    Skipped hash    -> copyFile (mkFile hash) outFile
+    OK hash svg     -> do let cached = mkFile hash
+                          BS.writeFile cached (renderSvg svg)
+                          copyFile cached outFile
+ where
+   mkFile base = dir FP.</> base FP.<.> "svg"
+
+build :: Build
+build =
+  defaultBuildOpts
+  { outFile = "out.svg" &= typFile &= help "Output file (default: \"out.svg\")"
+  }
+  &= summary "The diagrams-builder-svg program, for dynamically rendering diagrams using the native SVG backend.  Give it a source file and an expression to render (which may refer to things declared in the source file), and it outputs an image, using hashing to avoid rerendering images unnecessarily."
+  &= program "diagrams-builder-svg"
+
+main :: IO ()
+main = do
+  opts <- cmdArgs build
+  compileExample opts
