diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,12 @@
+### 1.0.0.2
+
+- Use the recently published nanovg-0.8.0.0 from Hackage, instead of the version from the PR's commit.
+- Added `appRenderOnMainThread` option.
+
+### 1.0.0.1
+
+- Fix Haddocks for widget configuration types.
+
 ### 1.0.0.0
 
 Initial public release
diff --git a/monomer.cabal b/monomer.cabal
--- a/monomer.cabal
+++ b/monomer.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           monomer
-version:        1.0.0.1
+version:        1.0.0.2
 synopsis:       A GUI library for writing native Haskell applications.
 description:    Monomer is an easy to use, cross platform, GUI library for writing native
                 Haskell applications.
diff --git a/src/Monomer/Main/Core.hs b/src/Monomer/Main/Core.hs
--- a/src/Monomer/Main/Core.hs
+++ b/src/Monomer/Main/Core.hs
@@ -70,6 +70,7 @@
 
 data MainLoopArgs sp e ep = MainLoopArgs {
   _mlOS :: Text,
+  _mlRenderer :: Maybe Renderer,
   _mlTheme :: Theme,
   _mlAppStartTs :: Int,
   _mlMaxFps :: Int,
@@ -132,6 +133,7 @@
   dpr <- use L.dpr
   winSize <- use L.windowSize
 
+  let useRenderThread = fromMaybe True (_apcUseRenderThread config)
   let maxFps = fromMaybe 60 (_apcMaxFps config)
   let fonts = _apcFonts config
   let theme = fromMaybe def (_apcTheme config)
@@ -143,6 +145,9 @@
   model <- use L.mainModel
   os <- getPlatform
   widgetSharedMVar <- liftIO $ newMVar Map.empty
+  renderer <- if useRenderThread
+    then return Nothing
+    else liftIO $ Just <$> makeRenderer fonts dpr
   fontManager <- liftIO $ makeFontManager fonts dpr
 
   let wenv = WidgetEnv {
@@ -179,6 +184,7 @@
 
   let loopArgs = MainLoopArgs {
     _mlOS = os,
+    _mlRenderer = renderer,
     _mlTheme = theme,
     _mlMaxFps = maxFps,
     _mlAppStartTs = 0,
@@ -194,10 +200,11 @@
 
   L.mainModel .= _weModel newWenv
 
-  liftIO . forkOS . void $
-    startRenderThread channel window glCtx fonts dpr newWenv newRoot
+  when useRenderThread $ do
+    liftIO $ watchWindowResize channel
+    liftIO . void . forkOS $
+      startRenderThread channel window glCtx fonts dpr newWenv newRoot
 
-  liftIO $ watchWindowResize channel
   mainLoop window fontManager config loopArgs
 
 mainLoop
@@ -297,12 +304,19 @@
   -- Rendering
   renderCurrentReq <- checkRenderCurrent startTicks _mlLatestRenderTs
 
+  let useRenderThread = fromMaybe True (_apcUseRenderThread config)
   let renderEvent = any isActionEvent eventsPayload
   let winRedrawEvt = windowResized || windowExposed
   let renderNeeded = winRedrawEvt || renderEvent || renderCurrentReq
 
-  when renderNeeded $
+  when (renderNeeded && useRenderThread) $
     liftIO . atomically $ writeTChan _mlChannel (MsgRender newWenv newRoot)
+
+  when (renderNeeded && not useRenderThread) $ do
+    let renderer = fromJust _mlRenderer
+    let bgColor = newWenv ^. L.theme . L.clearColor
+
+    liftIO $ renderWidgets window dpr renderer bgColor newWenv newRoot
 
   L.renderRequested .= windowResized
 
diff --git a/src/Monomer/Main/Types.hs b/src/Monomer/Main/Types.hs
--- a/src/Monomer/Main/Types.hs
+++ b/src/Monomer/Main/Types.hs
@@ -152,6 +152,8 @@
   _apcWindowResizable :: Maybe Bool,
   -- | Whether the main window has a border.
   _apcWindowBorder :: Maybe Bool,
+  -- | Whether a separate render thread should be used. Defaults to True.
+  _apcUseRenderThread :: Maybe Bool,
   {-|
   Max number of FPS the application will run at. It does not necessarily mean
   rendering will happen every frame, but events and schedules will be checked at
@@ -191,6 +193,7 @@
     _apcWindowTitle = Nothing,
     _apcWindowResizable = Nothing,
     _apcWindowBorder = Nothing,
+    _apcUseRenderThread = Nothing,
     _apcMaxFps = Nothing,
     _apcScaleFactor = Nothing,
     _apcFonts = [],
@@ -209,6 +212,7 @@
     _apcWindowTitle = _apcWindowTitle a2 <|> _apcWindowTitle a1,
     _apcWindowResizable = _apcWindowResizable a2 <|> _apcWindowResizable a1,
     _apcWindowBorder = _apcWindowBorder a2 <|> _apcWindowBorder a1,
+    _apcUseRenderThread = _apcUseRenderThread a2 <|> _apcUseRenderThread a1,
     _apcMaxFps = _apcMaxFps a2 <|> _apcMaxFps a1,
     _apcScaleFactor = _apcScaleFactor a2 <|> _apcScaleFactor a1,
     _apcFonts = _apcFonts a1 ++ _apcFonts a2,
@@ -249,7 +253,22 @@
 }
 
 {-|
-Max number of FPS the application will run. It does not necessarily mean
+Performs rendering on the main thread. On macOS and Windows this also disables
+continuous rendering on window resize, but in some Linux configurations it still
+works.
+
+This option is useful when OpenGL driver issues prevent normal startup showing
+the "Unable to make GL context current" error.
+
+It can also be used for single threaded applications (without -threaded).
+-}
+appRenderOnMainThread :: AppConfig e
+appRenderOnMainThread = def {
+  _apcUseRenderThread = Just False
+}
+
+{-|
+Max number of FPS the application will run on. It does not necessarily mean
 rendering will happen every frame, but events and schedules will be checked at
 this rate and may cause it.
 -}
