diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Revision history for tinyapp
 
+## 0.2.0.0 -- 2024-11-01
+
+* Add support for interactive applications that renders text based on keystrokes. Great for small games.
+
 ## 0.1.0.0 -- 2024-07-18
 
-* First version.
+* Add support for REPL applications.
diff --git a/src/TinyApp/Interactive.hs b/src/TinyApp/Interactive.hs
new file mode 100644
--- /dev/null
+++ b/src/TinyApp/Interactive.hs
@@ -0,0 +1,135 @@
+-- | Build interactice apps that reacts to each keystroke and renders text
+-- Requires `ghc-options: -threaded`
+module TinyApp.Interactive
+  ( Event (..),
+    Key (..),
+    Modifier (..),
+    Sandbox (..),
+    ContinueExit (..),
+    runInteractive,
+    runInteractive',
+  )
+where
+
+import Brick qualified as B
+import Brick.Main qualified as BM
+import Brick.Types qualified as BT
+import Brick.Widgets.Core qualified as BWC
+import Control.Monad
+import Control.Monad.State
+import Graphics.Vty qualified as V
+import Graphics.Vty.Input.Events qualified as VE
+
+-- | Representes keys that can be pressed
+data Key
+  = KEsc
+  | KChar Char
+  | KBS
+  | KEnter
+  | KLeft
+  | KRight
+  | KUp
+  | KDown
+  | KUpLeft
+  | KUpRight
+  | KDownLeft
+  | KDownRight
+  | KCenter
+  | KFun Int
+  | KBackTab
+  | KPrtScr
+  | KPause
+  | KIns
+  | KHome
+  | KPageUp
+  | KDel
+  | KEnd
+  | KPageDown
+  | KBegin
+  | KMenu
+  deriving (Eq, Show, Read, Ord)
+
+fromVKey :: V.Key -> Key
+fromVKey V.KEsc = KEsc
+fromVKey (V.KChar char) = KChar char
+fromVKey V.KBS = KBS
+fromVKey V.KEnter = KEnter
+fromVKey V.KLeft = KLeft
+fromVKey V.KRight = KRight
+fromVKey V.KUp = KUp
+fromVKey V.KDown = KDown
+fromVKey V.KUpLeft = KUpLeft
+fromVKey V.KUpRight = KUpRight
+fromVKey V.KDownLeft = KDownLeft
+fromVKey V.KDownRight = KDownRight
+fromVKey V.KCenter = KCenter
+fromVKey (V.KFun int) = KFun int
+fromVKey V.KBackTab = KBackTab
+fromVKey V.KPrtScr = KPrtScr
+fromVKey V.KPause = KPause
+fromVKey V.KIns = KIns
+fromVKey V.KHome = KHome
+fromVKey V.KPageUp = KPageUp
+fromVKey V.KDel = KDel
+fromVKey V.KEnd = KEnd
+fromVKey V.KPageDown = KPageDown
+fromVKey V.KBegin = KBegin
+fromVKey V.KMenu = KMenu
+
+-- | Modifiers keys
+data Modifier = MShift | MCtrl | MMeta | MAlt
+  deriving (Eq, Show, Read, Ord)
+
+fromVModifier :: V.Modifier -> Modifier
+fromVModifier V.MShift = MShift
+fromVModifier V.MCtrl = MCtrl
+fromVModifier V.MMeta = MMeta
+fromVModifier V.MAlt = MAlt
+
+-- | Event the application can receive
+data Event = Key Key [Modifier]
+
+-- | Signals whether the application should continue waiting input from the user or exit.
+data ContinueExit = Continue | Exit
+  deriving (Eq, Show)
+
+-- | Defines an interactive application that is not allowed to perform arbitrary IO while executing.
+data Sandbox state = Sandbox
+  { -- | Initial state
+    initialize :: state,
+    -- | What to draw based on the current state.
+    -- The screen is cleared between render calls. Usually use '\n' or *Prelude.unlines* to render multiple lines.
+    render :: state -> String,
+    -- | Process the event given the current state
+    -- Returns the next state and whether to continue or not the program
+    update :: Event -> state -> (state, ContinueExit)
+  }
+
+-- | Executes the application.
+runInteractive :: Sandbox s -> IO ()
+runInteractive = Control.Monad.void . runInteractive'
+
+-- | Executes the application returning its final state.
+runInteractive' :: forall s. Sandbox s -> IO s
+runInteractive' config =
+  let app :: BM.App s e ()
+      app =
+        BM.App
+          { BM.appDraw = \s -> [BWC.str (config.render s)],
+            BM.appChooseCursor = \_ _ -> Nothing,
+            BM.appHandleEvent = \e -> do
+              s <- get
+              case e of
+                BT.VtyEvent (VE.EvKey k ms) ->
+                  case config.update (Key (fromVKey k) (map fromVModifier ms)) s of
+                    (s', Continue) -> do
+                      put s'
+                    (s', Exit) -> do
+                      put s'
+                      BM.halt
+                _ ->
+                  return (),
+            BM.appStartEvent = return (),
+            BM.appAttrMap = \_ -> B.attrMap V.defAttr []
+          }
+   in BM.defaultMain app config.initialize
diff --git a/src/TinyApp/Repl.hs b/src/TinyApp/Repl.hs
--- a/src/TinyApp/Repl.hs
+++ b/src/TinyApp/Repl.hs
@@ -5,11 +5,11 @@
 import Control.Monad
 import System.IO
 
--- | Signals whether the REPL should continue asking input from the user or exit.
+-- | Signals whether the application should continue asking input from the user or exit.
 data ContinueExit = Continue | Exit
   deriving (Eq, Show)
 
--- | Defines a REPL application that is not allows to perform arbitrary IO while executing.
+-- | Defines a REPL application that is not allowed to perform arbitrary IO while executing.
 data Sandbox state = Sandbox
   { -- | Initial state
     initialize :: state,
diff --git a/tinyapp.cabal b/tinyapp.cabal
--- a/tinyapp.cabal
+++ b/tinyapp.cabal
@@ -1,8 +1,8 @@
 cabal-version:      3.0
 name:               tinyapp
-version:            0.1.0.2
+version:            0.2.0.0
 synopsis:           Library to build tiny apps in Haskell
-description:        Library to build tiny apps in Haskell such a REPLs
+description:        Library to build tiny apps in Haskell such a REPLs or text-based applications that reacts to keystrokes
 homepage:           https://github.com/bcardiff/haskell-tinyapp
 license:            MIT
 license-file:       LICENSE
@@ -12,7 +12,7 @@
 build-type:         Simple
 extra-doc-files:    CHANGELOG.md
 -- extra-source-files:
-category:           REPL, Command Line
+category:           REPL, tui, Command Line
 
 common warnings
     ghc-options: -Wall
@@ -21,10 +21,14 @@
     import:           warnings
     exposed-modules:
         TinyApp.Repl
+        TinyApp.Interactive
     -- other-modules:
     -- other-extensions:
     build-depends:
-        base >=4.17.2.1 && <5.0
+        base >=4.17.2.1 && <5.0,
+        brick >= 2.4 && < 2.5,
+        vty >= 6.2 && < 6.3,
+        mtl >= 2.2.2 && < 2.3,
     hs-source-dirs:   src
     default-language: GHC2021
     default-extensions:
