import type { Metadata, Viewport } from "next"; import { IceBackdrop } from "@/components/IceBackdrop"; import { InstallSheet } from "@/components/InstallSheet"; import { ServiceWorkerRegistrar } from "@/components/ServiceWorkerRegistrar"; import "./globals.css"; export const metadata: Metadata = { title: { default: "Freezmo — turn your notes into a study feed", template: "%s · Freezmo", }, description: "Freezmo turns photos and documents of your notes into a swipeable feed of short interactive study activities, powered by your own Ollama models.", applicationName: "Freezmo", manifest: "/manifest.webmanifest", appleWebApp: { capable: true, title: "Freezmo", statusBarStyle: "default", }, icons: { icon: [ // ?v=2 busts browser favicon caches after the icon redesign. { url: "/icons/favicon-32.png?v=2", sizes: "32x32", type: "image/png" }, { url: "/icons/icon-192.png?v=2", sizes: "192x192", type: "image/png" }, { url: "/icons/icon-512.png?v=2", sizes: "512x512", type: "image/png" }, ], apple: [ { url: "/icons/apple-touch-icon.png?v=2", sizes: "180x180" }, { url: "/icons/apple-touch-icon-167.png?v=2", sizes: "167x167" }, { url: "/icons/apple-touch-icon-152.png?v=2", sizes: "152x152" }, ], }, other: { // iOS standalone niceties "apple-mobile-web-app-capable": "yes", "mobile-web-app-capable": "yes", "format-detection": "telephone=no", }, }; export const viewport: Viewport = { width: "device-width", initialScale: 1, // Phones: no pinch/double-tap zoom (the app-like feel). The input font-size // rule in globals.css is what actually stops iOS Safari's focus auto-zoom, // which ignores user-scalable=no. maximumScale: 1, userScalable: false, viewportFit: "cover", themeColor: [ { media: "(prefers-color-scheme: light)", color: "#f4f7fd" }, { media: "(prefers-color-scheme: dark)", color: "#0e1424" }, ], }; /** Applies the saved theme before paint to avoid a flash. */ const themeScript = `(function(){try{var s=localStorage.getItem('freezmo.theme');var d=s?s==='dark':window.matchMedia('(prefers-color-scheme: dark)').matches;if(d)document.documentElement.classList.add('dark');}catch(e){}})();`; /** * Captures Chrome's `beforeinstallprompt` (it can fire before React hydrates) * and records an install so the prompt never comes back. Static, no user data. */ const installScript = `(function(){try{ window.addEventListener('beforeinstallprompt',function(e){e.preventDefault();window.__freezmoInstallPrompt=e;window.dispatchEvent(new Event('freezmo:installprompt'));}); window.addEventListener('appinstalled',function(){try{localStorage.setItem('freezmo.install.installed','1')}catch(e){}window.dispatchEvent(new Event('freezmo:installed'));}); }catch(e){}})();`; export default function RootLayout({ children }: { children: React.ReactNode }) { return (