diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -6,6 +6,13 @@
 project adheres to the [Haskell Package Versioning
 Policy (PVP)](https://pvp.haskell.org)
 
+## 1.1.4.0 -- 2021-03-11
+
+ * Fix build issue on M1 MacOS.
+ * Improve documentation.
+ * Fix bug in 'reanimateLiveEntry'.
+ * Simplify 'mkRect' definition.
+
 ## 1.1.3.2 -- 2021-01-14
 
  * Add flag for disabling the HGeometry dependency.
diff --git a/examples/decompose.hs b/examples/decompose.hs
new file mode 100644
--- /dev/null
+++ b/examples/decompose.hs
@@ -0,0 +1,69 @@
+#!/usr/bin/env stack
+-- stack runghc --package reanimate
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE OverloadedStrings #-}
+module Main(main) where
+
+import           Algorithms.Geometry.PolygonTriangulation.Triangulate (triangulate')
+import           Control.Lens
+import           Control.Monad
+import qualified Data.CircularSeq                                     as C
+import qualified Data.Geometry                                        as Geo
+import           Data.Geometry.PlanarSubdivision                      (PolygonFaceData (..))
+import qualified Data.Geometry.Point                                  as Geo
+import qualified Data.Geometry.Polygon                                as Geo
+import qualified Data.PlaneGraph                                      as Geo
+import           Data.Proxy
+import           Graphics.SvgTree.Types
+import           Linear.V2
+import           Reanimate
+import           Reanimate.Builtin.Documentation
+import           Reanimate.PolyShape
+
+import           Data.Ext
+import           Data.List
+import qualified Data.Vector                                          as V
+
+scaleP n = lowerTransformations . scale n
+
+env = addStatic (mkBackground "white") .
+  mapA (withFillOpacity 0 . withStrokeColor "black" . withStrokeWidth (defaultStrokeWidth*0.1))
+
+main :: IO ()
+main = reanimate $ env $ scene $ do
+  let --svg = scaleP 4 $ center $ latex "$F=ma$"
+      svg = scaleP 4 $ center $ latex "$\\infty$"
+      withHoles :: [PolyShapeWithHoles]
+      withHoles = plGroupShapes . unionPolyShapes $ svgToPolyShapes svg
+      hpoly = map toPoly withHoles
+      rects :: [[RPoint]]
+      rects = concatMap decomposeP hpoly
+  -- newSpriteSVG_ $ scaleP 4 $ center $ latex "$F=ma$"
+  forM_ rects $ \rect -> do
+    newSpriteSVG_ $ mkLinePathClosed [ (x, y) | V2 x y <- rect ]
+    wait (1/60)
+  wait 1
+
+
+-- map (decomposePolygon . plPolygonify 1 . mergePolyShapeHoles) $ plGroupShapes $ unionPolyShapes $ svgToPolyShapes $ latex "I"
+
+toPoly :: PolyShapeWithHoles -> Geo.Polygon Geo.Multi () Double
+toPoly (PolyShapeWithHoles outer holes) = Geo.MultiPolygon
+  (toSeq outer)
+  (map (Geo.SimplePolygon . toSeq) holes)
+  where
+    tol = 0.001
+    toSeq p = C.fromList $
+      [ Geo.Point2 x y :+ ()
+      | V2 x y <- init $ plPolygonify tol p ]
+
+
+decomposeP :: Geo.Polygon Geo.Multi () Double -> [[RPoint]]
+decomposeP poly =
+  [ [ V2 x y
+    | v <- V.toList (Geo.boundaryVertices f pg)
+    , let Geo.Point2 x y = pg^.Geo.vertexDataOf v . Geo.location ]
+  | (f, Inside) <- V.toList (Geo.internalFaces pg) ]
+
+  where
+    pg = triangulate' Proxy poly
diff --git a/reanimate.cabal b/reanimate.cabal
--- a/reanimate.cabal
+++ b/reanimate.cabal
@@ -3,7 +3,7 @@
 --  see http://haskell.org/cabal/users-guide/
 
 name:                reanimate
-version:             1.1.3.3
+version:             1.1.4.0
 -- synopsis:
 -- description:
 license:             PublicDomain
diff --git a/src/Reanimate/Driver.hs b/src/Reanimate/Driver.hs
--- a/src/Reanimate/Driver.hs
+++ b/src/Reanimate/Driver.hs
@@ -4,18 +4,19 @@
   )
 where
 
-import           Control.Applicative      ((<|>))
+import           Control.Applicative     ((<|>))
 import           Control.Concurrent
 import           Control.Monad
 import           Data.Either
 import           Data.Maybe
-import           Reanimate.Animation      (Animation, duration)
+import           Paths_reanimate         (getDataFileName)
+import           Reanimate.Animation     (Animation, duration)
 import           Reanimate.Driver.CLI
 import           Reanimate.Driver.Check
 import           Reanimate.Driver.Daemon
 import           Reanimate.Parameters
-import           Reanimate.Render         (render, renderSnippets, renderSvgs, renderSvgs_,
-                                           selectRaster)
+import           Reanimate.Render        (render, renderSnippets, renderSvgs, renderSvgs_,
+                                          selectRaster)
 import           System.Directory
 import           System.Exit
 import           System.FilePath
@@ -200,10 +201,21 @@
 makeEven x | even x    = x
            | otherwise = x - 1
 
+sanityCheck :: IO ()
+sanityCheck = do
+  url <- getDataFileName "viewer-elm/dist/index.html"
+  hasClient <- doesFileExist url
+  unless hasClient $ do
+    hPutStrLn stderr $ "Couldn't find web client at: " ++ url
+    hPutStrLn stderr $ "You may need to run:"
+    hPutStrLn stderr $ "  $ export reanimate_datadir=`pwd`"
+    hPutStrLn stderr $ "For more information, see this cabal issue: https://github.com/haskell/cabal/issues/6235"
+    exitFailure
 
 -- serve viewVerbose viewGHCPath viewGHCOpts viewOrigin
 viewAnimation :: Bool -> Animation -> IO ()
 viewAnimation _detach animation = do
+  sanityCheck
   detached <- ensureDaemon
 
   let rate = 60
diff --git a/src/Reanimate/Driver/Server.hs b/src/Reanimate/Driver/Server.hs
--- a/src/Reanimate/Driver/Server.hs
+++ b/src/Reanimate/Driver/Server.hs
@@ -14,12 +14,12 @@
 import qualified Data.Text                 as T
 import           Network.Socket            (AddrInfo (..), AddrInfoFlag (..), SocketOption (..),
                                             SocketType (Stream), accept, bind, close, defaultHints,
-                                            getAddrInfo, listen, socket,
-                                            setCloseOnExecIfNeeded, setSocketOption, withFdSocket,
-                                            withSocketsDo)
+                                            getAddrInfo, listen, setCloseOnExecIfNeeded,
+                                            setSocketOption, socket, withFdSocket, withSocketsDo)
 import           Network.Socket.ByteString (recv)
 import           Network.WebSockets
 import           Paths_reanimate           (getDataFileName)
+import           System.Exit               (exitFailure)
 import           System.IO                 (hPutStrLn, stderr)
 import           Web.Browser               (openBrowser)
 
@@ -124,8 +124,9 @@
 openViewer = do
   url <- getDataFileName "viewer-elm/dist/index.html"
   bSucc <- openBrowser url
-  unless bSucc $
-    hPutStrLn stderr $ "Failed to open browser. Manually visit: " ++ url
+  unless bSucc $ do
+    hPutStrLn stderr "Failed to open browser."
+    exitFailure
 
 -------------------------------------------------------------------------------
 -- Websocket API
