diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2015 Hirotomo Moriwaki
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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/barrier.cabal b/barrier.cabal
new file mode 100644
--- /dev/null
+++ b/barrier.cabal
@@ -0,0 +1,108 @@
+name:                barrier
+version:             0.1.0
+synopsis:            Shield.io style badge generator
+description:         see example: <https://github.com/philopon/barrier/blob/master/examples/example.hs>
+license:             MIT
+license-file:        LICENSE
+author:              HirotomoMoriwaki<philopon.dependence@gmail.com>
+maintainer:          HirotomoMoriwaki<philopon.dependence@gmail.com>
+Homepage:            https://github.com/philopon/barrier
+Bug-reports:         https://github.com/philopon/barrier/issues
+copyright:           (c) 2015 Hirotomo Moriwaki
+category:            Graphics
+build-type:          Simple
+data-files:          data/advance.txt
+                   , tests/data/flat/1.svg
+                   , tests/data/flat/2.svg
+                   , tests/data/flat/3.svg
+                   , tests/data/flat/4.svg
+                   , tests/data/flatSquare/1.svg
+                   , tests/data/flatSquare/2.svg
+                   , tests/data/flatSquare/3.svg
+                   , tests/data/flatSquare/4.svg
+                   , tests/data/plastic/1.svg
+                   , tests/data/plastic/2.svg
+                   , tests/data/plastic/3.svg
+                   , tests/data/plastic/4.svg
+cabal-version:       >=1.10
+
+flag example
+  default: False
+  description: build example
+
+flag generator
+  default: False
+  description: build font advance generator
+
+flag test-results
+  default: False
+  description: build test results generator
+
+library
+  exposed-modules:     Graphics.Badge.Barrier
+                       Graphics.Badge.Barrier.Color
+                       Graphics.Badge.Barrier.Internal
+                       Graphics.Badge.Barrier.Style.Flat
+                       Graphics.Badge.Barrier.Style.FlatSquare
+                       Graphics.Badge.Barrier.Style.Plastic
+  build-depends:       base                 >=4.6  && <4.8
+                     , template-haskell
+                     , unordered-containers >=0.2  && <0.3
+                     , blaze-svg            >=0.3  && <0.4
+                     , text                 >=1.1  && <1.3
+                     , bytestring           >=0.10 && <0.11
+  hs-source-dirs:      src
+  ghc-options:         -Wall -O2
+  default-language:    Haskell2010
+
+executable barrier-data-generator
+  main-is:             data-generator.hs
+  if flag(generator)
+    buildable:         True
+    build-depends:     base      >=4.6 && <4.8
+                     , freetype2 >=0.1 && <0.2
+  else
+    buildable:         False
+  ghc-options:         -Wall -O2
+  default-language:    Haskell2010
+
+executable barrier-example
+  main-is:             example.hs
+  if flag(example)
+    buildable:         True
+    build-depends:     base             >=4.6  && <4.8
+                     , bytestring       >=0.10 && <0.11
+                     , lens-family-core >=1.2  && <1.3
+                     , barrier
+  else
+    buildable:         False
+  hs-source-dirs:      examples
+  ghc-options:         -Wall -O2
+  default-language:    Haskell2010
+
+executable barrier-test-result-generator
+  main-is:             make-test-data.hs
+  if flag(test-results)
+    buildable:         True
+    build-depends:     base             >=4.6  && <4.8
+                     , bytestring       >=0.10 && <0.11
+                     , lens-family-core >=1.2  && <1.3
+                     , barrier
+  else
+    buildable:         False
+  hs-source-dirs:      examples
+  ghc-options:         -Wall -O2
+  default-language:    Haskell2010
+
+test-suite tasty
+  type:                exitcode-stdio-1.0
+  main-is:             tasty.hs
+  build-depends:       base             >=4.6  && <4.8
+                     , bytestring       >=0.10 && <0.11
+                     , lens-family-core >=1.2  && <1.3
+                     , tasty            >=0.10 && <0.11
+                     , tasty-golden     >=2.2  && <2.3
+                     , barrier
+  hs-source-dirs:      tests
+  ghc-options:         -Wall -O2
+  default-language:    Haskell2010
diff --git a/data-generator.hs b/data-generator.hs
new file mode 100644
--- /dev/null
+++ b/data-generator.hs
@@ -0,0 +1,72 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE LambdaCase #-}
+
+import System.Environment
+
+import Control.Monad
+import Control.Applicative
+import Control.Exception
+
+import Foreign.Storable
+import Foreign.Marshal
+import Foreign.Ptr
+import Foreign.C
+
+import Graphics.Rendering.FreeType.Internal
+import Graphics.Rendering.FreeType.Internal.Face(glyph, FT_Face)
+import Graphics.Rendering.FreeType.Internal.Vector(FT_Vector(FT_Vector))
+import Graphics.Rendering.FreeType.Internal.Library(FT_Library)
+import Graphics.Rendering.FreeType.Internal.GlyphSlot(advance)
+import Graphics.Rendering.FreeType.Internal.PrimitiveTypes(FT_ULong)
+
+import Data.Typeable
+
+data FTError = FTError String CInt deriving(Show, Typeable)
+instance Exception FTError
+
+ft :: String -> IO CInt -> IO ()
+ft n f = do
+    e <- f
+    unless (e == 0) $ throwIO (FTError n e)
+
+withFreeType :: (FT_Library -> IO a) -> IO a
+withFreeType = bracket bra ket
+  where
+    bra = alloca $ \p -> ft "Init_FreeType" (ft_Init_FreeType p) >> peek p
+    ket = ft "Done_FreeType" . ft_Done_FreeType
+
+withFontFace :: FilePath -> (FT_Face -> IO a) -> FT_Library -> IO a
+withFontFace fn m lib = bracket bra ket m
+  where
+    bra = alloca $ \p -> withCString fn $ \f ->
+        ft "New_Face" (ft_New_Face lib f 0 p) >> peek p
+    ket = ft "Done_Face" . ft_Done_Face
+
+firstChar :: FT_Face -> IO FT_ULong
+firstChar face = fromIntegral <$> ft_Get_First_Char face nullPtr
+
+nextChar :: FT_Face -> FT_ULong -> IO FT_ULong
+nextChar face c = ft_Get_Next_Char face c nullPtr
+
+forCharM_ :: FT_Face -> (FT_ULong -> IO ()) -> IO ()
+forCharM_ face m = firstChar face >>= go
+  where
+    go 0 = return ()
+    go i = m i >> nextChar face i >>= go
+
+
+main :: IO ()
+main = getArgs >>= \case
+    [fontPath] -> withFreeType $ withFontFace fontPath $ \face -> do
+        ft "Set_Pixel_Sizes" $ ft_Set_Pixel_Sizes face 0 11
+        slot <- peek $ glyph face
+        forCharM_ face $ \c -> do
+            ft "Load_Char" $ ft_Load_Char face c 0
+            FT_Vector x _ <- peek $ advance slot
+            case quotRem x 64 of
+                (s, 0) -> putStrLn $ show c ++ '\t': show s
+                _      -> fail "rem font size"
+
+    _ -> do
+        p <- getProgName
+        putStrLn $ "Usage: " ++ p ++ " FONT_FILE"
diff --git a/data/advance.txt b/data/advance.txt
new file mode 100644
--- /dev/null
+++ b/data/advance.txt
@@ -0,0 +1,738 @@
+32	4
+33	4
+34	5
+35	9
+36	7
+37	12
+38	8
+39	3
+40	5
+41	5
+42	7
+43	9
+44	4
+45	5
+46	4
+47	5
+48	7
+49	7
+50	7
+51	7
+52	7
+53	7
+54	7
+55	7
+56	7
+57	7
+58	5
+59	5
+60	9
+61	9
+62	9
+63	6
+64	10
+65	8
+66	8
+67	9
+68	9
+69	7
+70	6
+71	9
+72	8
+73	5
+74	5
+75	8
+76	6
+77	9
+78	8
+79	9
+80	7
+81	9
+82	8
+83	8
+84	7
+85	8
+86	8
+87	11
+88	8
+89	7
+90	8
+91	5
+92	5
+93	5
+94	9
+95	7
+96	7
+97	7
+98	7
+99	6
+100	7
+101	7
+102	4
+103	7
+104	7
+105	3
+106	4
+107	7
+108	3
+109	11
+110	7
+111	7
+112	7
+113	7
+114	5
+115	6
+116	4
+117	7
+118	7
+119	9
+120	7
+121	7
+122	6
+123	7
+124	5
+125	7
+126	9
+160	4
+161	4
+162	7
+163	7
+164	7
+165	7
+166	5
+167	7
+168	7
+169	11
+170	6
+171	7
+172	9
+173	5
+174	11
+175	7
+176	6
+177	9
+178	6
+179	6
+180	7
+181	7
+182	7
+183	4
+184	7
+185	6
+186	6
+187	7
+188	11
+189	11
+190	11
+191	6
+192	8
+193	8
+194	8
+195	8
+196	8
+197	8
+198	11
+199	9
+200	7
+201	7
+202	7
+203	7
+204	5
+205	5
+206	5
+207	5
+208	9
+209	8
+210	9
+211	9
+212	9
+213	9
+214	9
+215	9
+216	9
+217	8
+218	8
+219	8
+220	8
+221	7
+222	7
+223	7
+224	7
+225	7
+226	7
+227	7
+228	7
+229	7
+230	11
+231	6
+232	7
+233	7
+234	7
+235	7
+236	3
+237	3
+238	3
+239	3
+240	7
+241	7
+242	7
+243	7
+244	7
+245	7
+246	7
+247	9
+248	7
+249	7
+250	7
+251	7
+252	7
+253	7
+254	7
+255	7
+256	8
+257	7
+258	8
+259	7
+260	8
+261	7
+262	9
+263	6
+264	9
+265	6
+266	9
+267	6
+268	9
+269	6
+270	9
+271	7
+272	9
+273	7
+274	7
+275	7
+276	7
+277	7
+278	7
+279	7
+280	7
+281	7
+282	7
+283	7
+284	9
+285	7
+286	9
+287	7
+288	9
+289	7
+290	9
+291	7
+292	8
+293	7
+294	8
+295	7
+296	5
+297	3
+298	5
+299	3
+300	5
+301	3
+302	5
+303	3
+304	5
+305	3
+306	10
+307	7
+308	5
+309	4
+310	8
+311	7
+312	7
+313	6
+314	3
+315	6
+316	3
+317	6
+318	3
+319	6
+320	5
+321	6
+322	3
+323	8
+324	7
+325	8
+326	7
+327	8
+328	7
+329	8
+330	8
+331	7
+332	9
+333	7
+334	9
+335	7
+336	9
+337	7
+338	12
+339	11
+340	8
+341	5
+342	8
+343	5
+344	8
+345	5
+346	8
+347	6
+348	8
+349	6
+350	8
+351	6
+352	8
+353	6
+354	7
+355	4
+356	7
+357	4
+358	7
+359	4
+360	8
+361	7
+362	8
+363	7
+364	8
+365	7
+366	8
+367	7
+368	8
+369	7
+370	8
+371	7
+372	11
+373	9
+374	7
+375	7
+376	7
+377	8
+378	6
+379	8
+380	6
+381	8
+382	6
+383	3
+399	8
+402	7
+416	9
+417	7
+431	8
+432	7
+506	8
+507	7
+508	11
+509	11
+510	9
+511	7
+536	8
+537	6
+538	7
+539	4
+601	7
+710	7
+711	7
+713	7
+728	7
+729	7
+730	7
+731	7
+732	7
+733	7
+768	0
+769	0
+771	0
+777	0
+803	0
+894	5
+900	7
+901	7
+902	8
+903	5
+904	8
+905	9
+906	6
+908	10
+910	9
+911	9
+912	3
+913	8
+914	8
+915	6
+916	8
+917	7
+918	8
+919	8
+920	9
+921	5
+922	8
+923	8
+924	9
+925	8
+926	7
+927	9
+928	8
+929	7
+931	7
+932	7
+933	7
+934	9
+935	8
+936	9
+937	9
+938	5
+939	7
+940	7
+941	6
+942	7
+943	3
+944	7
+945	7
+946	7
+947	7
+948	7
+949	6
+950	5
+951	7
+952	7
+953	3
+954	7
+955	7
+956	7
+957	7
+958	6
+959	7
+960	7
+961	7
+962	6
+963	7
+964	5
+965	7
+966	9
+967	7
+968	9
+969	9
+970	3
+971	7
+972	7
+973	7
+974	9
+1025	7
+1026	9
+1027	6
+1028	9
+1029	8
+1030	5
+1031	5
+1032	5
+1033	13
+1034	12
+1035	9
+1036	8
+1037	8
+1038	8
+1039	8
+1040	8
+1041	8
+1042	8
+1043	6
+1044	8
+1045	7
+1046	11
+1047	7
+1048	8
+1049	8
+1050	8
+1051	8
+1052	9
+1053	8
+1054	9
+1055	8
+1056	7
+1057	9
+1058	7
+1059	8
+1060	9
+1061	8
+1062	9
+1063	8
+1064	11
+1065	12
+1066	9
+1067	10
+1068	7
+1069	9
+1070	11
+1071	8
+1072	7
+1073	7
+1074	7
+1075	5
+1076	8
+1077	7
+1078	9
+1079	6
+1080	7
+1081	7
+1082	7
+1083	7
+1084	7
+1085	7
+1086	7
+1087	7
+1088	7
+1089	6
+1090	5
+1091	7
+1092	9
+1093	7
+1094	8
+1095	7
+1096	9
+1097	10
+1098	8
+1099	9
+1100	7
+1101	7
+1102	10
+1103	7
+1105	7
+1106	7
+1107	5
+1108	7
+1109	6
+1110	3
+1111	3
+1112	4
+1113	10
+1114	11
+1115	7
+1116	7
+1117	7
+1118	7
+1119	7
+1168	6
+1169	5
+1170	6
+1171	5
+1174	11
+1175	9
+1178	8
+1179	7
+1180	8
+1181	7
+1186	8
+1187	7
+1198	7
+1199	7
+1200	7
+1201	7
+1202	8
+1203	7
+1208	8
+1209	7
+1210	8
+1211	7
+1240	8
+1241	7
+1256	9
+1257	7
+1380	7
+1408	7
+3647	8
+7808	11
+7809	9
+7810	11
+7811	9
+7812	11
+7813	9
+7840	8
+7841	7
+7842	8
+7843	7
+7844	8
+7845	7
+7846	8
+7847	7
+7848	8
+7849	7
+7850	8
+7851	7
+7852	8
+7853	7
+7854	8
+7855	7
+7856	8
+7857	7
+7858	8
+7859	7
+7860	8
+7861	7
+7862	8
+7863	7
+7864	7
+7865	7
+7866	7
+7867	7
+7868	7
+7869	7
+7870	7
+7871	7
+7872	7
+7873	7
+7874	7
+7875	7
+7876	7
+7877	7
+7878	7
+7879	7
+7880	5
+7881	3
+7882	5
+7883	3
+7884	9
+7885	7
+7886	9
+7887	7
+7888	9
+7889	7
+7890	9
+7891	7
+7892	9
+7893	7
+7894	9
+7895	7
+7896	9
+7897	7
+7898	9
+7899	7
+7900	9
+7901	7
+7902	9
+7903	7
+7904	9
+7905	7
+7906	9
+7907	7
+7908	8
+7909	7
+7910	8
+7911	7
+7912	8
+7913	7
+7914	8
+7915	7
+7916	8
+7917	7
+7918	8
+7919	7
+7920	8
+7921	7
+7922	7
+7923	7
+7924	7
+7925	7
+7926	7
+7927	7
+7928	7
+7929	7
+8210	7
+8211	7
+8212	11
+8213	11
+8215	7
+8216	3
+8217	3
+8218	3
+8219	3
+8220	5
+8221	5
+8222	5
+8223	5
+8224	7
+8225	7
+8226	6
+8230	9
+8240	17
+8242	4
+8243	6
+8244	6
+8249	5
+8250	5
+8252	7
+8254	7
+8260	4
+8308	6
+8309	6
+8311	6
+8312	6
+8319	6
+8352	7
+8353	8
+8354	8
+8355	7
+8356	7
+8357	11
+8358	8
+8359	13
+8360	13
+8361	11
+8362	9
+8363	7
+8364	7
+8365	8
+8366	7
+8367	11
+8368	6
+8369	7
+8370	9
+8371	8
+8372	8
+8373	8
+8453	12
+8467	4
+8470	13
+8480	12
+8482	11
+8486	9
+8494	8
+8539	11
+8540	11
+8541	11
+8542	11
+8706	7
+8710	8
+8719	9
+8721	8
+8722	9
+8725	4
+8729	4
+8730	9
+8734	11
+8747	7
+8776	9
+8800	9
+8801	9
+8804	9
+8805	9
+9472	8
+9474	8
+9484	8
+9488	8
+9492	8
+9496	8
+9633	7
+9642	4
+9643	4
+9674	9
+9679	7
+9702	4
+9834	6
+64257	7
+64258	7
+65509	7
+65510	11
diff --git a/examples/example.hs b/examples/example.hs
new file mode 100644
--- /dev/null
+++ b/examples/example.hs
@@ -0,0 +1,9 @@
+{-# LANGUAGE OverloadedStrings #-}
+import Lens.Family
+import Graphics.Badge.Barrier
+import qualified Data.ByteString.Lazy.Char8 as L
+
+main :: IO ()
+main = do
+    L.writeFile "passing.svg" $ renderBadge flat "build" "passing"
+    L.writeFile "failing.svg" $ renderBadge (flat & right .~ red) "build" "failing"
diff --git a/examples/make-test-data.hs b/examples/make-test-data.hs
new file mode 100644
--- /dev/null
+++ b/examples/make-test-data.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE OverloadedStrings #-}
+import Lens.Family
+import Graphics.Badge.Barrier
+import qualified Data.ByteString.Lazy.Char8 as L
+
+main :: IO ()
+main = do
+    L.writeFile "flat/1.svg" $ renderBadge flat "build" "success"
+    L.writeFile "flat/2.svg" $ renderBadge (flat & right .~ red) "build" "failing"
+    L.writeFile "flat/3.svg" $ renderBadge (flat & left .~ green) "leaf" "leaf"
+    L.writeFile "flat/4.svg" $ renderBadge flat "longlonglonglonglonglonglonglonglonglonglonglong" "longlonglonglonglonglonglonglonglonglonglonglong"
+
+    L.writeFile "flatSquare/1.svg" $ renderBadge flatSquare "build" "success"
+    L.writeFile "flatSquare/2.svg" $ renderBadge (flatSquare & right .~ red) "build" "failing"
+    L.writeFile "flatSquare/3.svg" $ renderBadge (flatSquare & left .~ green) "leaf" "leaf"
+    L.writeFile "flatSquare/4.svg" $ renderBadge flatSquare "longlonglonglonglonglonglonglonglonglonglonglong" "longlonglonglonglonglonglonglonglonglonglonglong"
+
+    L.writeFile "plastic/1.svg" $ renderBadge plastic "build" "success"
+    L.writeFile "plastic/2.svg" $ renderBadge (plastic & right .~ red) "build" "failing"
+    L.writeFile "plastic/3.svg" $ renderBadge (plastic & left .~ green) "leaf" "leaf"
+    L.writeFile "plastic/4.svg" $ renderBadge plastic "longlonglonglonglonglonglonglonglonglonglonglong" "longlonglonglonglonglonglonglonglonglonglonglong"
diff --git a/src/Graphics/Badge/Barrier.hs b/src/Graphics/Badge/Barrier.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Badge/Barrier.hs
@@ -0,0 +1,37 @@
+module Graphics.Badge.Barrier
+    ( -- * badge
+      Badge
+    , flat
+    , flatSquare
+    , plastic
+
+    -- * render function
+    , renderBadge
+
+      -- * lens
+    , HasLeftColor(..)
+    , HasRightColor(..)
+
+    , module Graphics.Badge.Barrier.Color
+    ) where
+
+import Graphics.Badge.Barrier.Internal
+import Graphics.Badge.Barrier.Color
+
+import Graphics.Badge.Barrier.Style.Flat
+import Graphics.Badge.Barrier.Style.FlatSquare
+import Graphics.Badge.Barrier.Style.Plastic
+
+import Text.Blaze.Svg.Renderer.Utf8
+
+import Data.Text(Text)
+import Data.ByteString.Lazy(ByteString)
+
+-- | @
+-- renderBadge flat "left" "right"
+-- @
+renderBadge :: Badge b => b
+            -> Text -- ^ left text
+            -> Text -- ^ right text
+            -> ByteString -- ^ svg string
+renderBadge b l r = renderSvg $ makeBadge b l r
diff --git a/src/Graphics/Badge/Barrier/Color.hs b/src/Graphics/Badge/Barrier/Color.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Badge/Barrier/Color.hs
@@ -0,0 +1,46 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Graphics.Badge.Barrier.Color where
+
+import Data.Text(Text)
+import Data.String(IsString)
+
+newtype Color = Color Text
+    deriving(Show, Eq, IsString)
+
+-- | #4c1
+brightgreen :: Color
+brightgreen = "#4c1"
+
+-- | #97CA00
+green :: Color
+green = "#97CA00"
+
+-- | #dfb317
+yellow :: Color
+yellow = "#dfb317"
+
+-- | #a4a61d
+yellowgreen :: Color
+yellowgreen = "#a4a61d"
+
+-- | #fe7d37
+orange :: Color
+orange = "#fe7d37"
+
+-- | #e05d44
+red :: Color
+red = "#e05d44" 
+
+-- | #007ec6
+blue :: Color
+blue = "#007ec6" 
+
+-- | #555
+gray :: Color
+gray = "#555"
+
+-- | #9f9f9f
+lightgray :: Color
+lightgray = "#9f9f9f"
diff --git a/src/Graphics/Badge/Barrier/Internal.hs b/src/Graphics/Badge/Barrier/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Badge/Barrier/Internal.hs
@@ -0,0 +1,63 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE Rank2Types #-}
+
+module Graphics.Badge.Barrier.Internal
+    ( BadgeConfig(..)
+    , Badge(..)
+    , makeBadge
+    , Lens'
+    
+    , HasLeftColor(..)
+    , HasRightColor(..)
+    ) where
+
+import Language.Haskell.TH
+
+import Control.Arrow(second, (***))
+
+import Text.Blaze.Svg11(Svg)
+
+import qualified Data.Text as T
+import qualified Data.HashMap.Strict as S
+
+import Graphics.Badge.Barrier.Color
+
+advanceDict :: S.HashMap Char Int
+advanceDict = $( do
+    dat <- runIO $ readFile "data/advance.txt"
+    let convI = litE . integerL . read
+        convC = litE . charL . toEnum . read
+    let kvs = flip map (lines dat) $ tupE . (\(a,b) -> [a,b]) .
+            (convC *** convI) . second tail . break (== '\t')
+    [|S.fromList $(listE kvs)|]
+    )
+
+advance :: Char -> Int
+advance c = S.lookupDefault 11 c advanceDict
+
+measureText :: T.Text -> Int
+measureText = T.foldl' (\i c -> advance c + i) 0
+
+data BadgeConfig = BadgeConfig
+    { textLeft   :: T.Text
+    , textRight  :: T.Text
+    , widthLeft  :: Int
+    , widthRight :: Int
+    }
+
+badge' :: T.Text -> T.Text -> BadgeConfig
+badge' l r = BadgeConfig l r (measureText l + 10) (measureText r + 10)
+
+makeBadge :: Badge b => b -> T.Text -> T.Text -> Svg
+makeBadge b l r = badge b (badge' l r)
+
+class Badge a where
+    badge :: a -> BadgeConfig -> Svg
+
+type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s
+
+class HasLeftColor a where
+    left :: Lens' a Color
+
+class HasRightColor a where
+    right :: Lens' a Color
diff --git a/src/Graphics/Badge/Barrier/Style/Flat.hs b/src/Graphics/Badge/Barrier/Style/Flat.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Badge/Barrier/Style/Flat.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+
+module Graphics.Badge.Barrier.Style.Flat
+    ( Flat(..)
+    , flat
+    ) where
+
+import Graphics.Badge.Barrier.Internal
+import Graphics.Badge.Barrier.Color
+
+import Text.Blaze.Svg11(Svg, AttributeValue, toValue, (!))
+import qualified Text.Blaze.Svg11 as S
+import qualified Text.Blaze.Svg11.Attributes as A
+
+data Flat = Flat
+    { leftColor  :: Color
+    , rightColor :: Color
+    }
+
+instance Badge Flat where
+    badge Flat{..} = flat' leftColor rightColor
+
+instance HasLeftColor Flat where
+    left f (Flat l r) = fmap (\l' -> Flat l' r) (f l)
+
+instance HasRightColor Flat where
+    right f (Flat l r) = fmap (\r' -> Flat l r') (f r)
+
+flat :: Flat
+flat = Flat gray brightgreen
+
+flat' :: Color -> Color -> BadgeConfig -> Svg
+flat' (Color colorA) (Color colorB) BadgeConfig{..} = S.docTypeSvg ! A.width (toValue svgWidth) ! A.height "20" $ do
+    S.lineargradient ! A.id_ "smooth" ! A.x2 "0" ! A.y2 "100%" $ do
+        S.stop ! A.offset "0" ! A.stopColor "#bbb" ! A.stopOpacity ".1"
+        S.stop ! A.offset "1" ! A.stopOpacity ".1"
+
+    S.mask ! A.id_ "round" $
+        S.rect ! A.width (toValue svgWidth) ! A.height "20" ! A.rx "3" ! A.fill "#fff"
+
+    S.g ! A.mask "url(#round)" $ do
+        S.rect ! A.width (toValue widthLeft) ! A.height "20" ! A.fill (toValue colorA)
+        S.rect ! A.x (toValue widthLeft) ! A.width (toValue widthRight) ! A.height "20" ! A.fill (toValue colorB)
+        S.rect ! A.width (toValue svgWidth) ! A.height "20" ! A.fill "url(#smooth)"
+
+    S.g ! A.fill "#fff" ! A.textAnchor "middle" ! A.fontFamily "DejaVu Sans,Verdana,Geneva,sans-serif" ! A.fontSize "11" $ do
+        S.text_ (S.text textLeft)  ! A.x (float $ fromIntegral widthLeft / 2 + 1) ! A.y "15" ! A.fill "#010101" ! A.fillOpacity ".3"
+        S.text_ (S.text textLeft)  ! A.x (float $ fromIntegral widthLeft / 2 + 1) ! A.y "14"
+        S.text_ (S.text textRight) ! A.x (float $ fromIntegral widthLeft + fromIntegral widthRight / 2 - 1) ! A.y "15" ! A.fill "#010101" ! A.fillOpacity ".3"
+        S.text_ (S.text textRight) ! A.x (float $ fromIntegral widthLeft + fromIntegral widthRight / 2 - 1) ! A.y "14"
+        
+  where
+    svgWidth = widthLeft + widthRight
+    float :: Double -> AttributeValue
+    float = toValue
diff --git a/src/Graphics/Badge/Barrier/Style/FlatSquare.hs b/src/Graphics/Badge/Barrier/Style/FlatSquare.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Badge/Barrier/Style/FlatSquare.hs
@@ -0,0 +1,46 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+
+module Graphics.Badge.Barrier.Style.FlatSquare
+    ( FlatSquare(..)
+    , flatSquare
+    ) where
+
+import Graphics.Badge.Barrier.Internal
+import Graphics.Badge.Barrier.Color
+
+import Text.Blaze.Svg11(Svg, AttributeValue, toValue, (!))
+import qualified Text.Blaze.Svg11 as S
+import qualified Text.Blaze.Svg11.Attributes as A
+
+data FlatSquare = FlatSquare
+    { leftColor  :: Color
+    , rightColor :: Color
+    }
+
+instance Badge FlatSquare where
+    badge FlatSquare{..} = flatSquare' leftColor rightColor
+
+instance HasLeftColor FlatSquare where
+    left f (FlatSquare l r) = fmap (\l' -> FlatSquare l' r) (f l)
+
+instance HasRightColor FlatSquare where
+    right f (FlatSquare l r) = fmap (\r' -> FlatSquare l r') (f r)
+
+flatSquare :: FlatSquare
+flatSquare = FlatSquare gray brightgreen
+
+flatSquare' :: Color -> Color -> BadgeConfig -> Svg
+flatSquare' (Color colorA) (Color colorB) BadgeConfig{..} = S.docTypeSvg ! A.width (toValue svgWidth) ! A.height "20" $ do
+    S.g ! A.shapeRendering "crispEdges" $ do
+        S.rect ! A.width (toValue widthLeft) ! A.height "20" ! A.fill (toValue colorA)
+        S.rect ! A.x (toValue widthLeft) ! A.width (toValue widthRight) ! A.height "20" ! A.fill (toValue colorB)
+
+    S.g ! A.fill "#fff" ! A.textAnchor "middle" ! A.fontFamily "DejaVu Sans,Verdana,Geneva,sans-serif" ! A.fontSize "11" $ do
+        S.text_ (S.text textLeft)  ! A.x (float $ fromIntegral widthLeft / 2 + 1) ! A.y "14"
+        S.text_ (S.text textRight) ! A.x (float $ fromIntegral widthLeft + fromIntegral widthRight / 2 - 1) ! A.y "14"
+        
+  where
+    svgWidth = widthLeft + widthRight
+    float :: Double -> AttributeValue
+    float = toValue
diff --git a/src/Graphics/Badge/Barrier/Style/Plastic.hs b/src/Graphics/Badge/Barrier/Style/Plastic.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Badge/Barrier/Style/Plastic.hs
@@ -0,0 +1,58 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+
+module Graphics.Badge.Barrier.Style.Plastic
+    ( Plastic(..)
+    , plastic
+    ) where
+
+import Graphics.Badge.Barrier.Internal
+import Graphics.Badge.Barrier.Color
+
+import Text.Blaze.Svg11(Svg, AttributeValue, toValue, (!))
+import qualified Text.Blaze.Svg11 as S
+import qualified Text.Blaze.Svg11.Attributes as A
+
+data Plastic = Plastic
+    { leftColor  :: Color
+    , rightColor :: Color
+    }
+
+instance Badge Plastic where
+    badge Plastic{..} = plastic' leftColor rightColor
+
+instance HasLeftColor Plastic where
+    left f (Plastic l r) = fmap (\l' -> Plastic l' r) (f l)
+
+instance HasRightColor Plastic where
+    right f (Plastic l r) = fmap (\r' -> Plastic l r') (f r)
+
+plastic :: Plastic
+plastic = Plastic gray brightgreen
+
+plastic' :: Color -> Color -> BadgeConfig -> Svg
+plastic' (Color colorA) (Color colorB) BadgeConfig{..} = S.docTypeSvg ! A.width (toValue svgWidth) ! A.height "18" $ do
+    S.lineargradient ! A.id_ "smooth" ! A.x2 "0" ! A.y2 "100%" $ do
+        S.stop ! A.offset "0"   ! A.stopColor "#fff" ! A.stopOpacity ".7"
+        S.stop ! A.offset "0.1" ! A.stopColor "#aaa" ! A.stopOpacity ".1"
+        S.stop ! A.offset "0.9" ! A.stopColor "#000" ! A.stopOpacity ".3"
+        S.stop ! A.offset "1"   ! A.stopColor "#000" ! A.stopOpacity ".5"
+
+    S.mask ! A.id_ "round" $
+        S.rect ! A.width (toValue svgWidth) ! A.height "18" ! A.rx "4" ! A.fill "#fff"
+
+    S.g ! A.mask "url(#round)" $ do
+        S.rect ! A.width (toValue widthLeft) ! A.height "18" ! A.fill (toValue colorA)
+        S.rect ! A.x (toValue widthLeft) ! A.width (toValue widthRight) ! A.height "18" ! A.fill (toValue colorB)
+        S.rect ! A.width (toValue svgWidth) ! A.height "18" ! A.fill "url(#smooth)"
+
+    S.g ! A.fill "#fff" ! A.textAnchor "middle" ! A.fontFamily "DejaVu Sans,Verdana,Geneva,sans-serif" ! A.fontSize "11" $ do
+        S.text_ (S.text textLeft)  ! A.x (float $ fromIntegral widthLeft / 2 + 1) ! A.y "14" ! A.fill "#010101" ! A.fillOpacity ".3"
+        S.text_ (S.text textLeft)  ! A.x (float $ fromIntegral widthLeft / 2 + 1) ! A.y "13"
+        S.text_ (S.text textRight) ! A.x (float $ fromIntegral widthLeft + fromIntegral widthRight / 2 - 1) ! A.y "14" ! A.fill "#010101" ! A.fillOpacity ".3"
+        S.text_ (S.text textRight) ! A.x (float $ fromIntegral widthLeft + fromIntegral widthRight / 2 - 1) ! A.y "13"
+        
+  where
+    svgWidth = widthLeft + widthRight
+    float :: Double -> AttributeValue
+    float = toValue
diff --git a/tests/data/flat/1.svg b/tests/data/flat/1.svg
new file mode 100644
--- /dev/null
+++ b/tests/data/flat/1.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="91" height="20"><linearGradient id="smooth" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1" /><stop offset="1" stop-opacity=".1" /></linearGradient><mask id="round"><rect width="91" height="20" rx="3" fill="#fff" /></mask><g mask="url(#round)"><rect width="37" height="20" fill="#555" /><rect x="37" width="54" height="20" fill="#4c1" /><rect width="91" height="20" fill="url(#smooth)" /></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="19.5" y="15" fill="#010101" fill-opacity=".3">build</text><text x="19.5" y="14">build</text><text x="63.0" y="15" fill="#010101" fill-opacity=".3">success</text><text x="63.0" y="14">success</text></g></svg>
diff --git a/tests/data/flat/2.svg b/tests/data/flat/2.svg
new file mode 100644
--- /dev/null
+++ b/tests/data/flat/2.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="20"><linearGradient id="smooth" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1" /><stop offset="1" stop-opacity=".1" /></linearGradient><mask id="round"><rect width="81" height="20" rx="3" fill="#fff" /></mask><g mask="url(#round)"><rect width="37" height="20" fill="#555" /><rect x="37" width="44" height="20" fill="#e05d44" /><rect width="81" height="20" fill="url(#smooth)" /></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="19.5" y="15" fill="#010101" fill-opacity=".3">build</text><text x="19.5" y="14">build</text><text x="58.0" y="15" fill="#010101" fill-opacity=".3">failing</text><text x="58.0" y="14">failing</text></g></svg>
diff --git a/tests/data/flat/3.svg b/tests/data/flat/3.svg
new file mode 100644
--- /dev/null
+++ b/tests/data/flat/3.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="62" height="20"><linearGradient id="smooth" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1" /><stop offset="1" stop-opacity=".1" /></linearGradient><mask id="round"><rect width="62" height="20" rx="3" fill="#fff" /></mask><g mask="url(#round)"><rect width="31" height="20" fill="#97CA00" /><rect x="31" width="31" height="20" fill="#4c1" /><rect width="62" height="20" fill="url(#smooth)" /></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="16.5" y="15" fill="#010101" fill-opacity=".3">leaf</text><text x="16.5" y="14">leaf</text><text x="45.5" y="15" fill="#010101" fill-opacity=".3">leaf</text><text x="45.5" y="14">leaf</text></g></svg>
diff --git a/tests/data/flat/4.svg b/tests/data/flat/4.svg
new file mode 100644
--- /dev/null
+++ b/tests/data/flat/4.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="596" height="20"><linearGradient id="smooth" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1" /><stop offset="1" stop-opacity=".1" /></linearGradient><mask id="round"><rect width="596" height="20" rx="3" fill="#fff" /></mask><g mask="url(#round)"><rect width="298" height="20" fill="#555" /><rect x="298" width="298" height="20" fill="#4c1" /><rect width="596" height="20" fill="url(#smooth)" /></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="150.0" y="15" fill="#010101" fill-opacity=".3">longlonglonglonglonglonglonglonglonglonglonglong</text><text x="150.0" y="14">longlonglonglonglonglonglonglonglonglonglonglong</text><text x="446.0" y="15" fill="#010101" fill-opacity=".3">longlonglonglonglonglonglonglonglonglonglonglong</text><text x="446.0" y="14">longlonglonglonglonglonglonglonglonglonglonglong</text></g></svg>
diff --git a/tests/data/flatSquare/1.svg b/tests/data/flatSquare/1.svg
new file mode 100644
--- /dev/null
+++ b/tests/data/flatSquare/1.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="91" height="20"><g shape-rendering="crispEdges"><rect width="37" height="20" fill="#555" /><rect x="37" width="54" height="20" fill="#4c1" /></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="19.5" y="14">build</text><text x="63.0" y="14">success</text></g></svg>
diff --git a/tests/data/flatSquare/2.svg b/tests/data/flatSquare/2.svg
new file mode 100644
--- /dev/null
+++ b/tests/data/flatSquare/2.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="20"><g shape-rendering="crispEdges"><rect width="37" height="20" fill="#555" /><rect x="37" width="44" height="20" fill="#e05d44" /></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="19.5" y="14">build</text><text x="58.0" y="14">failing</text></g></svg>
diff --git a/tests/data/flatSquare/3.svg b/tests/data/flatSquare/3.svg
new file mode 100644
--- /dev/null
+++ b/tests/data/flatSquare/3.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="62" height="20"><g shape-rendering="crispEdges"><rect width="31" height="20" fill="#97CA00" /><rect x="31" width="31" height="20" fill="#4c1" /></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="16.5" y="14">leaf</text><text x="45.5" y="14">leaf</text></g></svg>
diff --git a/tests/data/flatSquare/4.svg b/tests/data/flatSquare/4.svg
new file mode 100644
--- /dev/null
+++ b/tests/data/flatSquare/4.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="596" height="20"><g shape-rendering="crispEdges"><rect width="298" height="20" fill="#555" /><rect x="298" width="298" height="20" fill="#4c1" /></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="150.0" y="14">longlonglonglonglonglonglonglonglonglonglonglong</text><text x="446.0" y="14">longlonglonglonglonglonglonglonglonglonglonglong</text></g></svg>
diff --git a/tests/data/plastic/1.svg b/tests/data/plastic/1.svg
new file mode 100644
--- /dev/null
+++ b/tests/data/plastic/1.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="91" height="18"><linearGradient id="smooth" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7" /><stop offset="0.1" stop-color="#aaa" stop-opacity=".1" /><stop offset="0.9" stop-color="#000" stop-opacity=".3" /><stop offset="1" stop-color="#000" stop-opacity=".5" /></linearGradient><mask id="round"><rect width="91" height="18" rx="4" fill="#fff" /></mask><g mask="url(#round)"><rect width="37" height="18" fill="#555" /><rect x="37" width="54" height="18" fill="#4c1" /><rect width="91" height="18" fill="url(#smooth)" /></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="19.5" y="14" fill="#010101" fill-opacity=".3">build</text><text x="19.5" y="13">build</text><text x="63.0" y="14" fill="#010101" fill-opacity=".3">success</text><text x="63.0" y="13">success</text></g></svg>
diff --git a/tests/data/plastic/2.svg b/tests/data/plastic/2.svg
new file mode 100644
--- /dev/null
+++ b/tests/data/plastic/2.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="18"><linearGradient id="smooth" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7" /><stop offset="0.1" stop-color="#aaa" stop-opacity=".1" /><stop offset="0.9" stop-color="#000" stop-opacity=".3" /><stop offset="1" stop-color="#000" stop-opacity=".5" /></linearGradient><mask id="round"><rect width="81" height="18" rx="4" fill="#fff" /></mask><g mask="url(#round)"><rect width="37" height="18" fill="#555" /><rect x="37" width="44" height="18" fill="#e05d44" /><rect width="81" height="18" fill="url(#smooth)" /></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="19.5" y="14" fill="#010101" fill-opacity=".3">build</text><text x="19.5" y="13">build</text><text x="58.0" y="14" fill="#010101" fill-opacity=".3">failing</text><text x="58.0" y="13">failing</text></g></svg>
diff --git a/tests/data/plastic/3.svg b/tests/data/plastic/3.svg
new file mode 100644
--- /dev/null
+++ b/tests/data/plastic/3.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="62" height="18"><linearGradient id="smooth" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7" /><stop offset="0.1" stop-color="#aaa" stop-opacity=".1" /><stop offset="0.9" stop-color="#000" stop-opacity=".3" /><stop offset="1" stop-color="#000" stop-opacity=".5" /></linearGradient><mask id="round"><rect width="62" height="18" rx="4" fill="#fff" /></mask><g mask="url(#round)"><rect width="31" height="18" fill="#97CA00" /><rect x="31" width="31" height="18" fill="#4c1" /><rect width="62" height="18" fill="url(#smooth)" /></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="16.5" y="14" fill="#010101" fill-opacity=".3">leaf</text><text x="16.5" y="13">leaf</text><text x="45.5" y="14" fill="#010101" fill-opacity=".3">leaf</text><text x="45.5" y="13">leaf</text></g></svg>
diff --git a/tests/data/plastic/4.svg b/tests/data/plastic/4.svg
new file mode 100644
--- /dev/null
+++ b/tests/data/plastic/4.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="596" height="18"><linearGradient id="smooth" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7" /><stop offset="0.1" stop-color="#aaa" stop-opacity=".1" /><stop offset="0.9" stop-color="#000" stop-opacity=".3" /><stop offset="1" stop-color="#000" stop-opacity=".5" /></linearGradient><mask id="round"><rect width="596" height="18" rx="4" fill="#fff" /></mask><g mask="url(#round)"><rect width="298" height="18" fill="#555" /><rect x="298" width="298" height="18" fill="#4c1" /><rect width="596" height="18" fill="url(#smooth)" /></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="150.0" y="14" fill="#010101" fill-opacity=".3">longlonglonglonglonglonglonglonglonglonglonglong</text><text x="150.0" y="13">longlonglonglonglonglonglonglonglonglonglonglong</text><text x="446.0" y="14" fill="#010101" fill-opacity=".3">longlonglonglonglonglonglonglonglonglonglonglong</text><text x="446.0" y="13">longlonglonglonglonglonglonglonglonglonglonglong</text></g></svg>
diff --git a/tests/tasty.hs b/tests/tasty.hs
new file mode 100644
--- /dev/null
+++ b/tests/tasty.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE OverloadedStrings #-}
+import Lens.Family
+import Graphics.Badge.Barrier
+
+import Test.Tasty
+import Test.Tasty.Golden
+
+main :: IO ()
+main = defaultMain $ testGroup ""
+    [ testGroup "flat"
+        [ goldenVsString "1" "tests/data/flat/1.svg" . return $ renderBadge flat "build" "success"
+        , goldenVsString "2" "tests/data/flat/2.svg" . return $ renderBadge (flat & right .~ red) "build" "failing"
+        , goldenVsString "3" "tests/data/flat/3.svg" . return $ renderBadge (flat & left .~ green) "leaf" "leaf"
+        , goldenVsString "4" "tests/data/flat/4.svg" . return $ renderBadge flat "longlonglonglonglonglonglonglonglonglonglonglong" "longlonglonglonglonglonglonglonglonglonglonglong"
+        ]
+    , testGroup "flatSquare"
+        [ goldenVsString "1" "tests/data/flatSquare/1.svg" . return $ renderBadge flatSquare "build" "success"
+        , goldenVsString "2" "tests/data/flatSquare/2.svg" . return $ renderBadge (flatSquare & right .~ red) "build" "failing"
+        , goldenVsString "3" "tests/data/flatSquare/3.svg" . return $ renderBadge (flatSquare & left .~ green) "leaf" "leaf"
+        , goldenVsString "4" "tests/data/flatSquare/4.svg" . return $ renderBadge flatSquare "longlonglonglonglonglonglonglonglonglonglonglong" "longlonglonglonglonglonglonglonglonglonglonglong"
+        ]
+    , testGroup "plastic"
+        [ goldenVsString "1" "tests/data/plastic/1.svg" . return $ renderBadge plastic "build" "success"
+        , goldenVsString "2" "tests/data/plastic/2.svg" . return $ renderBadge (plastic & right .~ red) "build" "failing"
+        , goldenVsString "3" "tests/data/plastic/3.svg" . return $ renderBadge (plastic & left .~ green) "leaf" "leaf"
+        , goldenVsString "4" "tests/data/plastic/4.svg" . return $ renderBadge plastic "longlonglonglonglonglonglonglonglonglonglonglong" "longlonglonglonglonglonglonglonglonglonglonglong"
+        ]
+    ]
