diff --git a/app/example.hs b/app/example.hs
--- a/app/example.hs
+++ b/app/example.hs
@@ -3,37 +3,38 @@
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedLabels #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeOperators #-}
 {-# OPTIONS_GHC -Wall #-}
 
-import Control.Category (id)
+import Prelude hiding (log, init)
 import Control.Lens hiding (Wrapped, Unwrapped)
-import Data.Attoparsec.Text
-import Lucid hiding (b_)
-import Network.Wai
-import Network.Wai.Middleware.RequestLogger
+import Data.Attoparsec.Text (parseOnly, decimal)
+import Lucid
+import Network.Wai (rawPathInfo)
+import Network.Wai.Middleware.RequestLogger (logStdoutDev)
 import Network.Wai.Middleware.Static (addBase, noDots, staticPolicy, (>->))
 import Options.Generic
-import Protolude hiding (replace, Rep, log)
 import Web.Page
 import Web.Page.Examples
-import Web.Scotty
+import Web.Scotty (scotty, middleware)
 import qualified Box
 import qualified Data.Text as Text
+import Data.Text (pack, Text)
+import Control.Monad
+import Data.Maybe
 
 testPage :: Text -> Text -> [(Text, Html ())] -> Page
 testPage title mid sections =
   bootstrapPage <>
   bridgePage &
   #htmlHeader .~ title_ "iroTestPage" &
-  #htmlBody .~ b_ "container" (mconcat
-    [ b_ "row" (h1_ (toHtml title))
-    , b_ "row" (h2_ ("middleware: " <> toHtml mid))
-    , b_ "row" $ mconcat $ (\(t,h) -> b_ "col" (h2_ (toHtml t) <> with div_ [id_ t] h)) <$> sections
+  #htmlBody .~ divClass_ "container" (mconcat
+    [ divClass_ "row" (h1_ (toHtml title))
+    , divClass_ "row" (h2_ ("middleware: " <> toHtml mid))
+    , divClass_ "row" $ mconcat $ (\(t,h) -> divClass_ "col" (h2_ (toHtml t) <> with div_ [id_ t] h)) <$> sections
     ])
 
 -- | bridge testing without the SharedRep method
@@ -72,14 +73,14 @@
       (\x -> Right (x,t))
       (parseOnly decimal v)
     step (Element "textid" v) (n, _) = Right (n,v)
-    step e' _ = Left $ "unknown id: " <> show e'
+    step e' _ = Left $ "unknown id: " <> pack (show e')
 
 sendBridgeTest :: (Show a) => Engine -> Either Text a -> IO ()
 sendBridgeTest e (Left err) = append e "log" err
 sendBridgeTest e (Right a) =
   replace e "output"
   (toText $ cardify (mempty, []) (Just "output was:")
-    (toHtml (show a :: Text), []))
+    (toHtml (show a), []))
 
 consumeBridgeTest :: Engine -> IO (Int, Text)
 consumeBridgeTest e =
@@ -90,15 +91,15 @@
 
 midBridgeTest :: (Show a) => Html () -> (Engine -> IO a) -> Application -> Application
 midBridgeTest init eeio = start $ \ e -> do
-  appendWithScript e "input" (toText init)
-  final <- eeio e `finally` putStrLn ("midBridgeTest finalled" :: Text)
-  putStrLn $ ("final value was: " :: Text) <> show final
+  append e "input" (toText init)
+  final <- eeio e `finally` putStrLn "midBridgeTest finalled"
+  putStrLn $ "final value was: " <> show final
 
 -- * SharedRep testing
 
 -- | Middleware that shows the current shared values
 midShow :: (Show a) => SharedRep IO a -> Application -> Application
-midShow sr = midShared sr initShowRep (logResults show)
+midShow sr = midShared sr initShowRep (logResults (pack . show))
 
 initShowRep
   :: (Show a)
@@ -108,8 +109,8 @@
 initShowRep e r =
   void $ oneRep r
   (\(Rep h fa) m -> do
-      appendWithScript e "input" (toText h)
-      replace e "output" (show (fa m)))
+      append e "input" (toText h)
+      replace e "output" (pack . show $ fa m))
 
 results :: (a -> Text) -> Engine -> a -> IO ()
 results r e x = replace e "output" (r x)
@@ -129,7 +130,7 @@
 initFiddleRep e r =
   void $ oneRep r
   (\(Rep h _) _ ->
-      appendWithScript e "input" (toText h))
+      append e "input" (toText h))
 
 logFiddle :: Engine -> Either Text (Either Text (Concerns Text, Bool)) -> IO ()
 logFiddle e (Left err) = append e "log" ("map error: " <> err)
@@ -137,13 +138,12 @@
 logFiddle e (Right (Right (c,u))) = bool (pure ()) (sendConcerns e "output" c) u
 
 -- | evaluate a Fiddle, and any downstream bridging representation
-
 midViaFiddle
   :: Show a
   => SharedRep IO a
   -> Application -> Application
 midViaFiddle sr =
-  midShared (viaFiddle sr) (initViaFiddleRep show) (\e -> logViaFiddle e show . second snd)
+  midShared (viaFiddle sr) (initViaFiddleRep (pack . show)) (\e -> logViaFiddle e (pack . show) . second snd)
 
 initViaFiddleRep
   :: (a -> Text)
@@ -153,7 +153,7 @@
 initViaFiddleRep rend e r =
   void $ oneRep r
   (\(Rep h fa) m -> do
-      appendWithScript e "input" (toText h)
+      append e "input" (toText h)
       case (snd $ fa m) of
         Left err -> append e "log" ("map error: " <> err)
         Right (_,c,a) -> do
@@ -168,7 +168,7 @@
   replace e "output" (r a)
 logViaFiddle e r (Right (Right (False,_,a))) = replace e "output" (r a)
 
-data MidType = Dev | Prod | ChooseFileExample | DataListExample | SumTypeExample | SumType2Example | Bridge | Listify | ListifyMaybe | Fiddle | ViaFiddle | NoMid deriving (Eq, Read, Show, Generic)
+data MidType = Dev | Prod | ChooseFileExample | DataListExample | SumTypeExample | SumType2Example | Bridge | ListExample | ListRepExample | Fiddle | ViaFiddle | NoMid deriving (Eq, Read, Show, Generic)
 
 instance ParseField MidType
 instance ParseRecord MidType
@@ -193,7 +193,7 @@
       middleware logStdoutDev
     when (tr $ logPath o) $
       middleware $ \app req res ->
-        putStrLn ("raw path:" :: Text) >>
+        putStrLn "raw path:" >>
         print (rawPathInfo req) >> app req res
   -- Only one middleware servicing the web socket can be run at a time.  Simply switching on based on paths doesn't work because socket comms comes through "/"
   -- so that the first bridge middleware consumes all the elements
@@ -212,25 +212,25 @@
         (repSumTypeExample 2 "default text" SumOnly)
       SumType2Example -> midShow
         (repSumType2Example 2 "default text" SumOnly (SumOutside 2))
-      Listify -> midShow (listifyExample 5)
-      ListifyMaybe -> midShow (listifyMaybeExample 10)
+      ListExample -> midShow (listExample 5)
+      ListRepExample -> midShow (listRepExample 10)
       Bridge -> midBridgeTest (toHtml rangeTest <> toHtml textTest)
         consumeBridgeTest
       Fiddle -> midFiddle fiddleExample
       ViaFiddle -> midViaFiddle
         (slider Nothing 0 10 0.01 4)
-    servePageWith "/simple" defaultPageConfig page1
-    servePageWith "/iro" defaultPageConfig
-      (testPage "iro" (show $ midtype o)
+    servePageWith "/simple" (defaultPageConfig "page1") page1
+    servePageWith "/iro" (defaultPageConfig "iro")
+      (testPage "iro" (pack . show $ midtype o)
         [ ("input", mempty)
         , ("representation", mempty)
         , ("output", mempty)
         ])
-    servePageWith "/" defaultPageConfig
-      (testPage "prod" (show $ midtype o)
+    servePageWith "/" (defaultPageConfig "prod")
+      (testPage "prod" (pack . show $ midtype o)
        [ ("input", mempty)
        , ("output",
           (bool mempty
-            (toHtml (show initBridgeTest :: Text))
+            (toHtml (show initBridgeTest))
             (midtype o == Bridge)))
        ])
diff --git a/readme.md b/readme.md
new file mode 100644
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,32 @@
+[web-rep](https://github.com/tonyday567/web-rep) [![Build Status](https://travis-ci.org/tonyday567/web-rep.svg)](https://travis-ci.org/tonyday567/web-rep)
+===
+
+Various functions and representations for a web page.
+
+
+recipes
+---
+
+```
+stack build --test --exec "$(stack path --local-install-root)/bin/page-example --midtype Prod" --file-watch
+stack build web-rep:test:test --file-watch --ghc-options -freverse-errors
+```
+
+reference
+---
+
+- beam me up [scotty](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/flags.html#flag-reference)
+- [scotty-starter](https://github.com/scotty-web/scotty-starter)
+- get [bootstrap](https://getbootstrap.com/)
+- [bootstrap-slider](https://seiyria.com/bootstrap-slider)
+- [blaze](http://hackage.haskell.org/package/blaze-html)
+- [lucid](http://hackage.haskell.org/package/lucid)
+- [clay](https://www.stackage.org/clay)
+- [javascript-bridge](https://github.com/ku-fpg/javascript-bridge)
+
+
+todo
+---
+
+https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#Do_not_ever_use_eval!
+
diff --git a/src/Web/Page.hs b/src/Web/Page.hs
--- a/src/Web/Page.hs
+++ b/src/Web/Page.hs
@@ -1,42 +1,41 @@
+
+-- | haskell for web page representations
+
 module Web.Page
-  ( renderJs
-  , renderCss
-  , renderHtml
-  , module X
+  ( module X
   , Value(..)
   , finally
   , PixelRGB8(..)
   , HashMap.HashMap(..)
   , fromList
+  , void
+  , sequenceA_
+  , Text
+  , pack
+  , unpack
+  , bool
   ) where
 
-import Protolude hiding (Selector)
-import Web.Page.Css as X
-import Web.Page.Js as X
+import Web.Page.SharedReps as X
 import Web.Page.Render as X
 import Web.Page.Server as X
 import Web.Page.Types as X
 import Web.Page.Bridge as X
-import Web.Page.Rep as X
-import Web.Page.Rep.Input as X
 import Web.Page.Html as X
 import Web.Page.Html.Input as X
 import Web.Page.Bootstrap as X
 import Text.InterpolatedString.Perl6 as X
+import Control.Monad.Trans.State as X
+import Data.Bifunctor as X
+import Control.Applicative as X
+import Data.Biapplicative as X
 import Control.Exception (finally)
-
+import Data.Text.Lazy (toStrict)
 import GHC.Exts (fromList)
 import qualified Data.HashMap.Strict as HashMap
-import qualified Web.Page.Css as Css (render)
-import qualified Web.Page.Js as Js
 import Data.Aeson (Value(..))
 import Codec.Picture.Types (PixelRGB8(..))
-
-renderJs :: JS -> Text
-renderJs = toStrict . Js.renderToText . Js.unJS
-
-renderCss :: Css -> Text
-renderCss = toStrict . Css.render
-
-renderHtml :: Html a -> Text
-renderHtml = toText
+import Control.Monad
+import Data.Foldable (sequenceA_)
+import Data.Text (Text, pack, unpack)
+import Data.Bool
diff --git a/src/Web/Page/Bootstrap.hs b/src/Web/Page/Bootstrap.hs
--- a/src/Web/Page/Bootstrap.hs
+++ b/src/Web/Page/Bootstrap.hs
@@ -4,125 +4,162 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# OPTIONS_GHC -Wall #-}
 
+-- | some <https://getbootstrap.com/ bootstrap> assets
 module Web.Page.Bootstrap
-  ( bootstrapPage
-  , cardify
-  , b_
-  , accordion
-  , accordionChecked
-  , accordionCardChecked
-  , accordion_
-  ) where
+  ( bootstrapPage,
+    cardify,
+    divClass_,
+    accordion,
+    accordionChecked,
+    accordionCardChecked,
+    accordion_,
+  )
+where
 
-import Lucid hiding (b_)
+import Lucid
 import Lucid.Base
-import Protolude
+import Prelude
 import Web.Page.Html
 import Web.Page.Types
+import Data.Text (Text)
+import Control.Monad.State
+import Data.Bool
+import Data.Functor.Identity
 
 bootstrapCss :: [Html ()]
 bootstrapCss =
-  [link_
-  [ rel_ "stylesheet"
-  , href_ "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
-  , integrity_ "sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
-  , crossorigin_ "anonymous"
-  ]]
+  [ link_
+      [ rel_ "stylesheet",
+        href_ "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css",
+        integrity_ "sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T",
+        crossorigin_ "anonymous"
+      ]
+  ]
 
 bootstrapJs :: [Html ()]
 bootstrapJs =
-  [ with (script_ mempty)
-    [ src_ "https://code.jquery.com/jquery-3.3.1.slim.min.js"
-    , integrity_ "sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
-    , crossorigin_ "anonymous"
-    ]
-  , with (script_ mempty)
-    [ src_ "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
-    , integrity_ "sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
-    , crossorigin_ "anonymous"
-    ]
-  , with (script_ mempty)
-    [ src_ "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
-    , integrity_ "sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
-    , crossorigin_ "anonymous"
-    ]
+  [ with
+      (script_ mempty)
+      [ src_ "https://code.jquery.com/jquery-3.3.1.slim.min.js",
+        integrity_ "sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo",
+        crossorigin_ "anonymous"
+      ],
+    with
+      (script_ mempty)
+      [ src_ "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js",
+        integrity_ "sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1",
+        crossorigin_ "anonymous"
+      ],
+    with
+      (script_ mempty)
+      [ src_ "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js",
+        integrity_ "sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM",
+        crossorigin_ "anonymous"
+      ]
   ]
 
 bootstrapMeta :: [Html ()]
 bootstrapMeta =
-  [ meta_ [charset_ "utf-8"]
-  , meta_ [ name_ "viewport"
-          , content_ "width=device-width, initial-scale=1, shrink-to-fit=no"]
+  [ meta_ [charset_ "utf-8"],
+    meta_
+      [ name_ "viewport",
+        content_ "width=device-width, initial-scale=1, shrink-to-fit=no"
+      ]
   ]
 
+-- | A page containing all the <https://getbootstrap.com/ bootstrap> needs for a web page.
 bootstrapPage :: Page
 bootstrapPage =
   Page
-  bootstrapCss
-  bootstrapJs
-  mempty
-  mempty
-  mempty
-  (mconcat bootstrapMeta)
-  mempty
+    bootstrapCss
+    bootstrapJs
+    mempty
+    mempty
+    mempty
+    (mconcat bootstrapMeta)
+    mempty
 
--- | wrap some Html with the bootstrap card class
+-- | wrap some Html with the bootstrap <https://getbootstrap.com/docs/4.3/components/card/ card> class
 cardify :: (Html (), [Attribute]) -> Maybe Text -> (Html (), [Attribute]) -> Html ()
 cardify (h, hatts) t (b, batts) =
   with div_ ([class__ "card"] <> hatts) $
-   h <>
-   with
-   div_ ([class__ "card-body"] <> batts)
-   (maybe mempty (with h5_ [class__ "card-title"] . toHtml) t <>
-    b)
+    h
+      <> with
+        div_
+        ([class__ "card-body"] <> batts)
+        ( maybe mempty (with h5_ [class__ "card-title"] . toHtml) t
+            <> b
+        )
 
 -- | wrap some html with a classed div
-b_ :: Text -> Html () -> Html ()
-b_ t = with div_ [class__ t]
+divClass_ :: Text -> Html () -> Html ()
+divClass_ t = with div_ [class__ t]
 
 accordionCard :: Bool -> [Attribute] -> Text -> Text -> Text -> Text -> Html () -> Html ()
 accordionCard collapse atts idp idh idb t0 b =
   with div_ ([class__ "card"] <> atts) $
-    with div_ [class__ "card-header", id_ idh]
-      (with h2_ [class__ "mb-0"]
-        (with button_ [class__ ("btn btn-link" <> bool "" " collapsed" collapse), type_ "button", data_ "toggle" "collapse", data_ "target" ("#" <> idb), makeAttribute "aria-expanded" (bool "true" "false" collapse), makeAttribute "aria-controls" idb ] (toHtml t0))) <>
-    with div_ [id_ idb, class__ ("collapse" <> bool " show" "" collapse), makeAttribute "aria-labelledby" idh, data_ "parent" ("#" <> idp)]
-    (with div_ [class__ "card-body"] b)
+    with
+      div_
+      [class__ "card-header", id_ idh]
+      ( with
+          h2_
+          [class__ "mb-0"]
+          (with button_ [class__ ("btn btn-link" <> bool "" " collapsed" collapse), type_ "button", data_ "toggle" "collapse", data_ "target" ("#" <> idb), makeAttribute "aria-expanded" (bool "true" "false" collapse), makeAttribute "aria-controls" idb] (toHtml t0))
+      )
+      <> with
+        div_
+        [id_ idb, class__ ("collapse" <> bool " show" "" collapse), makeAttribute "aria-labelledby" idh, data_ "parent" ("#" <> idp)]
+        (with div_ [class__ "card-body"] b)
 
 accordionCardChecked :: Bool -> Text -> Text -> Text -> Text -> Html () -> Html () -> Html ()
 accordionCardChecked collapse idp idh idb label bodyhtml checkhtml =
   with div_ ([class__ "card"]) $
-    with div_ ([class__ "card-header", id_ idh])
-      (checkhtml <>
-       with h2_ [class__ "mb-0"]
-        (with button_ [class__ ("btn btn-link" <> bool "" " collapsed" collapse), type_ "button", data_ "toggle" "collapse", data_ "target" ("#" <> idb), makeAttribute "aria-expanded" (bool "true" "false" collapse), makeAttribute "aria-controls" idb ] (toHtml label))) <>
-    with div_ [id_ idb, class__ ("collapse" <> bool " show" "" collapse), makeAttribute "aria-labelledby" idh, data_ "parent" ("#" <> idp)]
-    (with div_ ([class__ "card-body"]) bodyhtml)
+    with
+      div_
+      ([class__ "card-header", id_ idh])
+      ( checkhtml
+          <> with
+            h2_
+            [class__ "mb-0"]
+            (with button_ [class__ ("btn btn-link" <> bool "" " collapsed" collapse), type_ "button", data_ "toggle" "collapse", data_ "target" ("#" <> idb), makeAttribute "aria-expanded" (bool "true" "false" collapse), makeAttribute "aria-controls" idb] (toHtml label))
+      )
+      <> with
+        div_
+        [id_ idb, class__ ("collapse" <> bool " show" "" collapse), makeAttribute "aria-labelledby" idh, data_ "parent" ("#" <> idp)]
+        (with div_ ([class__ "card-body"]) bodyhtml)
 
 -- | create a bootstrapped accordian class
-accordion :: (MonadState Int m) => Text -> Maybe Text -> [(Text, Html ())] -> m (Html ())
+accordion ::
+  (MonadState Int m) =>
+  Text ->
+  -- | name prefix.  This is needed because an Int doesn't seem to be a valid name.
+  Maybe Text ->
+  -- | card title
+  [(Text, Html ())] ->
+  -- | title, html tuple for each item in the accordion.
+  m (Html ())
 accordion pre x hs = do
   idp' <- genNamePre pre
   with div_ [class__ "accordion", id_ idp'] <$> aCards idp'
-    where
-      aCards par = mconcat <$> sequence (aCard par <$> hs)
-      aCard par (t,b) = do
-        idh <- genNamePre pre
-        idb <- genNamePre pre
-        pure $ accordionCard (x /= Just t) [] par idh idb t b
+  where
+    aCards par = mconcat <$> sequence (aCard par <$> hs)
+    aCard par (t, b) = do
+      idh <- genNamePre pre
+      idb <- genNamePre pre
+      pure $ accordionCard (x /= Just t) [] par idh idb t b
 
 -- | create a bootstrapped accordian class
 accordionChecked :: (MonadState Int m) => Text -> [(Text, Html (), Html ())] -> m (Html ())
 accordionChecked pre hs = do
   idp' <- genNamePre pre
   with div_ [class__ "accordion", id_ idp'] <$> aCards idp'
-    where
-      aCards par = mconcat <$> sequence (aCard par <$> hs)
-      aCard par (l,bodyhtml,checkhtml) = do
-        idh <- genNamePre pre
-        idb <- genNamePre pre
-        pure $ accordionCardChecked True par idh idb l bodyhtml checkhtml
+  where
+    aCards par = mconcat <$> sequence (aCard par <$> hs)
+    aCard par (l, bodyhtml, checkhtml) = do
+      idh <- genNamePre pre
+      idb <- genNamePre pre
+      pure $ accordionCardChecked True par idh idb l bodyhtml checkhtml
 
+-- | This version of accordion runs a local state for naming, and will cause name clashes if the prefix is not unique.
 accordion_ :: Text -> Maybe Text -> [(Text, Html ())] -> Html ()
 accordion_ pre x hs = runIdentity $ evalStateT (accordion pre x hs) 0
-
diff --git a/src/Web/Page/Bridge.hs b/src/Web/Page/Bridge.hs
--- a/src/Web/Page/Bridge.hs
+++ b/src/Web/Page/Bridge.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedLabels #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes #-}
@@ -6,36 +5,48 @@
 {-# OPTIONS_GHC -Wredundant-constraints #-}
 
 module Web.Page.Bridge
-  ( bridgePage
-  , sendc
-  , append
-  , replace
-  , appendWithScript
-  , replaceWithScript
-  , bridge
-  , sendConcerns
-  , Engine
-  , start
-  , Application
-  , midShared
-  ) where
+  ( bridgePage,
+    append,
+    replace,
+    bridge,
+    sendConcerns,
+    Engine,
+    start,
+    Application,
+    valueConsume,
+    sharedConsume,
+    runList,
+    runOnEvent,
+    midShared,
+  )
+where
 
-import Box.Cont
+import Box
+import Box.Cont ()
+import qualified Control.Foldl as L
 import Control.Lens
-import Data.Aeson (Value)
+import Control.Monad.Morph
+import Data.Aeson
 import Data.HashMap.Strict as HashMap
+import qualified Data.Text as Text
 import Lucid
-import Network.JavaScript (Engine, start, send, command, addListener, JavaScript(..), Application)
-import Protolude hiding (replace, Rep)
+import Network.JavaScript (Application, Engine, JavaScript (..), addListener, command, send, start)
+import qualified Streaming.Prelude as S
 import Text.InterpolatedString.Perl6
 import Web.Page.Html
-import Web.Page.Js
-import Web.Page.Rep
 import Web.Page.Types
-import qualified Data.Text as Text
+import Prelude hiding (init)
+import Data.Text (Text, pack)
+import Data.Text.Lazy (fromStrict)
+import Control.Monad.State
+import GHC.Conc
 
+-- | prevent the Enter key from triggering an event
 preventEnter :: PageJs
-preventEnter = PageJs $ fromText [q|
+preventEnter =
+  PageJs $
+    parseJs
+      [q|
 window.addEventListener('keydown',function(e) {
   if(e.keyIdentifier=='U+000A' || e.keyIdentifier=='Enter' || e.keyCode==13) {
     if(e.target.nodeName=='INPUT' && e.target.type !== 'textarea') {
@@ -46,16 +57,22 @@
 }, true);
 |]
 
+-- | create a web socket for event data
 webSocket :: PageJs
-webSocket = PageJsText [q|
+webSocket =
+  PageJsText
+    [q|
 window.jsb = {ws: new WebSocket('ws://' + location.host + '/')};
 jsb.ws.onmessage = (evt) => eval(evt.data);
 |]
 
--- see https://ghinda.net/article/script-tags/
+-- | script injection js.
+--
+-- See https://ghinda.net/article/script-tags/ for why this is needed.
 runScriptJs :: PageJs
-runScriptJs = PageJsText [q|
-
+runScriptJs =
+  PageJsText
+    [q|
 function insertScript ($script) {
   var s = document.createElement('script')
   s.type = 'text/javascript'
@@ -83,75 +100,153 @@
 }
 |]
 
+-- | componentry to kick off a javascript-bridge enabled page
 bridgePage :: Page
 bridgePage =
-  mempty &
-  #jsGlobal .~ (preventEnter <> runScriptJs) &
-  #jsOnLoad .~ webSocket
+  mempty
+    & #jsGlobal .~ (preventEnter <> runScriptJs)
+    & #jsOnLoad .~ webSocket
 
 sendc :: Engine -> Text -> IO ()
 sendc e = send e . command . JavaScript . fromStrict
 
+-- | replace a container and run any embedded scripts
 replace :: Engine -> Text -> Text -> IO ()
-replace e d t = send e $ command
-  [qc|
+replace e d t =
+  send e $
+    command
+      [qc|
      var $container = document.getElementById('{d}')
      $container.innerHTML = '{clean t}'
      runScripts($container)
      |]
 
+-- | append to a container and run any embedded scripts
 append :: Engine -> Text -> Text -> IO ()
-append e d t = send e $ command
-    [qc|
+append e d t =
+  send e $
+    command
+      [qc|
      var $container = document.getElementById('{d}')
      $container.innerHTML += '{clean t}'
      runScripts($container)
      |]
 
-replaceWithScript :: Engine -> Text -> Text -> IO ()
-replaceWithScript e d t = send e $ command
-  [qc|
-     var $container = document.getElementById('{d}')
-     $container.innerHTML = '{clean t}'
-     runScripts($container)
-     |]
-
-appendWithScript :: Engine -> Text -> Text -> IO ()
-appendWithScript e d t = send e $ command
-    [qc|
-     var $container = document.getElementById('{d}')
-     $container.innerHTML += '{clean t}'
-     runScripts($container)
-     |]
+clean :: Text -> Text
+clean =
+  Text.intercalate "\\'" . Text.split (== '\'')
+    . Text.intercalate "\\n"
+    . Text.lines
 
+-- | send css, js and html over the bridge
 sendConcerns :: Engine -> Text -> Concerns Text -> IO ()
 sendConcerns e t (Concerns c j h) = do
-  replaceWithScript e t h
+  replace e t h
   append e t (toText $ style_ c)
   sendc e j
 
+-- | The javascript bridge continuation.
 bridge :: Engine -> Cont_ IO Value
 bridge e = Cont_ $ \vio -> void $ addListener e vio
 
-clean :: Text -> Text
-clean =
-  Text.intercalate "\\'" . Text.split (=='\'') .
-  Text.intercalate "\\n" . Text.lines
+fromJson' :: (FromJSON a) => Value -> Either Text a
+fromJson' v = case fromJSON v of
+  (Success a) -> Right a
+  (Error e) -> Left $ "Json conversion error: " <> Text.pack e <> " of " <> (pack . show) v
 
--- | create Wai Middleware for a SharedRep providing an initialiser and action on events
+valueModel :: (FromJSON a, MonadState s m) => (a -> s -> s) -> S.Stream (S.Of Value) m () -> S.Stream (S.Of (Either Text s)) m ()
+valueModel step s =
+  s
+    & S.map fromJson'
+    & S.partitionEithers
+    & hoist (S.chain (modify . step))
+    & hoist (S.mapM (const get))
+    & S.unseparate
+    & S.maps S.sumToEither
+
+-- | consume an Element using a Committer and a Value continuation
+valueConsume :: s -> (Element -> s -> s) -> Cont IO (Committer IO (Either Text s)) -> Cont_ IO Value -> IO s
+valueConsume init step comm vio = do
+  (c, e) <- atomically $ ends Unbounded
+  with_ vio (atomically . c)
+  etcM
+    init
+    (Transducer (valueModel step))
+    (Box <$> comm <*> (liftE <$> pure (Emitter (Just <$> e))))
+
+stepM :: MonadState s m => (s -> (s, b)) -> (a -> s -> s) -> a -> m (s, b)
+stepM sr step v = do
+  hm <- get
+  let (hm', b) = sr $ step v hm
+  put hm'
+  pure (hm', b)
+
+sharedModel :: (FromJSON a, MonadState s m) => (s -> (s, Either Text b)) -> (a -> s -> s) -> S.Stream (S.Of Value) m () -> S.Stream (S.Of (Either Text (s, Either Text b))) m ()
+sharedModel sr step s =
+  s
+    & S.map fromJson'
+    & S.partitionEithers
+    & hoist (S.mapM (stepM sr step))
+    & S.unseparate
+    & S.maps S.sumToEither
+
+-- | consume shared values using a step function, a continuation committer, and a Value continuation.
+sharedConsume :: (s -> (s, Either Text b)) -> s -> (Element -> s -> s) -> Cont IO (Committer IO (Either Text (s, Either Text b))) -> Cont_ IO Value -> IO s
+sharedConsume sh init step comm vio = do
+  (c, e) <- atomically $ ends Unbounded
+  with_ vio (atomically . c)
+  etcM
+    init
+    (Transducer (sharedModel sh step))
+    (Box <$> comm <*> (liftE <$> pure (Emitter (Just <$> e))))
+
+-- | run a SharedRep using an initial state, a step function that consumes the shared model, and a value continuation
+runOnEvent ::
+  SharedRep IO a ->
+  (Rep a -> StateT (Int, HashMap Text Text) IO ()) ->
+  (Either Text (HashMap Text Text, Either Text a) -> IO ()) ->
+  Cont_ IO Value ->
+  IO (HashMap Text Text)
+runOnEvent sr hio eaction cv = flip evalStateT (0, HashMap.empty) $ do
+  (Rep h fa) <- unrep sr
+  hio (Rep h fa)
+  m <- zoom _2 get
+  liftIO $
+    sharedConsume
+      fa
+      m
+      (\(Element k v) s -> insert k v s)
+      (pure (Committer (\v -> eaction v >> pure True)))
+      cv
+
+-- | create Wai Middleware for a 'SharedRep' providing an initialiser and action on events
 midShared ::
-  ( ) =>
+  () =>
   SharedRep IO a ->
   (Engine -> Rep a -> StateT (HashMap Text Text) IO ()) ->
   (Engine -> Either Text (HashMap Text Text, Either Text a) -> IO ()) ->
-  Application -> Application
+  Application ->
+  Application
 midShared sr init action = start $ \e ->
-  void $ runOnEvent
-  sr
-  (zoom _2 . init e)
-  (action e)
-  (bridge e)
-
-
-
+  void $
+    runOnEvent
+      sr
+      (zoom _2 . init e)
+      (action e)
+      (bridge e)
 
+-- | process a list of Values
+runList ::
+  (Monad m) =>
+  SharedRep m a ->
+  [Value] ->
+  m [Either Text (HashMap Text Text, Either Text a)]
+runList sr vs = S.fst' <$> do
+  (faStep, (_, hm)) <- flip runStateT (0, HashMap.empty) $ do
+    (Rep _ fa) <- unrep sr
+    pure fa
+  flip evalStateT hm $
+    L.purely
+      S.fold
+      L.list
+      (sharedModel faStep (\(Element k v) s -> insert k v s) (S.each vs))
diff --git a/src/Web/Page/Css.hs b/src/Web/Page/Css.hs
deleted file mode 100644
--- a/src/Web/Page/Css.hs
+++ /dev/null
@@ -1,68 +0,0 @@
-{-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE OverloadedStrings #-}
-
-module Web.Page.Css
-  ( fill
-  , stroke
-  , strokeWidth
-  , crispEdges
-  , optimizeSpeed
-  , geometricPrecision
-  , shapeRendering
-  , Css
-  , render
-  , renderWith
-  , compact
-  , PageCss(..)
-  ) where
-
-import Clay hiding (optimizeSpeed, geometricPrecision, PlayState)
-import Clay.Stylesheet (key)
-import Data.Text
-import Data.Text.Lazy (unpack)
-import Protolude
-import qualified GHC.Show
-
-instance Show Css where
-  show = Data.Text.Lazy.unpack . render
-
-instance Eq Css where
-  (==) a' b' = (Protolude.show a' :: Text) == Protolude.show b'
-
-data PageCss = PageCss Css | PageCssText Text deriving (Eq, Show, Generic)
-
-instance Semigroup PageCss where
-  (<>) (PageCss css) (PageCss css') = PageCss (css <> css')
-  (<>) (PageCssText css) (PageCssText css') = PageCssText (css <> css')
-  (<>) (PageCss css) (PageCssText css') =
-    PageCssText (show css <> css')
-  (<>) (PageCssText css) (PageCss css') =
-    PageCssText (css <> show css')
-
-instance Monoid PageCss where
-  mempty = PageCssText mempty
-  mappend = (<>)
-
--- a few SVG css
-fill :: Color -> Css
-fill = key "fill"
-
-stroke :: Color -> Css
-stroke = key "stroke"
-
-strokeWidth :: Size Position -> Css
-strokeWidth = key "stroke-width"
-
-newtype ShapeRendering = ShapeRendering Value
-  deriving (Inherit, Auto, Val)
-
-crispEdges, optimizeSpeed, geometricPrecision :: ShapeRendering
-crispEdges = ShapeRendering "crispEdges"
-optimizeSpeed = ShapeRendering "optimizeSpeed"
-geometricPrecision = ShapeRendering "geometricPrecision"
-
-shapeRendering :: ShapeRendering -> Css
-shapeRendering = key "shape-rendering"
diff --git a/src/Web/Page/Examples.hs b/src/Web/Page/Examples.hs
--- a/src/Web/Page/Examples.hs
+++ b/src/Web/Page/Examples.hs
@@ -20,19 +20,18 @@
   , repSumTypeExample
   , SumType2Example(..)
   , repSumType2Example
-  , listifyExample
-  , listifyMaybeExample
+  , listExample
+  , listRepExample
   , fiddleExample
   ) where
 
-import Control.Category (id)
 import Control.Lens hiding ((.=))
 import Data.Attoparsec.Text
-import Data.Biapplicative
 import Lucid
-import Protolude hiding ((<<*>>))
+import Prelude
 import Web.Page
 import qualified Clay
+import GHC.Generics
 
 -- | simple page examples
 page1 :: Page
@@ -58,7 +57,7 @@
   #structure .~ Headless $
   #localdirs .~ ["test/static"] $
   #filenames .~ (("other/cfg2" <>) <$> suffixes) $
-  defaultPageConfig
+  (defaultPageConfig "")
 
 cssLibs :: [Text]
 cssLibs =
@@ -131,7 +130,7 @@
   ds' <- slider (Just "double slider") 0 1 0.1 0.5
   c <- checkbox (Just "checkbox") True
   tog <- toggle (Just "toggle") False
-  dr <- dropdown decimal show (Just "dropdown") (show <$> [1..5::Int]) 3
+  dr <- dropdown decimal (pack . show) (Just "dropdown") ((pack . show) <$> [1..5::Int]) 3
   drt <- toShape <$> dropdown takeText id (Just "shape") (["Circle", "Square"]) (fromShape SquareShape)
   col <- colorPicker (Just "color") (PixelRGB8 56 128 200)
   pure (RepExamples t ta n ds' c tog dr drt col)
@@ -139,14 +138,14 @@
 -- encodeFile "saves/rep2.json" $ RepExamples "text1" "text2" 1 1.0 True True 2 (PixelRGB8 0 100 0)
 -- decodeFileStrict "saves/rep2.json" :: IO (Maybe RepExamples)
 
-listifyExample :: (Monad m) => Int -> SharedRep m [Int]
-listifyExample n =
-  accordionListify (Just "accordianListify") "al" Nothing
-  (\l a -> sliderI (Just l) (0::Int) n 1 a) ((\x -> "[" <> show x <> "]") <$> [0..n] :: [Text]) [0..n]
+listExample :: (Monad m) => Int -> SharedRep m [Int]
+listExample n =
+  accordionList (Just "accordianListify") "al" Nothing
+  (\l a -> sliderI (Just l) (0::Int) n 1 a) ((\x -> "[" <> (pack . show) x <> "]") <$> [0..n] :: [Text]) [0..n]
 
-listifyMaybeExample :: (Monad m) => Int -> SharedRep m [Int]
-listifyMaybeExample n =
-  listifyMaybe' (Just "listifyMaybe") "alm" (checkbox Nothing)
+listRepExample :: (Monad m) => Int -> SharedRep m [Int]
+listRepExample n =
+  listRep (Just "listifyMaybe") "alm" (checkbox Nothing)
     (sliderI Nothing (0::Int) n 1) n 3 [0..4]
 
 fiddleExample :: Concerns Text
diff --git a/src/Web/Page/Html.hs b/src/Web/Page/Html.hs
--- a/src/Web/Page/Html.hs
+++ b/src/Web/Page/Html.hs
@@ -16,17 +16,21 @@
 
 import Data.Text
 import Lucid
-import Protolude hiding ((%))
+import Prelude
 import qualified Data.Text.Lazy as Lazy
 import Codec.Picture.Types (PixelRGB8(..))
 import Data.Attoparsec.Text
 import Numeric
 import Data.Text.Format
 import Data.Text.Lazy.Builder (toLazyText)
+import Control.Monad.State
+import Data.Bool
 
+-- | FIXME: A horrible hack to separate class id's
 class__ :: Text -> Attribute
 class__ t = class_ (" " <> t <> " ")
 
+-- | Convert html to text
 toText :: Html a -> Text
 toText = Lazy.toStrict . renderText
 
@@ -34,21 +38,28 @@
 genName :: (MonadState Int m) => m Text
 genName = do
   modify (+1)
-  show <$> get
+  (pack . show) <$> get
 
 -- | sometimes a number doesn't work properly in html (or js???), and an alpha prefix seems to help
 genNamePre :: (MonadState Int m) => Text -> m Text
 genNamePre pre = (pre <>) <$> genName
 
+-- | Convert a link to a css library from text to html.
+-- >>> libCss "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
+-- <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
 libCss :: Text -> Html ()
 libCss url = link_
   [ rel_ "stylesheet"
   , href_ url
   ]
 
+-- | Convert a link to a js library from text to html.
+-- >>> libJs "https://code.jquery.com/jquery-3.3.1.slim.min.js"
+-- <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
 libJs :: Text -> Html ()
 libJs url = with (script_ mempty) [src_ url]
 
+-- | convert from #xxxxxx to 'PixelRGB8'
 fromHex :: Parser PixelRGB8
 fromHex =
   (\((r,g),b) ->
@@ -57,36 +68,27 @@
     (`divMod` 256) <$>
     (string "#" *> hexadecimal)
 
+-- | convert from 'PixelRGB8' to #xxxxxx
 toHex :: PixelRGB8 -> Text
 toHex (PixelRGB8 r g b) =
   "#"
-  <> justifyRight 2 '0' (toStrict $ toLazyText $ hex r)
-  <> justifyRight 2 '0' (toStrict $ toLazyText $ hex g)
-  <> justifyRight 2 '0' (toStrict $ toLazyText $ hex b)
+  <> justifyRight 2 '0' (Lazy.toStrict $ toLazyText $ hex r)
+  <> justifyRight 2 '0' (Lazy.toStrict $ toLazyText $ hex g)
+  <> justifyRight 2 '0' (Lazy.toStrict $ toLazyText $ hex b)
 
--- `ToHtml a` is used throughout because `Show a` gives "\"text\"" for show "text", and hilarity ensues when rendering to the web page.
--- hence orphans
+-- FIXME: `ToHtml a` is used throughout, mostly because `Show a` gives "\"text\"" for show "text", and hilarity ensues when rendering this to a web page, and I couldn't work out how to properly get aro0und this.
+-- Hence orphans.
 instance ToHtml Double where
-  toHtml = toHtml . (show :: Double -> Text)
-  toHtmlRaw = toHtmlRaw . (show :: Double -> Text)
-
-{-
-instance (RealFrac a, Floating a) => ToHtml (Colour a) where
-  toHtml = toHtml . sRGB24show
-  toHtmlRaw = toHtmlRaw . sRGB24show
-
-instance (RealFrac a, Floating a) => Show (Colour a) where
-  show = sRGB24show
-
--}
+  toHtml = toHtml . (pack . show)
+  toHtmlRaw = toHtmlRaw . (pack . show)
 
 instance ToHtml Bool where
   toHtml = toHtml . bool ("false" :: Text) "true"
   toHtmlRaw = toHtmlRaw . bool ("false" :: Text) "true"
 
 instance ToHtml Int where
-  toHtml = toHtml . (show :: Int -> Text)
-  toHtmlRaw = toHtmlRaw . (show :: Int -> Text)
+  toHtml = toHtml . (pack . show)
+  toHtmlRaw = toHtmlRaw . (pack . show)
 
 instance ToHtml PixelRGB8 where
   toHtml = toHtml . toHex
diff --git a/src/Web/Page/Html/Input.hs b/src/Web/Page/Html/Input.hs
--- a/src/Web/Page/Html/Input.hs
+++ b/src/Web/Page/Html/Input.hs
@@ -14,9 +14,12 @@
 import Data.Text
 import Lucid
 import Lucid.Base
-import Protolude hiding (for_)
+import Prelude
 import Text.InterpolatedString.Perl6
 import Web.Page.Html
+import GHC.Generics
+import Data.Bool
+import Data.Maybe
 
 -- | something that might exist on a web page and be a front-end input to computations.
 data Input a =
@@ -50,7 +53,7 @@
       ([ type_ "range"
        , class__ " form-control-range custom-range"
        , id_ i
-       , value_ (show $ toHtml v)
+       , value_ (pack $ show $ toHtml v)
        ] <> satts) <>
       scriptJsbEvent i "change")
   toHtml (Input v l i TextBox) =
@@ -60,14 +63,14 @@
       ([ type_ "text"
        , class__ "form-control"
        , id_ i
-       , value_ (show $ toHtml v)
+       , value_ (pack $ show $ toHtml v)
        ]) <>
       scriptJsbEvent i "input")
   toHtml (Input v l i (TextArea rows)) =
     with div_ [class__ "form-group"]
     (maybe mempty (with label_ [for_ i] . toHtml) l <>
      (with textarea_
-     [ rows_ (show rows)
+     [ rows_ (pack $ show rows)
      , class__ "form-control"
      , id_ i
      ] (toHtmlRaw v)
@@ -80,7 +83,7 @@
       ([ type_ "color"
        , class__ "form-control"
        , id_ i
-       , value_ (show $ toHtml v)
+       , value_ (pack $ show $ toHtml v)
        ]) <>
      scriptJsbEvent i "input")
   toHtml (Input _ l i ChooseFile) =
@@ -223,6 +226,7 @@
   \}));
 |]
 
+-- | toggle show/hide
 scriptToggleShow :: (Monad m) => Text -> Text -> HtmlT m ()
 scriptToggleShow checkName toggleClass = script_ [qq|
 $('#{checkName}').on('change', (function()\{
diff --git a/src/Web/Page/Js.hs b/src/Web/Page/Js.hs
deleted file mode 100644
--- a/src/Web/Page/Js.hs
+++ /dev/null
@@ -1,111 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE QuasiQuotes #-}
-
-module Web.Page.Js
-  ( JS(..)
-  , JSStatement(..)
-  , PageJs(..)
-  , minifyJS
-  , onLoad
-  , onLoadStatements
-  , toStatements
-  , toStatement
-  , renderToStatement
-  , renderToText
-  , readJs
-  , fromText
-  ) where
-
-import Language.JavaScript.Parser
-import Language.JavaScript.Parser.AST
-import Language.JavaScript.Process.Minify
-import Protolude hiding ((<>))
-import qualified Data.Text as Text
-import Data.Semigroup ((<>))
-import Text.InterpolatedString.Perl6
-
-newtype JS = JS {unJS :: JSAST} deriving (Show, Eq, Generic)
-
-instance Semigroup JS where
-  (<>) (JS (JSAstProgram ss ann)) (JS (JSAstProgram ss' _)) =
-    JS $ JSAstProgram (ss <> ss') ann
-  (<>) (JS (JSAstProgram ss ann)) (JS (JSAstStatement s _)) =
-    JS $ JSAstProgram (ss <> [s]) ann
-  (<>) (JS (JSAstProgram ss ann)) (JS (JSAstExpression e ann')) =
-    JS $ JSAstProgram (ss <> [JSExpressionStatement e (JSSemi ann')]) ann
-  (<>) (JS (JSAstProgram ss ann)) (JS (JSAstLiteral e ann')) =
-    JS $ JSAstProgram (ss <> [JSExpressionStatement e (JSSemi ann')]) ann
-  (<>) (JS (JSAstStatement s ann)) (JS (JSAstProgram ss _)) =
-    JS $ JSAstProgram (s : ss) ann
-  (<>) (JS (JSAstStatement s ann)) (JS (JSAstStatement s' _)) =
-    JS $ JSAstProgram [s,s'] ann
-  (<>) (JS (JSAstStatement s ann)) (JS (JSAstExpression e ann')) =
-    JS $ JSAstProgram [s,JSExpressionStatement e (JSSemi ann')] ann
-  (<>) (JS (JSAstStatement s ann)) (JS (JSAstLiteral e ann')) =
-    JS $ JSAstProgram [s,JSExpressionStatement e (JSSemi ann')] ann
-  (<>) (JS (JSAstExpression e ann)) (JS (JSAstProgram ss _)) =
-    JS $ JSAstProgram (JSExpressionStatement e (JSSemi ann) : ss) ann
-  (<>) (JS (JSAstExpression e ann)) (JS (JSAstStatement s' _)) =
-    JS $ JSAstProgram [JSExpressionStatement e (JSSemi ann),s'] ann
-  (<>) (JS (JSAstExpression e ann)) (JS (JSAstExpression e' ann')) =
-    JS $ JSAstProgram [JSExpressionStatement e (JSSemi ann),JSExpressionStatement e' (JSSemi ann')] ann
-  (<>) (JS (JSAstExpression e ann)) (JS (JSAstLiteral e' ann')) =
-    JS $ JSAstProgram [JSExpressionStatement e (JSSemi ann),JSExpressionStatement e' (JSSemi ann')] ann
-  (<>) (JS (JSAstLiteral e ann)) (JS (JSAstProgram ss _)) =
-    JS $ JSAstProgram (JSExpressionStatement e (JSSemi ann) : ss) ann
-  (<>) (JS (JSAstLiteral e ann)) (JS (JSAstStatement s' _)) =
-    JS $ JSAstProgram [JSExpressionStatement e (JSSemi ann),s'] ann
-  (<>) (JS (JSAstLiteral e ann)) (JS (JSAstExpression e' ann')) =
-    JS $ JSAstProgram [JSExpressionStatement e (JSSemi ann),JSExpressionStatement e' (JSSemi ann')] ann
-  (<>) (JS (JSAstLiteral e ann)) (JS (JSAstLiteral e' ann')) =
-    JS $ JSAstProgram [JSExpressionStatement e (JSSemi ann),JSExpressionStatement e' (JSSemi ann')] ann
-
-
-instance Monoid JS where
-  mempty = JS $ JSAstProgram [] (JSAnnot (TokenPn 0 0 0) [])
-  mappend = (<>)
-
-data PageJs = PageJs JS | PageJsText Text deriving (Eq, Show, Generic)
-
-instance Semigroup PageJs where
-  (<>) (PageJs js) (PageJs js') = PageJs (js <> js')
-  (<>) (PageJsText js) (PageJsText js') = PageJsText (js <> js')
-  (<>) (PageJs js) (PageJsText js') =
-    PageJsText (toStrict (renderToText $ unJS js) <> js')
-  (<>) (PageJsText js) (PageJs js') =
-    PageJsText (js <> toStrict (renderToText $ unJS js'))
-
-instance Monoid PageJs where
-  mempty = PageJs mempty
-  mappend = (<>)
-
-toStatements :: JS -> [JSStatement]
-toStatements (JS (JSAstProgram ss _)) = ss
-toStatements (JS (JSAstStatement s _)) = [s]
-toStatements (JS (JSAstExpression e ann')) = [JSExpressionStatement e (JSSemi ann')]
-toStatements (JS (JSAstLiteral e ann')) = [JSExpressionStatement e (JSSemi ann')]
-
-toStatement :: JS -> JSStatement
-toStatement (JS (JSAstProgram ss ann)) = JSStatementBlock JSNoAnnot ss JSNoAnnot (JSSemi ann)
-toStatement (JS (JSAstStatement s _)) = s
-toStatement (JS (JSAstExpression e ann')) = JSExpressionStatement e (JSSemi ann')
-toStatement (JS (JSAstLiteral e ann')) = JSExpressionStatement e (JSSemi ann')
-
-renderToStatement :: Text -> JSStatement
-renderToStatement t = toStatement $ JS $ readJs $ Text.unpack t
-
--- | standard window loader
-onLoadStatements :: [JSStatement] -> JS
-onLoadStatements js = JS $ JSAstProgram [JSAssignStatement (JSMemberDot (JSIdentifier JSNoAnnot "window") JSNoAnnot (JSIdentifier JSNoAnnot "onload")) (JSAssign JSNoAnnot) (JSFunctionExpression JSNoAnnot JSIdentNone JSNoAnnot JSLNil JSNoAnnot (JSBlock JSNoAnnot js JSNoAnnot)) JSSemiAuto] JSNoAnnot
-
-onLoadText :: Text -> Text
-onLoadText t = [qc| window.onload=function()\{{t}};|]
-
-onLoad :: PageJs -> PageJs
-onLoad (PageJs js) = PageJs $ onLoadStatements [toStatement js]
-onLoad (PageJsText js) = PageJsText $ onLoadText js
-
-fromText :: Text -> JS
-fromText = JS . readJs . Text.unpack
diff --git a/src/Web/Page/Render.hs b/src/Web/Page/Render.hs
--- a/src/Web/Page/Render.hs
+++ b/src/Web/Page/Render.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE OverloadedLabels #-}
 
+-- | Page rendering
 module Web.Page.Render
   ( renderPage
   , renderPageWith
@@ -9,7 +10,6 @@
   , renderPageAsText
   , renderPageToFile
   , renderPageHtmlToFile
-  , renderPageTextWith
   ) where
 
 import Control.Applicative
@@ -26,17 +26,19 @@
 import Web.Page.Types
 import qualified Data.Text as Text
 import qualified Lucid.Svg as Svg
-import qualified Web.Page.Css as Css
-import qualified Web.Page.Js as Js
+import Data.Foldable
 
+-- | Render a Page with the default configuration into Html.
 renderPage :: Page -> Html ()
 renderPage p =
-  (\(_, _, x) -> x) $ renderPageWith defaultPageConfig p
+  (\(_, _, x) -> x) $ renderPageWith (defaultPageConfig "default") p
 
+-- | Render a Page into Html.
 renderPageHtmlWith :: PageConfig -> Page -> Html ()
 renderPageHtmlWith pc p =
   (\(_, _, x) -> x) $ renderPageWith pc p
 
+-- | Render a Page into css text, js text and html.
 renderPageWith :: PageConfig -> Page -> (Text, Text, Html ())
 renderPageWith pc p =
   case pc ^. #concerns of
@@ -93,8 +95,9 @@
                , jsInline
                ])
     css = rendercss (p ^. #cssBody)
-    js = renderjs (p ^. #jsGlobal <> Js.onLoad (p ^. #jsOnLoad))
-    (renderjs, rendercss) = renderers $ pc ^. #pageRender
+    js = renderjs (p ^. #jsGlobal <> onLoad (p ^. #jsOnLoad))
+    renderjs = renderPageJs $ pc ^. #pageRender
+    rendercss = renderPageCss $ pc ^. #pageRender
     cssInline
       | pc ^. #concerns == Separated || css == mempty = mempty
       | otherwise = style_ [type_ "text/css"] css
@@ -106,24 +109,27 @@
         Inline -> p ^. #libsCss
         Separated ->
           p ^. #libsCss <>
-          [libCss (Text.pack $ pc ^. #filenames . #css)]
+          [libCss (Text.pack $ pc ^. #filenames . #cssConcern)]
     libsJs' =
       case pc ^. #concerns of
         Inline -> p ^. #libsJs
         Separated ->
           p ^. #libsJs <>
-          [libJs (Text.pack $ pc ^. #filenames . #js)]
+          [libJs (Text.pack $ pc ^. #filenames . #jsConcern)]
 
+-- | Render Page concerns to files.
 renderPageToFile :: FilePath -> PageConfig -> Page -> IO ()
 renderPageToFile dir pc page =
-  void $ sequenceA $ liftA2 writeFile' (pc ^. #filenames) (renderPageAsText pc page)
+  sequenceA_ $ liftA2 writeFile' (pc ^. #filenames) (renderPageAsText pc page)
   where
     writeFile' fp s = unless (s == mempty) (writeFile (dir <> "/" <> fp) s)
 
+-- | Render a page to just a Html file.
 renderPageHtmlToFile :: FilePath -> PageConfig -> Page -> IO ()
 renderPageHtmlToFile file pc page =
   writeFile file (toText $ renderPageHtmlWith pc page)
 
+-- | Render a Page as Text.
 renderPageAsText :: PageConfig -> Page -> Concerns Text
 renderPageAsText pc p =
   case pc ^. #concerns of
@@ -132,94 +138,4 @@
   where
     htmlt = toText h
     (css, js, h) = renderPageWith pc p
-
-rendererJs :: PageRender -> Js.PageJs -> Text
-rendererJs _ (Js.PageJsText js) = js
-rendererJs Minified (Js.PageJs js) = toStrict . Js.renderToText . Js.minifyJS . Js.unJS $ js
-rendererJs Pretty (Js.PageJs js) = toStrict . Js.renderToText . Js.unJS $ js
-
-rendererCss :: PageRender -> Css.PageCss -> Text
-rendererCss Minified (Css.PageCss css) = toStrict $ Css.renderWith Css.compact [] css
-rendererCss Pretty (Css.PageCss css) = toStrict $ Css.render css
-rendererCss _ (Css.PageCssText css) = css
-
-renderers :: PageRender -> (Js.PageJs -> Text, Css.PageCss -> Text)
-renderers p = (rendererJs p, rendererCss p)
-
-renderPageTextWith :: PageConfig -> PageText -> (Text, Text, Html ())
-renderPageTextWith pc p =
-  case pc ^. #concerns of
-    Inline -> (mempty, mempty, h)
-    Separated -> (css, js, h)
-  where
-    h =
-      case pc ^. #structure of
-        HeaderBody ->
-          doctype_ <>
-          with html_ [lang_ "en"]
-          (head_
-          (mconcat
-            [ meta_ [charset_ "utf-8"]
-            , toHtmlRaw cssInline
-            , mconcat (toHtmlRaw <$> libsCss')
-            , toHtmlRaw $ p ^. #htmlHeaderText
-            ]) <>
-          body_
-          (mconcat
-            [ toHtmlRaw $ p ^. #htmlBodyText
-            , mconcat (toHtmlRaw <$> libsJs')
-            , toHtmlRaw jsInline
-            ]))
-        Headless ->
-          mconcat
-            [ doctype_
-            , meta_ [charset_ "utf-8"]
-            , mconcat (toHtmlRaw <$> libsCss')
-            , toHtmlRaw cssInline
-            , toHtmlRaw $ p ^. #htmlHeaderText
-            , toHtmlRaw $ p ^. #htmlBodyText
-            , mconcat (toHtmlRaw <$> libsJs')
-            , toHtmlRaw jsInline
-            ]
-        Snippet ->
-          mconcat
-            [ mconcat (toHtmlRaw <$> libsCss')
-            , toHtmlRaw cssInline
-            , toHtmlRaw $ p ^. #htmlHeaderText
-            , toHtmlRaw $ p ^. #htmlBodyText
-            , mconcat (toHtmlRaw <$> libsJs')
-            , toHtmlRaw jsInline
-            ]
-        Svg ->
-          Svg.doctype_ <>
-          svg_
-            (Svg.defs_ $
-             mconcat
-               [ mconcat (toHtmlRaw <$> libsCss')
-               , toHtmlRaw cssInline
-               , toHtmlRaw $ p ^. #htmlBodyText
-               , mconcat (toHtmlRaw <$> libsJs')
-               , toHtmlRaw jsInline
-               ])
-    css = p ^. #cssBodyText
-    js = rendererJs Pretty (Js.PageJsText $ p ^. #jsGlobalText) <>
-         rendererJs Pretty (Js.onLoad (Js.PageJsText $ p ^. #jsOnLoadText))
-    cssInline
-      | pc ^. #concerns == Separated || css == mempty = mempty
-      | otherwise = renderText $ style_ [type_ "text/css"] css
-    jsInline
-      | pc ^. #concerns == Separated || js == mempty = mempty
-      | otherwise = renderText $ script_ mempty js
-    libsCss' =
-      case pc ^. #concerns of
-        Inline -> fromStrict <$> p ^. #libsCssText
-        Separated ->
-          (fromStrict <$> p ^. #libsCssText) <>
-          [renderText $ libCss (Text.pack $ pc ^. #filenames . #css)]
-    libsJs' =
-      case pc ^. #concerns of
-        Inline -> fromStrict <$> p ^. #libsJsText
-        Separated ->
-          (fromStrict <$> p ^. #libsJsText) <>
-          [renderText $ libJs (Text.pack $ pc ^. #filenames . #js)]
 
diff --git a/src/Web/Page/Rep.hs b/src/Web/Page/Rep.hs
deleted file mode 100644
--- a/src/Web/Page/Rep.hs
+++ /dev/null
@@ -1,249 +0,0 @@
-{-# LANGUAGE ApplicativeDo #-}
-{-# LANGUAGE DeriveFunctor #-}
-{-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE OverloadedLabels #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TupleSections #-}
-{-# OPTIONS_GHC -Wall #-}
-
-module Web.Page.Rep
-  ( Element(..)
-  , RepF(..)
-  , Rep
-  , oneRep
-  , SharedRepF(..)
-  , SharedRep
-  , runOnce
-  , zeroState
-  , listify
-  , accordionListify
-  , accordionListifyMaybe
-  , listifyDefault
-  , listifyMaybe
-  , listifyMaybe'
-  , defaultListifyLabels
-  , valueModel
-  , valueConsume
-  , sharedModel
-  , sharedConsume
-  , runList
-  , runOnEvent
-  ) where
-
-import Box
-import Box.Cont ()
-import Control.Lens
-import Control.Monad.Morph
-import Data.Aeson
-import Data.Biapplicative
-import Data.Bifunctor (Bifunctor(..))
-import Data.HashMap.Strict hiding (foldr)
-import Data.Text (pack, Text)
-import Lucid
-import Protolude hiding ((<<*>>), Rep, empty)
-import Web.Page.Bootstrap
-import qualified Control.Foldl as L
-import qualified Streaming.Prelude as S
-
--- | Abstracted message event elements
-data Element = Element
-  { element :: Text
-  , value :: Text
-  } deriving (Eq, Show, Generic)
-
-instance ToJSON Element
-
-instance FromJSON Element
-  where
-    parseJSON = withObject "Element" $ \v ->
-      Element <$>
-      v .: "element" <*>
-      v .: "value"
-
-fromJson' :: (FromJSON a) => Value -> Either Text a
-fromJson' v = case fromJSON v of
-  (Success a) -> Right a
-  (Error e) -> Left $ "Json conversion error: " <> pack e <> " of " <> show v
-
-data RepF r a = Rep
-  { rep :: r
-  , make :: HashMap Text Text -> (HashMap Text Text, Either Text a)
-  } deriving (Functor)
-
-type Rep a = RepF (Html ()) a
-
-instance (Semigroup r) => Semigroup (RepF r a) where
-  (Rep r0 a0) <> (Rep r1 a1) =
-    Rep
-    (r0 <> r1)
-    (\hm -> let (hm', x') = a0 hm in let (hm'', x'') = a1 hm' in (hm'', x' <> x''))
-
-instance (Monoid a, Monoid r) => Monoid (RepF r a) where
-  mempty = Rep mempty (,Right mempty)
-  mappend = (<>)
-
-instance Bifunctor RepF where
-  bimap f g (Rep r a) = Rep (f r) (second (fmap g) . a)
-
-instance Biapplicative RepF where
-  bipure r a = Rep r (, Right a)
-  (Rep fr fa) <<*>> (Rep r a) = Rep (fr r)
-    (\hm ->
-        let (hm', a') = a hm in let (hm'', fa') = fa hm' in (hm'', fa' <*> a'))
-
-instance (Monoid r) => Applicative (RepF r) where
-  pure = bipure mempty
-  Rep fh fm <*> Rep ah am =
-    Rep (fh <> ah) (\hm ->
-        let (hm', a') = am hm in let (hm'', fa') = fm hm' in (hm'', fa' <*> a'))
-
-oneRep :: (Monad m, MonadIO m) => Rep a -> (Rep a -> HashMap Text Text -> m ()) -> StateT (HashMap Text Text) m (HashMap Text Text, Either Text a)
-oneRep r@(Rep _ fa) action = do
-  m <- get
-  let (m',a) = fa m
-  put m'
-  lift $ action r m'
-  pure (m',a)
-
-newtype SharedRepF m r a = SharedRep
-  { unrep :: StateT (Int, HashMap Text Text) m (RepF r a)
-  } deriving Functor
-
-type SharedRep m a = SharedRepF m (Html ()) a 
-
-instance (Functor m) => Bifunctor (SharedRepF m) where
-  bimap f g (SharedRep s) = SharedRep $ fmap (bimap f g) s
-
-instance (Monad m) => Biapplicative (SharedRepF m) where
-  bipure r a = SharedRep $ pure $ bipure r a
-  (SharedRep f) <<*>> (SharedRep a) = SharedRep $ liftA2 (<<*>>) f a
-
-instance (Monad m, Monoid r) => Applicative (SharedRepF m r) where
-  pure = bipure mempty
-  SharedRep f <*> SharedRep a = SharedRep $ liftA2 (<*>) f a
-
-runOnce
-  :: (Monad m)
-  => SharedRep m a
-  -> (Html () -> HashMap Text Text -> m ())
-  -> m (HashMap Text Text, Either Text a)
-runOnce sr action = do
-  (Rep h fa, (_, m)) <- flip runStateT (0, empty) $ unrep sr
-  action h m
-  pure (fa m)
-
-zeroState
-  :: (Monad m)
-  => SharedRep m a
-  -> m (Html (), (HashMap Text Text, Either Text a))
-zeroState sr = do
-  (Rep h fa, (_, m)) <- flip runStateT (0, empty) $ unrep sr
-  pure (h, fa m)
-
-listify :: (Monad m) => (Text -> a -> SharedRep m a) -> [Text] -> [a] -> SharedRep m [a]
-listify sr labels as = foldr (\a x -> (:) <$> a <*> x) (pure []) (zipWith sr labels as)
-
-accordionListify :: (Monad m) => Maybe Text -> Text -> Maybe Text -> (Text -> a -> SharedRep m a) -> [Text] -> [a] -> SharedRep m [a]
-accordionListify title prefix open srf labels as = SharedRep $ do
-  (Rep h fa) <-
-    unrep $
-    first (accordion prefix open . zip labels ) $
-    foldr (\a x -> bimap (:) (:) a <<*>> x)
-    (pure []) (zipWith srf labels as)
-  h' <- zoom _1 h
-  pure (Rep (maybe mempty (h5_ . toHtml) title <> h') fa)
-
-accordionListifyMaybe :: (Monad m) => Maybe Text -> Text -> (a -> SharedRep m a) -> (Bool -> SharedRep m Bool) -> [Text] -> [(Bool, a)] -> SharedRep m [(Bool,a)]
-accordionListifyMaybe title prefix bodyf checkf labels xs = SharedRep $ do
-  (Rep h fa) <-
-    unrep $
-    first (accordionChecked prefix) $
-    first (zipWith (\l (ch,a) -> (l,a,ch)) labels) $
-    foldr (\a x -> bimap (:) (:) a <<*>> x)
-    (pure [])
-    ((\(ch, a) ->
-         (bimap (,) (,)
-          (checkf ch) <<*>> bodyf a)) <$> xs)
-  h' <- zoom _1 h
-  pure (Rep (maybe mempty (h5_ . toHtml) title <> h') fa)
-
-listifyDefault :: (Monad m) => Maybe Text -> Text -> (Text -> a -> SharedRep m a) -> [a] -> SharedRep m [a]
-listifyDefault t p srf as = accordionListify t p Nothing srf (defaultListifyLabels (length as)) as
-
-listifyMaybe :: (Monad m) => Maybe Text -> Text -> (Text -> Maybe a -> SharedRep m (Maybe a)) -> Int -> [a] -> SharedRep m [Maybe a]
-listifyMaybe t p srf n as = accordionListify t p Nothing srf (defaultListifyLabels n) (take n ((Just <$> as) <> repeat Nothing)) 
-
-listifyMaybe' :: (Monad m) => Maybe Text -> Text -> (Bool -> SharedRep m Bool) -> (a -> SharedRep m a) -> Int -> a -> [a] -> SharedRep m [a]
-listifyMaybe' t p brf srf n defa as = second (mconcat . fmap (\(b,a) -> bool [] [a] b)) $ accordionListifyMaybe t p srf brf (defaultListifyLabels n) (take n (((True,) <$> as) <> repeat (False, defa)))
-
-defaultListifyLabels :: Int -> [Text]
-defaultListifyLabels n = (\x -> "[" <> show x <> "]") <$> [0..n] :: [Text]
-
-valueModel :: (FromJSON a, MonadState s m) => (a -> s -> s) -> S.Stream (S.Of Value) m () -> S.Stream (S.Of (Either Text s)) m ()
-valueModel step s =
-  s &
-  S.map fromJson' &
-  S.partitionEithers &
-  hoist (S.chain (modify . step)) &
-  hoist (S.mapM (const get)) &
-  S.unseparate &
-  S.maps S.sumToEither
-
--- | consume an Element using a Committer and a Value continuation
-valueConsume :: s -> (Element -> s -> s) -> Cont IO (Committer IO (Either Text s)) -> Cont_ IO Value -> IO s
-valueConsume init step comm vio = do
-  (c,e) <- atomically $ ends Unbounded
-  with_ vio (atomically . c)
-  etcM init (Transducer (valueModel step))
-    (Box <$> comm <*> (liftE <$> pure (Emitter (Just <$> e))))
-
-stepM :: MonadState s m => (s -> (s, b)) -> (a -> s -> s) -> a -> m (s, b)
-stepM sr step v = do
-  hm <- get
-  let (hm',b) = sr $ step v hm
-  put hm'
-  pure (hm', b)
-
-sharedModel :: (FromJSON a, MonadState s m) => (s -> (s, Either Text b)) -> (a -> s -> s) -> S.Stream (S.Of Value) m () -> S.Stream (S.Of (Either Text (s, Either Text b))) m ()
-sharedModel sr step s =
-  s &
-  S.map fromJson' &
-  S.partitionEithers &
-  hoist (S.mapM (stepM sr step)) &
-  S.unseparate &
-  S.maps S.sumToEither
-
-runList
-  :: (Monad m)
-  => SharedRep m a
-  -> [Value]
-  -> m [Either Text (HashMap Text Text, Either Text a)]
-runList sr vs = S.fst' <$> do
-  (faStep, (_,hm)) <- flip runStateT (0, empty) $ do
-    (Rep _ fa) <- unrep sr
-    pure fa
-  flip evalStateT hm $
-    L.purely S.fold L.list
-    (sharedModel faStep (\(Element k v) s -> insert k v s) (S.each vs))
-
-sharedConsume :: (s -> (s, Either Text b)) -> s -> (Element -> s -> s) -> Cont IO (Committer IO (Either Text (s, Either Text b))) -> Cont_ IO Value -> IO s
-sharedConsume sh init step comm vio = do
-  (c,e) <- atomically $ ends Unbounded
-  with_ vio (atomically . c)
-  etcM init (Transducer (sharedModel sh step))
-    (Box <$> comm <*> (liftE <$> pure (Emitter (Just <$> e))))
-
-runOnEvent
-  :: SharedRep IO a
-  -> (Rep a -> StateT (Int, HashMap Text Text) IO ())
-  -> (Either Text (HashMap Text Text, Either Text a) -> IO ())
-  -> Cont_ IO Value
-  -> IO (HashMap Text Text)
-runOnEvent sr hio eaction cv = flip evalStateT (0, empty) $ do
-  (Rep h fa) <- unrep sr
-  hio (Rep h fa)
-  m <- zoom _2 get
-  liftIO $ sharedConsume fa m (\(Element k v) s -> insert k v s)
-    (pure (Committer (\v -> eaction v >> pure True))) cv
diff --git a/src/Web/Page/Rep/Input.hs b/src/Web/Page/Rep/Input.hs
deleted file mode 100644
--- a/src/Web/Page/Rep/Input.hs
+++ /dev/null
@@ -1,184 +0,0 @@
-{-# LANGUAGE ApplicativeDo #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE OverloadedLabels #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# OPTIONS_GHC -Wall #-}
-{-# OPTIONS_GHC -Wredundant-constraints #-}
-
-module Web.Page.Rep.Input
-  ( repInput
-  , repMessage
-  , sliderI
-  , slider
-  , dropdown
-  , datalist
-  , dropdownSum
-  , colorPicker
-  , textbox
-  , textarea
-  , checkbox
-  , toggle
-  , button
-  , chooseFile
-  , maybeRep
-  , fiddle
-  , viaFiddle
-  ) where
-
-import Codec.Picture.Types (PixelRGB8(..))
-import Control.Category (id)
-import Control.Lens
-import Data.Attoparsec.Text
-import Data.Biapplicative
-import Data.Bifunctor (Bifunctor(..))
-import Data.HashMap.Strict
-import Data.Text (pack, Text)
-import Lucid
-import Protolude hiding ((<<*>>), Rep)
-import Web.Page.Bootstrap
-import Web.Page.Html
-import Web.Page.Html.Input
-import Web.Page.Types
-import Web.Page.Rep
-import Box.Cont ()
-
--- | create a sharedRep from an Input
-repInput :: (Monad m, ToHtml a) => Parser a -> (a -> Text) -> Input a -> a -> SharedRep m a
-repInput p pr i a =
-  SharedRep $ do
-    name <- zoom _1 genName
-    zoom _2 (modify (insert name (pr a)))
-    pure $
-      Rep
-      (toHtml $ #inputVal .~ a $ #inputId .~ name $ i)
-      (\s ->
-        (s, join $
-        maybe (Left "lookup failed") Right $
-        either (Left . (\x -> name <> ": " <> x) . pack) Right . parseOnly p <$> lookup name s))
-
--- | does not put a value into the HashMap on instantiation, consumes the value when found in the HashMap, and substitutes a default on lookup failure
-repMessage :: (Monad m, ToHtml a) => Parser a -> (a -> Text) -> Input a -> a -> a -> SharedRep m a
-repMessage p _ i def a =
-  SharedRep $ do
-    name <- zoom _1 genName
-    pure $
-      Rep
-      (toHtml $ #inputVal .~ a $ #inputId .~ name $ i)
-      (\s ->
-        (delete name s, join $
-        maybe (Right $ Right def) Right $
-        either (Left . pack) Right . parseOnly p <$> lookup name s))
-
-slider :: (Monad m) => Maybe Text -> Double -> Double -> Double -> Double ->
-  SharedRep m Double
-slider label l u s v = repInput double show
-  (Input v label mempty (Slider [min_ (pack $ show l), max_ (pack $ show u), step_ (pack $ show s)])) v
-
-sliderI :: (Monad m, ToHtml a, Integral a, Show a) => Maybe Text -> a -> a -> a -> a ->
-  SharedRep m a
-sliderI label l u s v = repInput decimal show 
-  (Input v label mempty (Slider [min_ (pack $ show l), max_ (pack $ show u), step_ (pack $ show s)])) v
-
-textbox :: (Monad m) => Maybe Text -> Text -> SharedRep m Text
-textbox label v = repInput takeText id
-  (Input v label mempty TextBox) v
-
-textarea :: (Monad m) => Int -> Maybe Text -> Text -> SharedRep m Text
-textarea rows label v = repInput takeText id
-  (Input v label mempty (TextArea rows)) v
-
-colorPicker :: (Monad m) => Maybe Text -> PixelRGB8 -> SharedRep m PixelRGB8
-colorPicker label v = repInput fromHex toHex
-  (Input v label mempty ColorPicker) v
-
-dropdown :: (Monad m, ToHtml a) =>
-  Parser a -> (a -> Text) -> Maybe Text -> [Text] -> a -> SharedRep m a
-dropdown p pr label opts v = repInput p pr 
-  (Input v label mempty (Dropdown opts)) v
-
-datalist :: (Monad m) => Maybe Text -> [Text] -> Text -> Text -> SharedRep m Text
-datalist label opts v id'' = repInput takeText show
-  (Input v label mempty (Datalist opts id'')) v
-
-dropdownSum :: (Monad m, ToHtml a) =>
-  Parser a -> (a -> Text) -> Maybe Text -> [Text] -> a -> SharedRep m a
-dropdownSum p pr label opts v = repInput p pr
-  (Input v label mempty (DropdownSum opts)) v
-
-checkbox :: (Monad m) => Maybe Text -> Bool -> SharedRep m Bool
-checkbox label v = repInput ((=="true") <$> takeText) (bool "false" "true")
-  (Input v label mempty (Checkbox v)) v
-
-toggle :: (Monad m) => Maybe Text -> Bool -> SharedRep m Bool
-toggle label v = repInput ((=="true") <$> takeText) (bool "false" "true")
-  (Input v label mempty (Toggle v label)) v
-
-button :: (Monad m) => Maybe Text -> SharedRep m Bool
-button label = repMessage (pure True) (bool "false" "true")
-  (Input False label mempty Button) False False
-
-chooseFile :: (Monad m) => Maybe Text -> Text -> SharedRep m Text
-chooseFile label v = repInput takeText show
-  (Input v label mempty ChooseFile) v
-
-checkboxShowJs :: (Monad m) => Maybe Text -> Text -> Bool -> SharedRep m Bool
-checkboxShowJs label cl v =
-  SharedRep $ do
-    name <- zoom _1 genName
-    zoom _2 (modify (insert name (bool "false" "true" v)))
-    pure $
-      Rep
-      (toHtml (Input v label name (Checkbox v)) <> scriptToggleShow name cl)
-      (\s ->
-        (s, join $
-        maybe (Left "lookup failed") Right $
-        either (Left . pack) Right . parseOnly ((=="true") <$> takeText) <$>
-        lookup name s))
-
--- | represent a Maybe type using a checkbox hiding the underlying content on Nothing
-maybeRep :: (Monad m) => Maybe Text -> Bool -> SharedRep m a ->
-  SharedRep m (Maybe a)
-maybeRep label st sa = SharedRep $ do
-  className <- zoom _1 genName
-  unrep $ bimap (hmap className) mmap (checkboxShowJs label className st) <<*>> sa
-  where
-    hmap cl a b =
-      cardify (a, []) Nothing
-       ((Lucid.with div_
-        [class__ cl, style_
-                   ("display:" <> bool "none" "block" st)]
-        b),
-        [style_ "padding-top: 0.25rem; padding-bottom: 0.25rem;"])
-    mmap a b = bool Nothing (Just b) a
-
--- | representation of web concerns (css, js & html)
-fiddle :: (Monad m) => Concerns Text -> SharedRep m (Concerns Text, Bool)
-fiddle (Concerns c j h) =
-  bimap
-  (\c' j' h' up -> (Lucid.with div_ [class__ "fiddle "] $ mconcat [up,h',j',c']))
-  (\c' j' h' up -> (Concerns c' j' h', up))
-  (textarea 10 (Just "css") c) <<*>>
-  textarea 10 (Just "js") j <<*>>
-  textarea 10 (Just "html") h <<*>>
-  button (Just "update")
-
--- | turns a SharedRep into a fiddle
-viaFiddle
-  :: (Monad m)
-  => SharedRep m a
-  -> SharedRep m (Bool, Concerns Text, a)
-viaFiddle sr = SharedRep $ do
-  sr'@(Rep h _) <- unrep sr
-  hrep <- unrep $ textarea 10 (Just "html") (toText h)
-  crep <- unrep $ textarea 10 (Just "css") mempty
-  jrep <- unrep $ textarea 10 (Just "js") mempty
-  u <- unrep $ button (Just "update")
-  pure $
-    bimap
-    (\up a b c _ -> (Lucid.with div_ [class__ "fiddle "] $ mconcat [up, a, b, c]))
-    (\up a b c d -> (up, Concerns a b c, d))
-    u <<*>>
-    crep <<*>>
-    jrep <<*>>
-    hrep <<*>>
-    sr'
diff --git a/src/Web/Page/Server.hs b/src/Web/Page/Server.hs
--- a/src/Web/Page/Server.hs
+++ b/src/Web/Page/Server.hs
@@ -10,12 +10,15 @@
 import Control.Lens hiding (only)
 import Lucid (renderText)
 import Network.Wai.Middleware.Static (addBase, noDots, staticPolicy, only)
-import Protolude hiding (get)
+import Prelude
 import Web.Page.Render
 import Web.Page.Types
 import Web.Scotty
 import qualified Control.Monad.State as State
+import Control.Monad
+import Data.Text (unpack)
 
+-- | serve a Page via a ScottyM
 servePageWith :: RoutePattern -> PageConfig -> Page -> ScottyM ()
 servePageWith rp pc p =
   sequence_ $ servedir <> [getpage]
@@ -27,11 +30,11 @@
       do
         middleware $ staticPolicy $ only [(cssfp,cssfp), (jsfp, jsfp)]
         get rp (do
-                   State.lift $ writeFile' cssfp css
-                   State.lift $ writeFile' jsfp js
+                   State.lift $ writeFile' cssfp (unpack css)
+                   State.lift $ writeFile' jsfp (unpack js)
                    html $ renderText h)
-  cssfp = pc ^. #filenames . #css
-  jsfp = pc ^. #filenames . #js
+  cssfp = pc ^. #filenames . #cssConcern
+  jsfp = pc ^. #filenames . #jsConcern
   writeFile' fp s = unless (s == mempty) (writeFile fp s)
   servedir = (\x -> middleware $ staticPolicy (noDots <> addBase x)) <$> pc ^. #localdirs
 
diff --git a/src/Web/Page/SharedReps.hs b/src/Web/Page/SharedReps.hs
new file mode 100644
--- /dev/null
+++ b/src/Web/Page/SharedReps.hs
@@ -0,0 +1,354 @@
+{-# LANGUAGE ApplicativeDo #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE OverloadedLabels #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TupleSections #-}
+{-# OPTIONS_GHC -Wall #-}
+{-# OPTIONS_GHC -Wredundant-constraints #-}
+
+module Web.Page.SharedReps
+  ( repInput,
+    repMessage,
+    sliderI,
+    slider,
+    dropdown,
+    datalist,
+    dropdownSum,
+    colorPicker,
+    textbox,
+    textarea,
+    checkbox,
+    toggle,
+    button,
+    chooseFile,
+    maybeRep,
+    fiddle,
+    viaFiddle,
+    accordionList,
+    listMaybeRep,
+    listRep,
+    defaultListLabels,
+  )
+where
+
+import Box.Cont ()
+import Codec.Picture.Types (PixelRGB8 (..))
+import Control.Lens
+import Data.Attoparsec.Text hiding (take)
+import qualified Data.HashMap.Strict as HashMap
+import Data.Text (Text, pack)
+import Lucid
+import Prelude hiding (lookup)
+import Web.Page.Bootstrap
+import Web.Page.Html
+import Web.Page.Html.Input
+import Web.Page.Types
+import Data.Biapplicative
+import Control.Monad.Trans.State
+import Control.Monad
+import Data.Bool
+
+-- | create a sharedRep from an Input
+repInput :: (Monad m, ToHtml a) => Parser a -> (a -> Text) -> Input a -> a -> SharedRep m a
+repInput p pr i a =
+  SharedRep $ do
+    name <- zoom _1 genName
+    zoom _2 (modify (HashMap.insert name (pr a)))
+    pure $
+      Rep
+        (toHtml $ #inputVal .~ a $ #inputId .~ name $ i)
+        ( \s ->
+            ( s,
+              join
+                $ maybe (Left "lookup failed") Right
+                $ either (Left . (\x -> name <> ": " <> x) . pack) Right . parseOnly p <$> HashMap.lookup name s
+            )
+        )
+
+-- | does not put a value into the HashMap on instantiation, consumes the value when found in the HashMap, and substitutes a default on lookup failure
+repMessage :: (Monad m, ToHtml a) => Parser a -> (a -> Text) -> Input a -> a -> a -> SharedRep m a
+repMessage p _ i def a =
+  SharedRep $ do
+    name <- zoom _1 genName
+    pure $
+      Rep
+        (toHtml $ #inputVal .~ a $ #inputId .~ name $ i)
+        ( \s ->
+            ( HashMap.delete name s,
+              join
+                $ maybe (Right $ Right def) Right
+                $ either (Left . pack) Right . parseOnly p <$> HashMap.lookup name s
+            )
+        )
+
+slider ::
+  (Monad m) =>
+  Maybe Text ->
+  Double ->
+  Double ->
+  Double ->
+  Double ->
+  SharedRep m Double
+slider label l u s v =
+  repInput
+    double
+    (pack . show)
+    (Input v label mempty (Slider [min_ (pack $ show l), max_ (pack $ show u), step_ (pack $ show s)]))
+    v
+
+sliderI ::
+  (Monad m, ToHtml a, Integral a, Show a) =>
+  Maybe Text ->
+  a ->
+  a ->
+  a ->
+  a ->
+  SharedRep m a
+sliderI label l u s v =
+  repInput
+    decimal
+    (pack . show)
+    (Input v label mempty (Slider [min_ (pack $ show l), max_ (pack $ show u), step_ (pack $ show s)]))
+    v
+
+textbox :: (Monad m) => Maybe Text -> Text -> SharedRep m Text
+textbox label v =
+  repInput
+    takeText
+    id
+    (Input v label mempty TextBox)
+    v
+
+textarea :: (Monad m) => Int -> Maybe Text -> Text -> SharedRep m Text
+textarea rows label v =
+  repInput
+    takeText
+    id
+    (Input v label mempty (TextArea rows))
+    v
+
+colorPicker :: (Monad m) => Maybe Text -> PixelRGB8 -> SharedRep m PixelRGB8
+colorPicker label v =
+  repInput
+    fromHex
+    toHex
+    (Input v label mempty ColorPicker)
+    v
+
+dropdown ::
+  (Monad m, ToHtml a) =>
+  Parser a ->
+  (a -> Text) ->
+  Maybe Text ->
+  [Text] ->
+  a ->
+  SharedRep m a
+dropdown p pr label opts v =
+  repInput
+    p
+    pr
+    (Input v label mempty (Dropdown opts))
+    v
+
+datalist :: (Monad m) => Maybe Text -> [Text] -> Text -> Text -> SharedRep m Text
+datalist label opts v id'' =
+  repInput
+    takeText
+    (pack . show)
+    (Input v label mempty (Datalist opts id''))
+    v
+
+dropdownSum ::
+  (Monad m, ToHtml a) =>
+  Parser a ->
+  (a -> Text) ->
+  Maybe Text ->
+  [Text] ->
+  a ->
+  SharedRep m a
+dropdownSum p pr label opts v =
+  repInput
+    p
+    pr
+    (Input v label mempty (DropdownSum opts))
+    v
+
+checkbox :: (Monad m) => Maybe Text -> Bool -> SharedRep m Bool
+checkbox label v =
+  repInput
+    ((== "true") <$> takeText)
+    (bool "false" "true")
+    (Input v label mempty (Checkbox v))
+    v
+
+toggle :: (Monad m) => Maybe Text -> Bool -> SharedRep m Bool
+toggle label v =
+  repInput
+    ((== "true") <$> takeText)
+    (bool "false" "true")
+    (Input v label mempty (Toggle v label))
+    v
+
+button :: (Monad m) => Maybe Text -> SharedRep m Bool
+button label =
+  repMessage
+    (pure True)
+    (bool "false" "true")
+    (Input False label mempty Button)
+    False
+    False
+
+chooseFile :: (Monad m) => Maybe Text -> Text -> SharedRep m Text
+chooseFile label v =
+  repInput
+    takeText
+    (pack . show)
+    (Input v label mempty ChooseFile)
+    v
+
+checkboxShowJs :: (Monad m) => Maybe Text -> Text -> Bool -> SharedRep m Bool
+checkboxShowJs label cl v =
+  SharedRep $ do
+    name <- zoom _1 genName
+    zoom _2 (modify (HashMap.insert name (bool "false" "true" v)))
+    pure $
+      Rep
+        (toHtml (Input v label name (Checkbox v)) <> scriptToggleShow name cl)
+        ( \s ->
+            ( s,
+              join
+                $ maybe (Left "HashMap.lookup failed") Right
+                $ either (Left . pack) Right . parseOnly ((== "true") <$> takeText)
+                  <$> HashMap.lookup name s
+            )
+        )
+
+-- | represent a Maybe type using a checkbox hiding the underlying content on Nothing
+maybeRep ::
+  (Monad m) =>
+  Maybe Text ->
+  Bool ->
+  SharedRep m a ->
+  SharedRep m (Maybe a)
+maybeRep label st sa = SharedRep $ do
+  className <- zoom _1 genName
+  unrep $ bimap (hmap className) mmap (checkboxShowJs label className st) <<*>> sa
+  where
+    hmap cl a b =
+      cardify
+        (a, [])
+        Nothing
+        ( ( Lucid.with
+              div_
+              [ class__ cl,
+                style_
+                  ("display:" <> bool "none" "block" st)
+              ]
+              b
+          ),
+          [style_ "padding-top: 0.25rem; padding-bottom: 0.25rem;"]
+        )
+    mmap a b = bool Nothing (Just b) a
+
+-- | a (fixed-size) list represented in html as an accordion card
+accordionList :: (Monad m) => Maybe Text -> Text -> Maybe Text -> (Text -> a -> SharedRep m a) -> [Text] -> [a] -> SharedRep m [a]
+accordionList title prefix open srf labels as = SharedRep $ do
+  (Rep h fa) <-
+    unrep
+      $ first (accordion prefix open . zip labels)
+      $ foldr
+        (\a x -> bimap (:) (:) a <<*>> x)
+        (pure [])
+        (zipWith srf labels as)
+  h' <- zoom _1 h
+  pure (Rep (maybe mempty (h5_ . toHtml) title <> h') fa)
+
+-- | a (fixed-sized) list of (Bool, a) tuples.
+accordionBoolList :: (Monad m) => Maybe Text -> Text -> (a -> SharedRep m a) -> (Bool -> SharedRep m Bool) -> [Text] -> [(Bool, a)] -> SharedRep m [(Bool, a)]
+accordionBoolList title prefix bodyf checkf labels xs = SharedRep $ do
+  (Rep h fa) <-
+    unrep
+      $ first (accordionChecked prefix)
+      $ first (zipWith (\l (ch, a) -> (l, a, ch)) labels)
+      $ foldr
+        (\a x -> bimap (:) (:) a <<*>> x)
+        (pure [])
+        ( ( \(ch, a) ->
+              ( bimap
+                  (,)
+                  (,)
+                  (checkf ch)
+                  <<*>> bodyf a
+              )
+          )
+            <$> xs
+        )
+  h' <- zoom _1 h
+  pure (Rep (maybe mempty (h5_ . toHtml) title <> h') fa)
+
+-- | a fixed-sized list of Maybe a\'s
+listMaybeRep :: (Monad m) => Maybe Text -> Text -> (Text -> Maybe a -> SharedRep m (Maybe a)) -> Int -> [a] -> SharedRep m [Maybe a]
+listMaybeRep t p srf n as =
+  accordionList t p Nothing srf (defaultListLabels n) (take n ((Just <$> as) <> repeat Nothing))
+
+-- | a SharedRep of [a].  Due to the applicative nature of the bridge, the size of lists has to be fixed on construction.  listRep is a workaround for this, to enable some form of dynamic sizing.
+listRep ::
+  (Monad m) =>
+  Maybe Text ->
+  Text ->
+  -- | name prefix (should be unique)
+  (Bool -> SharedRep m Bool) ->
+  -- | Bool Rep
+  (a -> SharedRep m a) ->
+  -- | a Rep
+  Int ->
+  -- | maximum length of list
+  a ->
+  -- | default value for new rows
+  [a] ->
+  -- | initial values
+  SharedRep m [a]
+listRep t p brf srf n defa as =
+  second (mconcat . fmap (\(b, a) -> bool [] [a] b)) $
+    accordionBoolList
+      t
+      p
+      srf
+      brf
+      (defaultListLabels n)
+      (take n (((True,) <$> as) <> repeat (False, defa)))
+
+defaultListLabels :: Int -> [Text]
+defaultListLabels n = (\x -> "[" <> pack (show x) <> "]") <$> [0 .. n] :: [Text]
+
+-- | representation of web concerns (css, js & html)
+fiddle :: (Monad m) => Concerns Text -> SharedRep m (Concerns Text, Bool)
+fiddle (Concerns c j h) =
+  bimap
+    (\c' j' h' up -> (Lucid.with div_ [class__ "fiddle "] $ mconcat [up, h', j', c']))
+    (\c' j' h' up -> (Concerns c' j' h', up))
+    (textarea 10 (Just "css") c)
+    <<*>> textarea 10 (Just "js") j
+    <<*>> textarea 10 (Just "html") h
+    <<*>> button (Just "update")
+
+-- | turns a SharedRep into a fiddle
+viaFiddle ::
+  (Monad m) =>
+  SharedRep m a ->
+  SharedRep m (Bool, Concerns Text, a)
+viaFiddle sr = SharedRep $ do
+  sr'@(Rep h _) <- unrep sr
+  hrep <- unrep $ textarea 10 (Just "html") (toText h)
+  crep <- unrep $ textarea 10 (Just "css") mempty
+  jrep <- unrep $ textarea 10 (Just "js") mempty
+  u <- unrep $ button (Just "update")
+  pure $
+    bimap
+      (\up a b c _ -> (Lucid.with div_ [class__ "fiddle "] $ mconcat [up, a, b, c]))
+      (\up a b c d -> (up, Concerns a b c, d))
+      u
+      <<*>> crep
+      <<*>> jrep
+      <<*>> hrep
+      <<*>> sr'
diff --git a/src/Web/Page/Types.hs b/src/Web/Page/Types.hs
--- a/src/Web/Page/Types.hs
+++ b/src/Web/Page/Types.hs
@@ -3,115 +3,408 @@
 {-# LANGUAGE DeriveTraversable #-}
 {-# LANGUAGE OverloadedLabels #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE TupleSections #-}
 
 module Web.Page.Types
-  ( Page(Page)
-  , PageText(PageText)
-  , PageConfig(PageConfig)
-  , defaultPageConfig
-  , Concern(..)
-  , Concerns(Concerns)
-  , suffixes
-  , concernNames
-  , PageConcerns(..)
-  , PageStructure(..)
-  , PageRender(..)
-  ) where
+  ( Page (..),
+    PageConfig (..),
+    defaultPageConfig,
+    Concerns (..),
+    suffixes,
+    concernNames,
+    PageConcerns (..),
+    PageStructure (..),
+    PageRender (..),
+    Css (..),
+    PageCss (..),
+    renderCss,
+    renderPageCss,
+    JS (..),
+    PageJs (..),
+    onLoad,
+    renderPageJs,
+    parseJs,
+    renderJs,
+    Element (..),
+    RepF (..),
+    Rep,
+    oneRep,
+    SharedRepF (..),
+    SharedRep,
+    runOnce,
+    zeroState,
+  )
+where
 
+import qualified Clay
+import Clay (Css (..))
 import Control.Lens
-import Data.Generics.Labels()
+import Control.Monad.Morph
+import Data.Aeson
+import Data.Biapplicative
+import Data.Bifunctor (Bifunctor (..))
+import Data.Generics.Labels ()
+import Data.HashMap.Strict as HashMap hiding (foldr)
 import Data.Semigroup ((<>))
+import Data.Text (Text, unpack)
+import qualified Data.Text as Text
+import Data.Text.Lazy (toStrict)
+import GHC.Generics hiding (Rep)
+import Language.JavaScript.Parser
+import Language.JavaScript.Parser.AST
+import Language.JavaScript.Process.Minify
 import Lucid
-import Protolude hiding ((<>))
-import qualified Web.Page.Css as Css
-import qualified Web.Page.Js as Js
+import Text.InterpolatedString.Perl6
+import Prelude
+import Control.Monad.State
+import Control.Monad.IO.Class
+import Control.Applicative
 
-data Page =
-    Page
-    { libsCss :: [Html ()]
-    , libsJs :: [Html ()]
-    , cssBody :: Css.PageCss
-    , jsGlobal :: Js.PageJs
-    , jsOnLoad :: Js.PageJs
-    , htmlHeader :: Html ()
-    , htmlBody :: Html ()
-    } deriving (Show, Generic)
+-- | Components of a web page.
+--
+-- A web page typically can take many forms but still be the same web page.  For example, css can be linked to in a separate file, or can be inline within html, but still be the same css. This type represents the practical components of what makes up a web page.
+data Page
+  = Page
+      { -- | css library links
+        libsCss :: [Html ()],
+        -- | javascript library links
+        libsJs :: [Html ()],
+        -- | css
+        cssBody :: PageCss,
+        -- | javascript with global scope
+        jsGlobal :: PageJs,
+        -- | javascript included within the onLoad function
+        jsOnLoad :: PageJs,
+        -- | html within the header
+        htmlHeader :: Html (),
+        -- | body html
+        htmlBody :: Html ()
+      }
+  deriving (Show, Generic)
 
 instance Semigroup Page where
   (<>) p0 p1 =
     Page
-    (p0 ^. #libsCss <> p1 ^. #libsCss)
-    (p0 ^. #libsJs <> p1 ^. #libsJs)
-    (p0 ^. #cssBody <> p1 ^. #cssBody)
-    (p0 ^. #jsGlobal <> p1 ^. #jsGlobal)
-    (p0 ^. #jsOnLoad <> p1 ^. #jsOnLoad)
-    (p0 ^. #htmlHeader <> p1 ^. #htmlHeader)
-    (p0 ^. #htmlBody <> p1 ^. #htmlBody)
+      (p0 ^. #libsCss <> p1 ^. #libsCss)
+      (p0 ^. #libsJs <> p1 ^. #libsJs)
+      (p0 ^. #cssBody <> p1 ^. #cssBody)
+      (p0 ^. #jsGlobal <> p1 ^. #jsGlobal)
+      (p0 ^. #jsOnLoad <> p1 ^. #jsOnLoad)
+      (p0 ^. #htmlHeader <> p1 ^. #htmlHeader)
+      (p0 ^. #htmlBody <> p1 ^. #htmlBody)
 
 instance Monoid Page where
-  mempty = Page [] [] mempty mempty mempty mempty mempty
-  mappend = (<>)
 
-data PageText =
-    PageText
-    { libsCssText :: [Text]
-    , libsJsText :: [Text]
-    , cssBodyText :: Text
-    , jsGlobalText :: Text
-    , jsOnLoadText :: Text
-    , htmlHeaderText :: Text
-    , htmlBodyText :: Text
-    } deriving (Show, Generic)
+  mempty = Page [] [] mempty mempty mempty mempty mempty
 
-data Concern = Css | Js | Html deriving (Show, Eq, Generic)
+  mappend = (<>)
 
-data Concerns a =
-  Concerns
-  { css :: a
-  , js :: a
-  , html :: a
-  } deriving (Eq, Show, Foldable, Traversable, Generic)
+-- | A web page typically is composed of css, javascript and html
+--
+-- 'Concerns' abstracts this compositional feature of a web page.
+data Concerns a
+  = Concerns
+      { cssConcern :: a,
+        jsConcern :: a,
+        htmlConcern :: a
+      }
+  deriving (Eq, Show, Foldable, Traversable, Generic)
 
 instance Functor Concerns where
   fmap f (Concerns c j h) = Concerns (f c) (f j) (f h)
 
 instance Applicative Concerns where
+
   pure a = Concerns a a a
+
   Concerns f g h <*> Concerns a b c = Concerns (f a) (g b) (h c)
 
+-- | the common file suffixes of the three concerns
 suffixes :: Concerns FilePath
 suffixes = Concerns ".css" ".js" ".html"
 
+-- | create filenames for each Concern element.
 concernNames :: FilePath -> FilePath -> Concerns FilePath
 concernNames dir stem =
-  (\x->dir<>stem<>x) <$> suffixes
+  (\x -> dir <> stem <> x) <$> suffixes
 
-data PageConcerns =
-  Inline |
-  Separated
+-- | Is the rendering to include all Concerns or be separated?
+data PageConcerns
+  = Inline
+  | Separated
   deriving (Show, Eq, Generic)
 
-data PageStructure =
-  HeaderBody |
-  Headless |
-  Snippet |
-  Svg
+-- | Various ways that a Html file can be structured.
+data PageStructure
+  = HeaderBody
+  | Headless
+  | Snippet
+  | Svg
   deriving (Show, Eq, Generic)
 
-data PageRender =
-  Pretty |
-  Minified
+-- | Post-processing of page concerns
+data PageRender
+  = Pretty
+  | Minified
+  | NoPost
   deriving (Show, Eq, Generic)
 
-data PageConfig =
+-- | Configuration of the rendering of a web page
+data PageConfig
+  = PageConfig
+      { concerns :: PageConcerns,
+        structure :: PageStructure,
+        pageRender :: PageRender,
+        filenames :: Concerns FilePath,
+        localdirs :: [FilePath]
+      }
+  deriving (Show, Eq, Generic)
+
+defaultPageConfig :: FilePath -> PageConfig
+defaultPageConfig stem =
   PageConfig
-  { concerns :: PageConcerns
-  , structure :: PageStructure
-  , pageRender :: PageRender
-  , filenames :: Concerns FilePath
-  , localdirs :: [FilePath]
-  } deriving (Show, Eq, Generic)
+    Inline
+    HeaderBody
+    Minified
+    ((stem <>) <$> suffixes)
+    []
 
-defaultPageConfig :: PageConfig
-defaultPageConfig = PageConfig Inline HeaderBody Minified
-    (("default"<>) <$> suffixes) []
+-- | unifies css as a Clay.Css and css as Text
+data PageCss = PageCss Clay.Css | PageCssText Text deriving (Generic)
+
+instance Show PageCss where
+  show (PageCss css) = unpack . renderCss $ css
+  show (PageCssText txt) = unpack txt
+
+instance Semigroup PageCss where
+  (<>) (PageCss css) (PageCss css') = PageCss (css <> css')
+  (<>) (PageCssText css) (PageCssText css') = PageCssText (css <> css')
+  (<>) (PageCss css) (PageCssText css') =
+    PageCssText (renderCss css <> css')
+  (<>) (PageCssText css) (PageCss css') =
+    PageCssText (css <> renderCss css')
+
+instance Monoid PageCss where
+
+  mempty = PageCssText mempty
+
+  mappend = (<>)
+
+-- | render PageCss as text
+renderPageCss :: PageRender -> PageCss -> Text
+renderPageCss Minified (PageCss css) = toStrict $ Clay.renderWith Clay.compact [] css
+renderPageCss _ (PageCss css) = toStrict $ Clay.render css
+renderPageCss _ (PageCssText css) = css
+
+-- | render Css as text
+renderCss :: Css -> Text
+renderCss = toStrict . Clay.render
+
+-- javascript types
+
+-- | wrapper for JSAST
+newtype JS = JS {unJS :: JSAST} deriving (Show, Eq, Generic)
+
+instance Semigroup JS where
+  (<>) (JS (JSAstProgram ss ann)) (JS (JSAstProgram ss' _)) =
+    JS $ JSAstProgram (ss <> ss') ann
+  (<>) (JS (JSAstProgram ss ann)) (JS (JSAstStatement s _)) =
+    JS $ JSAstProgram (ss <> [s]) ann
+  (<>) (JS (JSAstProgram ss ann)) (JS (JSAstExpression e ann')) =
+    JS $ JSAstProgram (ss <> [JSExpressionStatement e (JSSemi ann')]) ann
+  (<>) (JS (JSAstProgram ss ann)) (JS (JSAstLiteral e ann')) =
+    JS $ JSAstProgram (ss <> [JSExpressionStatement e (JSSemi ann')]) ann
+  (<>) (JS (JSAstStatement s ann)) (JS (JSAstProgram ss _)) =
+    JS $ JSAstProgram (s : ss) ann
+  (<>) (JS (JSAstStatement s ann)) (JS (JSAstStatement s' _)) =
+    JS $ JSAstProgram [s, s'] ann
+  (<>) (JS (JSAstStatement s ann)) (JS (JSAstExpression e ann')) =
+    JS $ JSAstProgram [s, JSExpressionStatement e (JSSemi ann')] ann
+  (<>) (JS (JSAstStatement s ann)) (JS (JSAstLiteral e ann')) =
+    JS $ JSAstProgram [s, JSExpressionStatement e (JSSemi ann')] ann
+  (<>) (JS (JSAstExpression e ann)) (JS (JSAstProgram ss _)) =
+    JS $ JSAstProgram (JSExpressionStatement e (JSSemi ann) : ss) ann
+  (<>) (JS (JSAstExpression e ann)) (JS (JSAstStatement s' _)) =
+    JS $ JSAstProgram [JSExpressionStatement e (JSSemi ann), s'] ann
+  (<>) (JS (JSAstExpression e ann)) (JS (JSAstExpression e' ann')) =
+    JS $ JSAstProgram [JSExpressionStatement e (JSSemi ann), JSExpressionStatement e' (JSSemi ann')] ann
+  (<>) (JS (JSAstExpression e ann)) (JS (JSAstLiteral e' ann')) =
+    JS $ JSAstProgram [JSExpressionStatement e (JSSemi ann), JSExpressionStatement e' (JSSemi ann')] ann
+  (<>) (JS (JSAstLiteral e ann)) (JS (JSAstProgram ss _)) =
+    JS $ JSAstProgram (JSExpressionStatement e (JSSemi ann) : ss) ann
+  (<>) (JS (JSAstLiteral e ann)) (JS (JSAstStatement s' _)) =
+    JS $ JSAstProgram [JSExpressionStatement e (JSSemi ann), s'] ann
+  (<>) (JS (JSAstLiteral e ann)) (JS (JSAstExpression e' ann')) =
+    JS $ JSAstProgram [JSExpressionStatement e (JSSemi ann), JSExpressionStatement e' (JSSemi ann')] ann
+  (<>) (JS (JSAstLiteral e ann)) (JS (JSAstLiteral e' ann')) =
+    JS $ JSAstProgram [JSExpressionStatement e (JSSemi ann), JSExpressionStatement e' (JSSemi ann')] ann
+
+instance Monoid JS where
+
+  mempty = JS $ JSAstProgram [] (JSAnnot (TokenPn 0 0 0) [])
+
+  mappend = (<>)
+
+-- | unify JSStatement javascript and text-rendered script
+data PageJs = PageJs JS | PageJsText Text deriving (Eq, Show, Generic)
+
+instance Semigroup PageJs where
+  (<>) (PageJs js) (PageJs js') = PageJs (js <> js')
+  (<>) (PageJsText js) (PageJsText js') = PageJsText (js <> js')
+  (<>) (PageJs js) (PageJsText js') =
+    PageJsText (toStrict (renderToText $ unJS js) <> js')
+  (<>) (PageJsText js) (PageJs js') =
+    PageJsText (js <> toStrict (renderToText $ unJS js'))
+
+instance Monoid PageJs where
+
+  mempty = PageJs mempty
+
+  mappend = (<>)
+
+-- | wrap js in standard DOM window loader
+onLoad :: PageJs -> PageJs
+onLoad (PageJs js) = PageJs $ onLoadStatements [toStatement js]
+onLoad (PageJsText js) = PageJsText $ onLoadText js
+
+toStatement :: JS -> JSStatement
+toStatement (JS (JSAstProgram ss ann)) = JSStatementBlock JSNoAnnot ss JSNoAnnot (JSSemi ann)
+toStatement (JS (JSAstStatement s _)) = s
+toStatement (JS (JSAstExpression e ann')) = JSExpressionStatement e (JSSemi ann')
+toStatement (JS (JSAstLiteral e ann')) = JSExpressionStatement e (JSSemi ann')
+
+onLoadStatements :: [JSStatement] -> JS
+onLoadStatements js = JS $ JSAstProgram [JSAssignStatement (JSMemberDot (JSIdentifier JSNoAnnot "window") JSNoAnnot (JSIdentifier JSNoAnnot "onload")) (JSAssign JSNoAnnot) (JSFunctionExpression JSNoAnnot JSIdentNone JSNoAnnot JSLNil JSNoAnnot (JSBlock JSNoAnnot js JSNoAnnot)) JSSemiAuto] JSNoAnnot
+
+onLoadText :: Text -> Text
+onLoadText t = [qc| window.onload=function()\{{t}};|]
+
+-- | convert text to JS
+parseJs :: Text -> JS
+parseJs = JS . readJs . Text.unpack
+
+-- | render JS as text
+renderJs :: JS -> Text
+renderJs = toStrict . renderToText . unJS
+
+-- | render PageJs as text
+renderPageJs :: PageRender -> PageJs -> Text
+renderPageJs _ (PageJsText js) = js
+renderPageJs Minified (PageJs js) = toStrict . renderToText . minifyJS . unJS $ js
+renderPageJs Pretty (PageJs js) = toStrict . renderToText . unJS $ js
+
+-- | Abstracted message event element
+data Element
+  = Element
+      { element :: Text,
+        value :: Text
+      }
+  deriving (Eq, Show, Generic)
+
+instance ToJSON Element
+
+instance FromJSON Element where
+  parseJSON = withObject "Element" $ \v ->
+    Element
+      <$> v .: "element"
+      <*> v .: "value"
+
+data RepF r a
+  = Rep
+      { rep :: r,
+        make :: HashMap Text Text -> (HashMap Text Text, Either Text a)
+      }
+  deriving (Functor)
+
+type Rep a = RepF (Html ()) a
+
+instance (Semigroup r) => Semigroup (RepF r a) where
+  (Rep r0 a0) <> (Rep r1 a1) =
+    Rep
+      (r0 <> r1)
+      (\hm -> let (hm', x') = a0 hm in let (hm'', x'') = a1 hm' in (hm'', x' <> x''))
+
+instance (Monoid a, Monoid r) => Monoid (RepF r a) where
+
+  mempty = Rep mempty (,Right mempty)
+
+  mappend = (<>)
+
+instance Bifunctor RepF where
+  bimap f g (Rep r a) = Rep (f r) (second (fmap g) . a)
+
+instance Biapplicative RepF where
+
+  bipure r a = Rep r (,Right a)
+
+  (Rep fr fa) <<*>> (Rep r a) =
+    Rep
+      (fr r)
+      ( \hm ->
+          let (hm', a') = a hm in let (hm'', fa') = fa hm' in (hm'', fa' <*> a')
+      )
+
+instance (Monoid r) => Applicative (RepF r) where
+
+  pure = bipure mempty
+
+  Rep fh fm <*> Rep ah am =
+    Rep
+      (fh <> ah)
+      ( \hm ->
+          let (hm', a') = am hm in let (hm'', fa') = fm hm' in (hm'', fa' <*> a')
+      )
+
+oneRep :: (Monad m, MonadIO m) => Rep a -> (Rep a -> HashMap Text Text -> m ()) -> StateT (HashMap Text Text) m (HashMap Text Text, Either Text a)
+oneRep r@(Rep _ fa) action = do
+  m <- get
+  let (m', a) = fa m
+  put m'
+  lift $ action r m'
+  pure (m', a)
+
+newtype SharedRepF m r a
+  = SharedRep
+      { unrep :: StateT (Int, HashMap Text Text) m (RepF r a)
+      }
+  deriving (Functor)
+
+type SharedRep m a = SharedRepF m (Html ()) a
+
+instance (Functor m) => Bifunctor (SharedRepF m) where
+  bimap f g (SharedRep s) = SharedRep $ fmap (bimap f g) s
+
+instance (Monad m) => Biapplicative (SharedRepF m) where
+
+  bipure r a = SharedRep $ pure $ bipure r a
+
+  (SharedRep f) <<*>> (SharedRep a) = SharedRep $ liftA2 (<<*>>) f a
+
+instance (Monad m, Monoid r) => Applicative (SharedRepF m r) where
+
+  pure = bipure mempty
+
+  SharedRep f <*> SharedRep a = SharedRep $ liftA2 (<*>) f a
+
+-- | compute the initial state of a SharedRep (testing)
+zeroState ::
+  (Monad m) =>
+  SharedRep m a ->
+  m (Html (), (HashMap Text Text, Either Text a))
+zeroState sr = do
+  (Rep h fa, (_, m)) <- flip runStateT (0, HashMap.empty) $ unrep sr
+  pure (h, fa m)
+
+-- | compute the initial state of a SharedRep and then run a single action (testing)
+runOnce ::
+  (Monad m) =>
+  SharedRep m a ->
+  (Html () -> HashMap Text Text -> m ()) ->
+  m (HashMap Text Text, Either Text a)
+runOnce sr action = do
+  (Rep h fa, (_, m)) <- flip runStateT (0, HashMap.empty) $ unrep sr
+  action h m
+  pure (fa m)
+-- renderHtml :: Html a -> Text
+-- renderHtml = toText
diff --git a/test/test.hs b/test/test.hs
--- a/test/test.hs
+++ b/test/test.hs
@@ -5,7 +5,7 @@
 
 import Control.Lens
 import Lucid
-import Protolude
+import Prelude
 import Test.Tasty
 import Test.Tasty.Hspec
 import Web.Page
@@ -19,11 +19,11 @@
 generatePages ::
      Traversable t => FilePath -> t (FilePath, PageConfig, Page) -> IO ()
 generatePages dir xs =
-  void $ sequenceA $ (\(fp, pc, p) -> generatePage dir fp pc p) <$> xs
+  sequenceA_ $ (\(fp, pc, p) -> generatePage dir fp pc p) <$> xs
 
 genTest :: FilePath -> IO ()
 genTest dir =
-  void $ generatePages dir [("default", defaultPageConfig, page1), ("sep", cfg2, page2)]
+  void $ generatePages dir [("default", (defaultPageConfig "default"), page1), ("sep", cfg2, page2)]
 
 testVsFile :: FilePath -> FilePath -> PageConfig -> Page -> IO Bool
 testVsFile dir stem pc p = do
@@ -42,7 +42,7 @@
   let t = renderPageAsText pc' p
   case pc ^. #concerns of
     Inline -> do
-      t' <- Text.readFile (dir <> names ^. #html)
+      t' <- Text.readFile (dir <> names ^. #htmlConcern)
       return (t, Concerns mempty mempty t')
     Separated -> do
       t' <- sequenceA $ Text.readFile <$> (dir <>) <$> names
@@ -58,7 +58,7 @@
         "<!DOCTYPE HTML><html lang=\"en\"><head><meta charset=\"utf-8\"></head><body><script>window.onload=function(){}</script></body></html>"
       let dir = "test/canned/"
       it "renderPageToFile, renderPage (compared with default canned file)" $
-        testVsFile dir "default" defaultPageConfig page1 `shouldReturn` True
+        testVsFile dir "default" (defaultPageConfig "default") page1 `shouldReturn` True
       it "the various PageConfig's" $
         testVsFile dir "sep" cfg2 page2 `shouldReturn` True
 
@@ -74,7 +74,7 @@
           runIdentity .
           flip evalStateT 0 .
           accordion "acctest" Nothing $
-          (\x -> (Protolude.show x, "filler")) <$> [1..2::Int]) `shouldBe`
+          (\x -> (pack (show x), "filler")) <$> [1..2::Int]) `shouldBe`
         "<div id=\"acctest1\" class=\" accordion \"><div class=\" card \"><div id=\"acctest2\" class=\" card-header \"><h2 class=\" mb-0 \"><button data-toggle=\"collapse\" data-target=\"#acctest3\" aria-controls=\"acctest3\" type=\"button\" class=\" btn btn-link collapsed \" aria-expanded=\"false\">1</button></h2></div><div data-parent=\"#acctest1\" id=\"acctest3\" aria-labelledby=\"acctest2\" class=\" collapse \"><div class=\" card-body \">filler</div></div></div><div class=\" card \"><div id=\"acctest4\" class=\" card-header \"><h2 class=\" mb-0 \"><button data-toggle=\"collapse\" data-target=\"#acctest5\" aria-controls=\"acctest5\" type=\"button\" class=\" btn btn-link collapsed \" aria-expanded=\"false\">2</button></h2></div><div data-parent=\"#acctest1\" id=\"acctest5\" aria-labelledby=\"acctest4\" class=\" collapse \"><div class=\" card-body \">filler</div></div></div></div>"
 
 testsBridge :: IO (SpecWith ())
@@ -83,7 +83,7 @@
     describe "Web.Page.Bridge" $
       it "bridgePage versus canned" $
         toText (renderPage bridgePage) `shouldBe`
-                "<!DOCTYPE HTML><html lang=\"en\"><head><meta charset=\"utf-8\"></head><body><script>\nwindow.addEventListener('keydown',function(e) {\n  if(e.keyIdentifier=='U+000A' || e.keyIdentifier=='Enter' || e.keyCode==13) {\n    if(e.target.nodeName=='INPUT' && e.target.type !== 'textarea') {\n      e.preventDefault();\n      return false;\n    }\n  }\n}, true);\n\n\nfunction insertScript ($script) {\n  var s = document.createElement('script')\n  s.type = 'text/javascript'\n  if ($script.src) {\n    s.onload = callback\n    s.onerror = callback\n    s.src = $script.src\n  } else {\n    s.textContent = $script.innerText\n  }\n\n  // re-insert the script tag so it executes.\n  document.head.appendChild(s)\n\n  // clean-up\n  $script.parentNode.removeChild($script)\n}\n\nfunction runScripts ($container) {\n  // get scripts tags from a node\n  var $scripts = $container.querySelectorAll('script')\n  $scripts.forEach(function ($script) {\n    insertScript($script)\n  })\n}\n window.onload=function(){\nwindow.jsb = {ws: new WebSocket('ws://' + location.host + '/')};\njsb.ws.onmessage = (evt) => eval(evt.data);\n};</script></body></html>"
+                "<!DOCTYPE HTML><html lang=\"en\"><head><meta charset=\"utf-8\"></head><body><script>\nwindow.addEventListener('keydown',function(e) {\n  if(e.keyIdentifier=='U+000A' || e.keyIdentifier=='Enter' || e.keyCode==13) {\n    if(e.target.nodeName=='INPUT' && e.target.type !== 'textarea') {\n      e.preventDefault();\n      return false;\n    }\n  }\n}, true);\n\nfunction insertScript ($script) {\n  var s = document.createElement('script')\n  s.type = 'text/javascript'\n  if ($script.src) {\n    s.onload = callback\n    s.onerror = callback\n    s.src = $script.src\n  } else {\n    s.textContent = $script.innerText\n  }\n\n  // re-insert the script tag so it executes.\n  document.head.appendChild(s)\n\n  // clean-up\n  $script.parentNode.removeChild($script)\n}\n\nfunction runScripts ($container) {\n  // get scripts tags from a node\n  var $scripts = $container.querySelectorAll('script')\n  $scripts.forEach(function ($script) {\n    insertScript($script)\n  })\n}\n window.onload=function(){\nwindow.jsb = {ws: new WebSocket('ws://' + location.host + '/')};\njsb.ws.onmessage = (evt) => eval(evt.data);\n};</script></body></html>"
 
 testbs :: [Value]
 testbs =
@@ -130,8 +130,8 @@
       it "repExamples versus canned" $
         runIdentity (runOnce repExamples mempty) `shouldBe`
         (fromList [("7","3"),("1","sometext"),("4","0.5"),("2","no initial value & multi-line text\\nrenders is not ok?/"),("5","true"),("8","Square"),("3","3"),("6","false"),("9","#3880c8")],Right (RepExamples {repTextbox = "sometext", repTextarea = "no initial value & multi-line text\\nrenders is not ok?/", repSliderI = 3, repSlider = 0.5, repCheckbox = True, repToggle = False, repDropdown = 3, repShape = SquareShape, repColor = PixelRGB8 56 128 200}))
-      it "listifyExamples versus canned" $
-        runIdentity (runOnce (listifyExample 5) mempty) `shouldBe`
+      it "listExample versus canned" $
+        runIdentity (runOnce (listExample 5) mempty) `shouldBe`
         (fromList [("1","0"),("4","3"),("2","1"),("5","4"),("3","2"),("6","5")],Right [0,1,2,3,4,5])
       it "fiddleExample versus canned" $
         runIdentity (runOnce (fiddle fiddleExample) mempty) `shouldBe`
diff --git a/web-rep.cabal b/web-rep.cabal
--- a/web-rep.cabal
+++ b/web-rep.cabal
@@ -1,9 +1,9 @@
 cabal-version: 1.12
 name:           web-rep
-version:        0.1.3
-synopsis:       representations of a web pag
+version:        0.2.0
+synopsis:       representations of a web page
 category: web
-description:    See readme.md for verbage (if any)
+description:    An applicative-based, shared-data representation of a web page. 
 bug-reports:    https://github.com/tonyday567/web-page/issues
 maintainer:     Tony Day <tonyday567@gmail.com>
 license:        MIT
@@ -11,20 +11,18 @@
 build-type:     Simple
 extra-source-files:
     stack.yaml
+    readme.md
 
 library
   exposed-modules:
       Web.Page
       Web.Page.Bootstrap
       Web.Page.Bridge
-      Web.Page.Css
       Web.Page.Examples
       Web.Page.Html
       Web.Page.Html.Input
-      Web.Page.Js
       Web.Page.Render
-      Web.Page.Rep
-      Web.Page.Rep.Input
+      Web.Page.SharedReps
       Web.Page.Server
       Web.Page.Types
   hs-source-dirs:
@@ -47,7 +45,6 @@
     , lucid-svg
     , mmorph
     , mtl
-    , protolude
     , scotty
     , streaming
     , text
@@ -69,7 +66,6 @@
     , lens
     , lucid
     , optparse-generic
-    , protolude
     , scotty
     , text
     , wai
@@ -88,7 +84,6 @@
     base >= 4.12 && <5
     , lens
     , lucid
-    , protolude
     , tasty
     , tasty-hspec
     , text
