diff --git a/docs/components/home/Home.vue b/docs/components/home/Home.vue
index c3b02cd2..2274543e 100644
--- a/docs/components/home/Home.vue
+++ b/docs/components/home/Home.vue
@@ -1,9 +1,13 @@
diff --git a/docs/components/utils.ts b/docs/components/utils.ts
new file mode 100644
index 00000000..935b56ef
--- /dev/null
+++ b/docs/components/utils.ts
@@ -0,0 +1,41 @@
+import Blobity from 'blobity'
+import type { InjectionKey, Ref } from 'vue'
+
+const BlobityInjection: InjectionKey[> = Symbol('blobity')
+
+const defaultOptions = {
+ licenseKey: 'opensource',
+ invert: true,
+ zIndex: 0,
+ magnetic: false,
+ dotColor: '#10b981',
+ radius: 8,
+ focusableElementsOffsetX: 5,
+ focusableElementsOffsetY: 4,
+ mode: 'normal',
+ focusableElements:
+ '[data-blobity], a:not([data-no-blobity]), button:not([data-no-blobity]), [data-blobity-tooltip], .back-to-top, .intro',
+}
+
+export const useBlobity = createSharedComposable(() => {
+ const blobity = ref(new Blobity(defaultOptions as any))
+
+ provide(BlobityInjection, blobity)
+
+ const { y } = useWindowScroll()
+
+ onBeforeUnmount(() => {
+ blobity.value.destroy()
+ })
+
+ function reset() {
+ blobity.value.reset()
+ blobity.value.updateOptions(defaultOptions as any)
+ }
+
+ watch(y, () => {
+ blobity.value.bounce()
+ })
+
+ return { blobity, reset }
+})
]