diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 # Revision history for reflex-dom-fragment-shader-canvas
 
-## 0.1 -- YYYY-mm-dd
+## 0.1.0.1 -- 2018-08-08
+
+* Try to work around the problem of lost WebGL contexts
+
+## 0.1 -- 2018-07-18
 
 * First version. Released on an unsuspecting world.
diff --git a/Reflex/Dom/FragmentShaderCanvas.hs b/Reflex/Dom/FragmentShaderCanvas.hs
--- a/Reflex/Dom/FragmentShaderCanvas.hs
+++ b/Reflex/Dom/FragmentShaderCanvas.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 {-# OPTIONS_GHC -Wno-unused-do-bind #-}
 module Reflex.Dom.FragmentShaderCanvas (fragmentShaderCanvas, trivialFragmentShader) where
 
@@ -8,12 +9,19 @@
 import Control.Lens ((^.))
 import Control.Monad.IO.Class
 
-import Reflex.Dom
+import Reflex.Dom hiding (preventDefault)
 
+import GHCJS.DOM
+import GHCJS.DOM.Document
 import GHCJS.DOM.Types hiding (Text)
-import Language.Javascript.JSaddle.String
-import Language.Javascript.JSaddle.Object (js1, js2, jsf, js, js0, new, jsg)
+import GHCJS.DOM.HTMLCanvasElement
+import GHCJS.DOM.WebGLRenderingContextBase
+import GHCJS.DOM.CanvasRenderingContext2D
+import GHCJS.DOM.EventM (on, preventDefault)
+import qualified GHCJS.DOM.EventTargetClosures as DOM (EventName, unsafeEventName)
+import Language.Javascript.JSaddle.Object (new, jsg, js1)
 
+
 vertexShaderSource :: Text
 vertexShaderSource =
   "attribute vec2 a_position;\
@@ -21,76 +29,100 @@
   \  gl_Position = vec4(a_position, 0, 1);\
   \}"
 
+-- | An example fragment shader program, drawing a red circle
 trivialFragmentShader :: Text
 trivialFragmentShader = Text.unlines
   [ "precision mediump float;"
   , "uniform vec2 u_windowSize;"
   , "void main() {"
   , "  float s = 2.0 / min(u_windowSize.x, u_windowSize.y);"
-  , "  vec2 pos0 = s * (gl_FragCoord.xy - 0.5 * u_windowSize);"
-  , "  if (length(pos0) > 1.0) { gl_FragColor = vec4(0,0,0,0); return; }"
-  , "  vec3 col0 = vec3(1.0,0.0,0.0);"
-  , "  gl_FragColor = vec4(col0, 1.0);"
+  , "  vec2 pos = s * (gl_FragCoord.xy - 0.5 * u_windowSize);"
+  , "  // pos is a scaled pixel position, (0,0) is in the center of the canvas"
+  , "  // If the position is outside the inscribed circle, make it transparent"
+  , "  if (length(pos) > 1.0) { gl_FragColor = vec4(0,0,0,0); return; }"
+  , "  // Otherwise, return red"
+  , "  gl_FragColor = vec4(1.0,0.0,0.0,1.0);"
   , "}"
   ]
 
+onOffScreenCanvas :: MonadDOM m => HTMLCanvasElement -> (HTMLCanvasElement -> m ()) -> m ()
+onOffScreenCanvas onScreen paint = do
+  doc <- currentDocumentUnchecked
+  offScreen <- createElement doc ("canvas" :: JSString)
+        >>= unsafeCastTo HTMLCanvasElement
 
-paintGL :: (MonadJSM m) => JSVal -> (Maybe Text -> m ()) -> Text -> m ()
-paintGL canvas printErr fragmentShaderSource = do
+  getWidth onScreen >>= setWidth offScreen
+  getHeight onScreen >>= setHeight offScreen
+
+  paint offScreen
+
+  ctx <- getContextUnsafe onScreen ("2d"::Text) ([]::[()])
+  ctx <- unsafeCastTo CanvasRenderingContext2D ctx
+  drawImage ctx offScreen 0 0
+  return ()
+
+
+paintGL :: MonadDOM m => (Maybe Text -> m ()) -> Text -> HTMLCanvasElement -> m ()
+paintGL printErr fragmentShaderSource canvas = do
   -- adaption of
   -- https://blog.mayflower.de/4584-Playing-around-with-pixel-shaders-in-WebGL.html
