diff --git a/packages/client/src/components/InstallButton.tsx b/packages/client/src/components/InstallButton.tsx
deleted file mode 100644
index 95f79bc..0000000
--- a/packages/client/src/components/InstallButton.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import { IconButton } from '@chakra-ui/react';
-import { HardDriveDownload } from 'lucide-react';
-import React from 'react';
-
-import { toolbarButtonZIndex } from './toolbar/Toolbar.tsx';
-
-function InstallButton() {
- // const install = usePWAInstall();
-
- const install = () => {
- console.warn('this does not work in all browsers');
- };
- return (
- }
- size="md"
- bg="transparent"
- stroke="text.accent"
- color="text.accent"
- onClick={() => install}
- _hover={{
- bg: 'transparent',
- svg: {
- stroke: 'accent.secondary',
- transition: 'stroke 0.3s ease-in-out',
- },
- }}
- zIndex={toolbarButtonZIndex}
- />
- );
-}
-
-export default InstallButton;
diff --git a/packages/client/src/components/install/Install.tsx b/packages/client/src/components/install/Install.tsx
new file mode 100644
index 0000000..4763df9
--- /dev/null
+++ b/packages/client/src/components/install/Install.tsx
@@ -0,0 +1,7 @@
+import React, { useEffect, useState } from 'react';
+
+function InstallButton() {
+ return ;
+}
+
+export default InstallButton;
diff --git a/packages/client/src/components/install/InstallButton.tsx b/packages/client/src/components/install/InstallButton.tsx
new file mode 100644
index 0000000..371b9a7
--- /dev/null
+++ b/packages/client/src/components/install/InstallButton.tsx
@@ -0,0 +1,61 @@
+import { IconButton } from '@chakra-ui/react';
+import { HardDriveDownload } from 'lucide-react';
+import React, { useEffect, useState } from 'react';
+
+import { toolbarButtonZIndex } from '../toolbar/Toolbar.tsx';
+
+function InstallButton() {
+ const [deferredPrompt, setDeferredPrompt] = useState(null);
+ const [isInstalled, setIsInstalled] = useState(false);
+
+ useEffect(() => {
+ const handleBeforeInstallPrompt = e => {
+ // Prevent the default prompt
+ e.preventDefault();
+ setDeferredPrompt(e);
+ };
+
+ window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
+
+ return () => {
+ window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
+ };
+ }, []);
+
+ const handleInstall = () => {
+ if (deferredPrompt) {
+ deferredPrompt.prompt();
+ deferredPrompt.userChoice.then(choiceResult => {
+ if (choiceResult.outcome === 'accepted') {
+ console.log('User accepted the installation prompt');
+ } else {
+ console.log('User dismissed the installation prompt');
+ }
+ });
+ setDeferredPrompt(null);
+ }
+ };
+
+ return (
+ }
+ size="md"
+ bg="transparent"
+ stroke="text.accent"
+ color="text.accent"
+ onClick={handleInstall}
+ _hover={{
+ bg: 'transparent',
+ svg: {
+ stroke: 'accent.secondary',
+ transition: 'stroke 0.3s ease-in-out',
+ },
+ }}
+ zIndex={toolbarButtonZIndex}
+ />
+ );
+}
+
+export default InstallButton;
diff --git a/packages/client/src/components/landing-component/BevyScene.tsx b/packages/client/src/components/landing-component/BevyScene.tsx
deleted file mode 100644
index 3e213e1..0000000
--- a/packages/client/src/components/landing-component/BevyScene.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import { Box, useBreakpointValue } from '@chakra-ui/react';
-import React, { memo, useEffect, useMemo } from 'react';
-
-export interface BevySceneProps {
- speed?: number;
- intensity?: number; // 0-1 when visible
- glow?: boolean;
- visible?: boolean; // NEW — defaults to true
-}
-
-const BevySceneInner: React.FC = ({
- speed = 1,
- intensity = 1,
- glow = false,
- visible,
-}) => {
- const maxWidth = useBreakpointValue({ base: 640, md: 720 }, { ssr: true });
-
- /* initialise once */
- useEffect(() => {
- let dispose: (() => void) | void;
- (async () => {
- const { default: init } = await import(/* webpackIgnore: true */ '/public/yachtpit.js');
- dispose = await init(); // zero-arg, uses #yachtpit-canvas
- })();
- return () => {
- if (typeof dispose === 'function') dispose();
- };
- }, []);
-
- /* memoised styles */
- const wrapperStyles = useMemo(
- () => ({
- position: 'absolute' as const,
- inset: 0,
- zIndex: 1,
- maxWidth: maxWidth,
- opacity: visible ? Math.min(Math.max(intensity, 0), 1) : 0,
- filter: glow ? 'blur(1px)' : 'none',
- transition: `opacity ${speed}s ease-in-out`,
- display: visible ? 'block' : 'none', // optional: reclaim hit-testing entirely
- }),
- [visible, intensity, glow, speed],
- );
-
- return (
-
-
-
- );
-};
-
-export const BevyScene = memo(BevySceneInner);
diff --git a/packages/client/src/components/toolbar/Toolbar.tsx b/packages/client/src/components/toolbar/Toolbar.tsx
index f9b8367..9d3bb8c 100644
--- a/packages/client/src/components/toolbar/Toolbar.tsx
+++ b/packages/client/src/components/toolbar/Toolbar.tsx
@@ -2,7 +2,7 @@ import { Flex } from '@chakra-ui/react';
import React from 'react';
import BuiltWithButton from '../BuiltWithButton';
-import InstallButton from '../InstallButton.tsx';
+import InstallButton from '../install/InstallButton.tsx';
import GithubButton from './GithubButton';
import SupportThisSiteButton from './SupportThisSiteButton';