diff --git a/python_payload/apps/gr33nhouse/__init__.py b/python_payload/apps/gr33nhouse/__init__.py
index 92905eb0cdde7fac6bee4f35c9c41e61ae95a869..28b2801f63e73a441a2b765fbf8c7495880173c3 100644
--- a/python_payload/apps/gr33nhouse/__init__.py
+++ b/python_payload/apps/gr33nhouse/__init__.py
@@ -1,20 +1,28 @@
+from st3m.goose import Enum
 from st3m.application import Application, ApplicationContext
 from st3m.input import InputController, InputState
 from st3m.ui import colours
 from st3m.ui.view import ViewManager
 from ctx import Context
+import network
 from .applist import AppList
 from .background import Flow3rView
 from .record import RecordView
 from .manual import ManualInputView
 
 
+class ViewState(Enum):
+    CONTENT = 1
+    NO_INTERNET = 2
+
+
 class Gr33nhouseApp(Application):
     items = ["Browse apps", "Record App Seed", "Enter App Seed"]
     selection = 0
 
     input: InputController
     background: Flow3rView
+    state: ViewState
 
     def __init__(self, app_ctx: ApplicationContext) -> None:
         super().__init__(app_ctx=app_ctx)
@@ -22,6 +30,8 @@ class Gr33nhouseApp(Application):
         self.input = InputController()
         self.background = Flow3rView()
 
+        self.state = ViewState.CONTENT
+
     def on_enter(self, vm: ViewManager | None) -> None:
         super().on_enter(vm)
 
@@ -29,6 +39,32 @@ class Gr33nhouseApp(Application):
             raise RuntimeError("vm is None")
 
     def draw(self, ctx: Context) -> None:
+        if self.state == ViewState.NO_INTERNET:
+            ctx.move_to(0, 0)
+            ctx.rgb(*colours.BLACK)
+            ctx.rectangle(
+                -120.0,
+                -120.0,
+                240.0,
+                240.0,
+            ).fill()
+
+            ctx.save()
+            ctx.rgb(*colours.WHITE)
+            ctx.font = "Camp Font 3"
+            ctx.font_size = 24
+            ctx.text_align = ctx.CENTER
+            ctx.text_baseline = ctx.MIDDLE
+
+            ctx.move_to(0, -15)
+            ctx.text("No internet")
+
+            ctx.move_to(0, 15)
+            ctx.text("Check settings")
+
+            ctx.restore()
+            return
+
         self.background.draw(ctx)
         ctx.save()
 
@@ -62,11 +98,18 @@ class Gr33nhouseApp(Application):
         ctx.restore()
 
     def think(self, ins: InputState, delta_ms: int) -> None:
+        self.input.think(ins, delta_ms)
+
         if self.vm is None:
             raise RuntimeError("vm is None")
 
+        if not network.WLAN(network.STA_IF).isconnected():
+            self.state = ViewState.NO_INTERNET
+            return
+        else:
+            self.state = ViewState.CONTENT
+
         self.background.think(ins, delta_ms)
-        self.input.think(ins, delta_ms)
 
         if self.input.buttons.app.left.pressed:
             if self.selection > 0:
diff --git a/python_payload/apps/gr33nhouse/confirmation.py b/python_payload/apps/gr33nhouse/confirmation.py
index fb4a4f63c1fa69081d1e2bb125e828673734cceb..ba23a9629419699df492851fcad4a72101b858d5 100644
--- a/python_payload/apps/gr33nhouse/confirmation.py
+++ b/python_payload/apps/gr33nhouse/confirmation.py
@@ -78,7 +78,7 @@ class ConfirmationView(BaseView):
             raise RuntimeError("vm is None")
 
         if self.input.buttons.app.middle.pressed:
-            self.vm.push(
+            self.vm.replace(
                 DownloadView(
                     url=self.url,
                 )
diff --git a/python_payload/apps/gr33nhouse/download.py b/python_payload/apps/gr33nhouse/download.py
index bdbb37bc31b9570449dde9658af1ef6959d1cde5..20fab528c40c25fe2578a6deea13450cca2b7e12 100644
--- a/python_payload/apps/gr33nhouse/download.py
+++ b/python_payload/apps/gr33nhouse/download.py
@@ -1,5 +1,6 @@
-from st3m.input import InputState
+from st3m.input import InputController, InputState
 from st3m.goose import Optional
+from st3m.ui import colours
 import urequests
 import gzip
 from utarfile import TarFile, DIRTYPE
@@ -12,29 +13,74 @@ from ctx import Context
 class DownloadView(BaseView):
     response: Optional[urequests.Response]
 
+    """
+    View state
+
+    1 = Init
+    2 = Fetching
+    3 = Extracting
+    4 = Extracting
+    5 = Done
+    """
+    state: int
+
+    input: InputController
+
     def __init__(self, url: str) -> None:
         super().__init__()
         self._state = 1
         self._try = 1
         self._url = url
 
+        self.input = InputController()
+
     def draw(self, ctx: Context) -> None:
         ctx.rgb(0, 0, 0).rectangle(-120, -120, 240, 240).fill()
 
+        ctx.save()
+        ctx.move_to(0, 0)
         if self._state == 1 or self._state == 2:
             # Fetching
-            ctx.rgb(255, 0, 0).rectangle(-20, -20, 40, 40).fill()
+            ctx.rgb(*colours.WHITE)
+            ctx.font = "Camp Font 3"
+            ctx.font_size = 24
+            ctx.text_align = ctx.CENTER
+            ctx.text_baseline = ctx.MIDDLE
+            ctx.text("Downloading...")
+
             self._state = 2
         elif self._state == 3 or self._state == 4:
             # Extracting
-            ctx.rgb(0, 0, 255).rectangle(-20, -20, 40, 40).fill()
+            ctx.rgb(*colours.WHITE)
+            ctx.font = "Camp Font 3"
+            ctx.font_size = 24
+            ctx.text_align = ctx.CENTER
+            ctx.text_baseline = ctx.MIDDLE
+            ctx.text("Extracting...")
+
             self._state = 4
         elif self._state == 5:
             # Done
-            ctx.rgb(0, 255, 0).rectangle(-20, -20, 40, 40).fill()
+            ctx.move_to(0, -30)
+
+            ctx.rgb(*colours.WHITE)
+            ctx.font = "Camp Font 3"
+            ctx.font_size = 24
+            ctx.text_align = ctx.CENTER
+            ctx.text_baseline = ctx.MIDDLE
+            ctx.text("All done!")
+
+            ctx.move_to(0, 0)
+            ctx.text("The app will be")
+
+            ctx.move_to(0, 30)
+            ctx.text("available after reboot")
+
+        ctx.restore()
 
     def think(self, ins: InputState, delta_ms: int) -> None:
-        super().think(ins, delta_ms)  # Let BaseView do its thing
+        # super().think(ins, delta_ms)  # Let BaseView do its thing
+        self.input.think(ins, delta_ms)
 
         if self._state == 2:
             try:
@@ -76,6 +122,7 @@ class DownloadView(BaseView):
                         of.write(f.read())
             self._state = 5
 
+        if self.input.buttons.app.middle.pressed:
             if self.vm is None:
                 raise RuntimeError("vm is None")
             self.vm.pop()