-  gl <- liftJSM $ canvas ^. js1 ("getContext"::Text) ("experimental-webgl"::Text)
-  liftJSM $ gl ^. jsf ("viewport"::Text) (0::Int, 0::Int, gl ^. js ("drawingBufferWidth"::Text), gl ^. js ("drawingBufferHeight"::Text))
 
-  -- gl ^. jsf "clearColor" [1.0, 0.0, 0.0, 1.0 :: Double]
-  -- gl ^. js1 "clear" (gl^. js "COLOR_BUFFER_BIT")
+  gl <- getContextUnsafe canvas ("experimental-webgl"::Text) ([]::[()])
+  gl <- unsafeCastTo WebGLRenderingContext gl
 
-  buffer <- liftJSM $ gl ^. js0 ("createBuffer"::Text)
-  liftJSM $ gl ^. jsf ("bindBuffer"::Text) (gl ^. js ("ARRAY_BUFFER"::Text), buffer)
-  liftJSM $ gl ^. jsf ("bufferData"::Text)
-    ( gl ^. js ("ARRAY_BUFFER"::Text)
-    , new (jsg ("Float32Array"::Text)) [[
-      -1.0, -1.0,
-       1.0, -1.0,
-      -1.0,  1.0,
-      -1.0,  1.0,
-       1.0, -1.0,
-       1.0,  1.0 :: Double]]
-    ,  gl ^. js ("STATIC_DRAW"::Text)
-    )
-  -- jsg "console" ^. js1 "log" (gl ^. js0 "getError")
+  w <- getDrawingBufferWidth gl
+  h <- getDrawingBufferHeight gl
+  viewport gl 0 0 w h
 
