diff --git a/app/apple-icon.png b/app/apple-icon.png
new file mode 100644
index 00000000..d1216935
Binary files /dev/null and b/app/apple-icon.png differ
diff --git a/app/layout.tsx b/app/layout.tsx
index a092d4fe..0bcfe2b3 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -16,6 +16,7 @@ import { CalendarToggleProvider } from '@/components/calendar-toggle-context'
import { MapLoadingProvider } from '@/components/map-loading-context';
import ConditionalLottie from '@/components/conditional-lottie';
import { MapProvider as MapContextProvider } from '@/components/map/map-context'
+import { IOSInstallPrompt } from '@/components/pwa/ios-install-prompt'
const fontSans = FontSans({
subsets: ['latin'],
@@ -28,14 +29,22 @@ const fontPoppins = Poppins({
weight: ['400', '500', '600', '700']
})
-const title = ''
+const title = 'QCX - AI-powered Search'
const description =
- 'language to Maps'
+ 'A minimalistic AI-powered search tool that uses advanced models for deep analysis and geospatial data.'
export const metadata: Metadata = {
metadataBase: new URL('https://www.qcx.world'),
title,
description,
+ appleWebApp: {
+ capable: true,
+ statusBarStyle: 'default',
+ title: 'QCX',
+ },
+ formatDetection: {
+ telephone: false,
+ },
openGraph: {
title,
description
@@ -52,7 +61,8 @@ export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
minimumScale: 1,
- maximumScale: 1
+ maximumScale: 1,
+ themeColor: '#171717'
}
export default function RootLayout({
@@ -84,6 +94,7 @@ export default function RootLayout({
{children}
+
diff --git a/app/manifest.ts b/app/manifest.ts
new file mode 100644
index 00000000..b1e5e5b0
--- /dev/null
+++ b/app/manifest.ts
@@ -0,0 +1,42 @@
+import { MetadataRoute } from 'next'
+
+export default function manifest(): MetadataRoute.Manifest {
+ return {
+ name: 'QCX - AI-powered Search & Analysis',
+ short_name: 'QCX',
+ description: 'A minimalistic AI-powered search tool that uses advanced models for deep analysis and geospatial data.',
+ start_url: '/',
+ display: 'standalone',
+ background_color: '#171717',
+ theme_color: '#171717',
+ icons: [
+ {
+ src: '/icon-192.png',
+ sizes: '192x192',
+ type: 'image/png',
+ purpose: 'any',
+ },
+ {
+ src: '/icon-512.png',
+ sizes: '512x512',
+ type: 'image/png',
+ purpose: 'any',
+ },
+ {
+ src: '/icon-1024-maskable.png',
+ sizes: '1024x1024',
+ type: 'image/png',
+ purpose: 'maskable',
+ },
+ ],
+ screenshots: [
+ {
+ src: '/images/opengraph-image.png',
+ sizes: '1200x630',
+ type: 'image/png',
+ label: 'QCX Home Screen',
+ },
+ ],
+ categories: ['search', 'ai', 'productivity'],
+ }
+}
diff --git a/components/pwa/ios-install-prompt.tsx b/components/pwa/ios-install-prompt.tsx
new file mode 100644
index 00000000..fd66173a
--- /dev/null
+++ b/components/pwa/ios-install-prompt.tsx
@@ -0,0 +1,56 @@
+'use client'
+
+import { useEffect, useState } from 'react'
+import { X, Share } from 'lucide-react'
+import { Button } from '@/components/ui/button'
+
+export function IOSInstallPrompt() {
+ const [showPrompt, setShowPrompt] = useState(false)
+
+ useEffect(() => {
+ // Check if it's iOS
+ const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !(window as any).MSStream
+
+ // Check if it's already in standalone mode (installed)
+ const isStandalone = window.matchMedia('(display-mode: standalone)').matches ||
+ (window.navigator as any).standalone
+
+ // Check if the prompt was already dismissed this session
+ const isDismissed = sessionStorage.getItem('ios-pwa-prompt-dismissed')
+
+ if (isIOS && !isStandalone && !isDismissed) {
+ setShowPrompt(true)
+ }
+ }, [])
+
+ const handleDismiss = () => {
+ setShowPrompt(false)
+ sessionStorage.setItem('ios-pwa-prompt-dismissed', 'true')
+ }
+
+ if (!showPrompt) return null
+
+ return (
+
+
+
+
+
+
+
+
+
Install QCX
+
+ Tap Share then Add to Home Screen to install as an app.
+
+
+
+
+
+ )
+}
diff --git a/public/icon-1024-maskable.png b/public/icon-1024-maskable.png
new file mode 100644
index 00000000..d1216935
Binary files /dev/null and b/public/icon-1024-maskable.png differ
diff --git a/public/icon-192.png b/public/icon-192.png
new file mode 100644
index 00000000..d1216935
Binary files /dev/null and b/public/icon-192.png differ
diff --git a/public/icon-512.png b/public/icon-512.png
new file mode 100644
index 00000000..d1216935
Binary files /dev/null and b/public/icon-512.png differ