diff --git a/lazy_player/reactive.py b/lazy_player/reactive/__init__.py
similarity index 100%
rename from lazy_player/reactive.py
rename to lazy_player/reactive/__init__.py
diff --git a/lazy_player/reactive/gobject.py b/lazy_player/reactive/gobject.py
new file mode 100644
index 0000000..0e245fe
--- /dev/null
+++ b/lazy_player/reactive/gobject.py
@@ -0,0 +1,27 @@
+from __future__ import annotations
+
+from typing import Any, TypeVar
+
+from gi.repository import GObject
+
+from . import Ref
+
+__all__ = ["GRef"]
+
+T = TypeVar("T")
+
+
+class GRef(Ref[T]):
+    _prop_name: str
+    _gobject: GObject.Object
+
+    def __init__(self, gobj: GObject.Object, prop_name: str):
+        super().__init__(gobj.get_property(prop_name))
+        self._prop_name = prop_name
+        gobj.connect(f"notify::{prop_name}", self._on_notify)
+
+    def _on_notify(self, *args: Any):
+        self.value = self._gobject.get_property(self._prop_name)
+
+    def __repr__(self):
+        return f"GRef(gobj={self._gobject!r}, prop_name={self._prop_name!r})"