-  vertexShader <- liftJSM $ gl ^. js1 ("createShader"::Text) (gl ^. js ("VERTEX_SHADER"::Text))
-  liftJSM $ gl ^. js2 ("shaderSource"::Text) vertexShader vertexShaderSource
-  liftJSM $ gl ^. js1 ("compileShader"::Text) vertexShader
+  buffer <- createBuffer gl
+  bindBuffer gl ARRAY_BUFFER (Just buffer)
+  array <- liftDOM (new (jsg ("Float32Array"::Text))
+        [[ -1.0, -1.0,
+            1.0, -1.0,
+           -1.0,  1.0,
+           -1.0,  1.0,
+            1.0, -1.0,
+            1.0,  1.0 :: Double]])
+    >>= unsafeCastTo Float32Array
+  let array' = uncheckedCastTo ArrayBuffer array
+  bufferData gl ARRAY_BUFFER (Just array') STATIC_DRAW
+
+  vertexShader <- createShader gl VERTEX_SHADER
+  shaderSource gl (Just vertexShader) vertexShaderSource
+  compileShader gl (Just vertexShader)
   -- jsg "console" ^. js1 "log" (gl ^. js1 "getShaderInfoLog" vertexShader)
 
-  fragmentShader <- liftJSM $ gl ^. js1 ("createShader"::Text) (gl ^. js ("FRAGMENT_SHADER"::Text))
-  liftJSM $ gl ^. js2 ("shaderSource"::Text) fragmentShader fragmentShaderSource
-  liftJSM $ gl ^. js1 ("compileShader"::Text) fragmentShader
+  fragmentShader <- createShader gl FRAGMENT_SHADER
+  shaderSource gl (Just fragmentShader) fragmentShaderSource
+  compileShader gl (Just fragmentShader)
   -- jsg "console" ^. js1 "log" (gl ^. js1 "getShaderInfoLog" fragmentShader)
-  err <- liftJSM $ gl ^. js1 ("getShaderInfoLog"::Text) fragmentShader
-  -- liftJSM $ jsg ("console"::Text) ^. js1 ("log"::Text) err
-  printErr . fmap textFromJSString =<< liftJSM (fromJSVal err)
+  err <- getShaderInfoLog gl (Just fragmentShader)
+  printErr err
 
-  program <- liftJSM $ gl ^. js0 ("createProgram"::Text)
-  liftJSM $ gl ^. js2 ("attachShader"::Text) program vertexShader
-  liftJSM $ gl ^. js2 ("attachShader"::Text) program fragmentShader
-  liftJSM $ gl ^. js1 ("linkProgram"::Text) program
-  liftJSM $ gl ^. js1 ("useProgram"::Text) program
+  program <- createProgram gl
+  attachShader gl (Just program) (Just vertexShader)
+  attachShader gl (Just program) (Just fragmentShader)
+  linkProgram gl (Just program)
+  useProgram gl (Just program)
   -- jsg "console" ^. js1 "log" (gl ^. js1 "getProgramInfoLog" program)
 
-  positionLocation <- liftJSM $ gl ^. js2 ("getAttribLocation"::Text) program ("a_position"::Text)
-  liftJSM $ gl ^. js1 ("enableVertexAttribArray"::Text) positionLocation
-  liftJSM $ gl ^. jsf ("vertexAttribPointer"::Text) (positionLocation, 2::Int, gl ^. js ("FLOAT"::Text), False, 0::Int, 0::Int)
-  liftJSM $ jsg ("console"::Text) ^. js1 ("log"::Text) program
+  positionLocation <- getAttribLocation gl (Just program) ("a_position" :: Text)
+  enableVertexAttribArray gl (fromIntegral positionLocation)
+  vertexAttribPointer gl (fromIntegral positionLocation) 2 FLOAT False 0 0
+  -- liftJSM $ jsg ("console"::Text) ^. js1 ("log"::Text) program
 
-  windowSizeLocation <- liftJSM $ gl ^. js2 ("getUniformLocation"::Text) program ("u_windowSize"::Text)
-  liftJSM $ gl ^. jsf ("uniform2f"::Text) (windowSizeLocation, gl ^. js ("drawingBufferWidth"::Text), gl ^. js ("drawingBufferHeight"::Text))
+  windowSizeLocation <- getUniformLocation gl (Just program) ("u_windowSize" :: Text)
+  uniform2f gl (Just windowSizeLocation) (fromIntegral w) (fromIntegral h)
 
-  liftJSM $ gl ^. jsf ("drawArrays"::Text) (gl ^. js ("TRIANGLES"::Text), 0::Int, 6::Int);
+  drawArrays gl TRIANGLES 0 6
   return ()
 
+webglcontextrestored :: DOM.EventName HTMLCanvasElement WebGLContextEvent
+webglcontextrestored = DOM.unsafeEventName "webglcontextrestored"
+
+webglcontextlost :: DOM.EventName HTMLCanvasElement WebGLContextEvent
+webglcontextlost = DOM.unsafeEventName "webglcontextlost"
+
 fragmentShaderCanvas ::
     (MonadWidget t m) =>
     (Map Text Text) ->
@@ -100,11 +132,29 @@
   (canvasEl, _) <- elAttr' "canvas" attrs $ blank
   (eError, reportError) <- newTriggerEvent
   pb <- getPostBuild
-  performEvent $ (<$ pb) $ do
-    e <- liftJSM $ fromJSValUnchecked =<< toJSVal (_element_raw canvasEl)
-    src0 <- sample (current fragmentShaderSource)
-    paintGL e (liftIO . reportError) src0
-  performEvent $ (<$> updated fragmentShaderSource) $ \src -> do
-    e <- liftJSM $ fromJSValUnchecked =<< toJSVal (_element_raw canvasEl)
-    paintGL e (liftIO . reportError) src
+
+  domEl <- unsafeCastTo HTMLCanvasElement $ _element_raw canvasEl
+
+  {-
+  eContextBack <- wrapDomEvent domEl (`on` webglcontextrestored) (return ())
+  eContextLost <- wrapDomEvent domEl (`on` webglcontextlost)     preventDefault
+
+  performEvent $ (<$> eContextLost) $ \() -> do
+    liftJSM $
+        jsg ("console"::Text) ^. js1 ("log"::Text) ("lost" :: Text)
+
+  performEvent $ (<$> eContextBack) $ \() -> do
+    liftJSM $
+        jsg ("console"::Text) ^. js1 ("log"::Text) ("back" :: Text)
+  -}
+
+  let eDraw = leftmost
+                [ updated fragmentShaderSource
+                , tag (current fragmentShaderSource) pb
+  --              , tag (current fragmentShaderSource) eContextBack
+                ]
+
+  performEvent $ (<$> eDraw) $ \src -> do
+    onOffScreenCanvas domEl $ paintGL (liftIO . reportError) src
+
   holdDyn Nothing eError
diff --git a/demo/Main.hs b/demo/Main.hs
--- a/demo/Main.hs
+++ b/demo/Main.hs
@@ -6,59 +6,59 @@
 import qualified Data.Text as T
 
 main :: IO ()
-main = mainWidgetWithHead
-    (el "style" (text css) >> el "title" (text "Fragment Shader Demo")) $ mdo
-        inp <- divClass "left" $ do
-            inp <- textArea $ def
-               & textAreaConfig_initialValue .~ trivialFragmentShader
-            divClass "error" $ dynText (maybe "" id <$> dError)
-            return inp
+main = mainWidgetWithHead htmlHead $ mdo
+    inp <- divClass "left" $ do
+        inp <- textArea $ def
+           & textAreaConfig_initialValue .~ trivialFragmentShader
+        divClass "error" $ dynText (maybe "" id <$> dError)
+        return inp
 
-        dError <- divClass "right" $ fragmentShaderCanvas
-            (mconcat [ "width"  =: "1000" , "height" =: "1000" ])
-            (_textArea_value inp)
-        return ()
+    dError <- divClass "right" $ fragmentShaderCanvas
+        -- Here we determine the resolution of the canvas
+        -- It would be desireable to do so dynamically, based on the widget
+        -- size. But Reflex.Dom.Widget.Resize messes with the CSS layout.
+        (mconcat [ "width"  =: "1000" , "height" =: "1000" ])
+        (_textArea_value inp)
+    return ()
+  where
+    htmlHead :: DomBuilder t m => m ()
+    htmlHead = do
+        el "style" (text css)
+        el "title" (text "Fragment Shader Demo")
 
 css :: T.Text
 css = T.unlines
-    [ "document {"
+    [ "html {"
     , "  margin: 0;"
-    , "  padding: 0;"
-    , "  width: 100vw;"
-    , "  height: 100vh;"
+    , "  height: 100%;"
     , "}"
     , "body {"
-    , "  margin: 0;"
-    , "  padding: 0;"
     , "  display: flex;"
-    , "  align-items: stretch;"
-    , "  width: 100vw;"
-    , "  height: 100vh;"
+    , "  height: 100%;"
     , "}"
+    , ".left {"
+    , "  flex:1 1 0;"
+    , "  display:flex;"
+    , "  flex-direction:column;"
+    , "  padding:1em;"
+    , "}"
+    , ".right {"
+    , "  flex:1 1 0;"
+    , "}"
     , "textarea {"
-    , "  width: 50vw;"
-    , "  height: 50vh;"
+    , "  resize:vertical;"
+    , "  height:50%;"
     , "}"
     , ".error {"
-    , "  width: 100%;"
+    , "  margin-top:1em;"
     , "  text-align: left;"
-    , "  white-space:pre;"
     , "  font-family:mono;"
-    , "  padding-top: 2em;"
-    , "  overflow: scrolll"
-    , "}"
-    , ".left {"
-    , "  width:50%;"
-    , "  padding:2em;"
-    , "}"
-    , ".right {"
-    , "  width:50%;"
-    , "  display: flex;"
+    , "  width:100%;"
+    , "  overflow: auto;"
     , "}"
     , "canvas {"
-    , "  border: 1px solid black;"
-    , "  max-width: 80%;"
-    , "  max-height: 80%;"
-    , "  margin:auto;"
+    , "  height:100%;"
+    , "  width:100%;"
+    , "  object-fit:contain;"
     , "}"
     ]
diff --git a/reflex-dom-fragment-shader-canvas.cabal b/reflex-dom-fragment-shader-canvas.cabal
--- a/reflex-dom-fragment-shader-canvas.cabal
+++ b/reflex-dom-fragment-shader-canvas.cabal
@@ -1,11 +1,13 @@
 name:                reflex-dom-fragment-shader-canvas
-version:             0.1
+version:             0.1.0.1
 synopsis:            A reflex-dom widget to draw on a canvas with a fragment shader program
 description:
   This simple reflex-dom widget takes a `Dynamic t Text` value representing
   the source code of a WebGL fragment shader, and renders it to
   a HTML canvas element.
   .
+  A live demo can be found at <https://nomeata.github.io/reflex-dom-fragment-shader-canvas/>.
+  .
   It also provides possible compiler errors in another `Dynamic t Text`.
 homepage:            https://github.com/nomeata/reflex-dom-fragment-shader-canvas
 license:             MIT
@@ -26,10 +28,10 @@
 library
   exposed-modules: Reflex.Dom.FragmentShaderCanvas
   build-depends: base >=4.2 && <5
-  build-depends: jsaddle >=0.9.5.0 && <0.10
+  build-depends: ghcjs-dom >=0.9.2 && <0.10
+  build-depends: jsaddle >=0.9.4 && <0.10
   build-depends: reflex-dom >= 0.4
   build-depends: lens >=4.0.7 && <5.0
-  build-depends: ghcjs-dom
   build-depends: transformers
   build-depends: containers
   build-depends: text
