From f609b10ab3e871cfc7c5fd99d7936d8ea2b7f58d Mon Sep 17 00:00:00 2001
From: ankitsejwal
Date: Mon, 29 Jun 2026 01:42:03 +0530
Subject: [PATCH 1/2] Add theme store and no-flash boot script
---
apps/web/index.html | 8 ++++++++
apps/web/src/stores/theme-store.ts | 30 ++++++++++++++++++++++++++++++
apps/web/src/styles.css | 2 ++
3 files changed, 40 insertions(+)
create mode 100644 apps/web/src/stores/theme-store.ts
diff --git a/apps/web/index.html b/apps/web/index.html
index 4cbc928..83f0ea6 100644
--- a/apps/web/index.html
+++ b/apps/web/index.html
@@ -7,6 +7,14 @@
Polaroid — print-at-home photo frames
+
diff --git a/apps/web/src/stores/theme-store.ts b/apps/web/src/stores/theme-store.ts
new file mode 100644
index 0000000..1d603d9
--- /dev/null
+++ b/apps/web/src/stores/theme-store.ts
@@ -0,0 +1,30 @@
+import { create } from 'zustand'
+
+export type Theme = 'light' | 'dark'
+
+// The initial class is set by an inline script in index.html (before paint),
+// so we just read it back here to seed the store.
+function currentTheme(): Theme {
+ if (typeof document === 'undefined') return 'light'
+ return document.documentElement.classList.contains('dark') ? 'dark' : 'light'
+}
+
+interface ThemeState {
+ theme: Theme
+ setTheme: (theme: Theme) => void
+ toggle: () => void
+}
+
+export const useThemeStore = create((set, get) => ({
+ theme: currentTheme(),
+ setTheme: (theme) => {
+ document.documentElement.classList.toggle('dark', theme === 'dark')
+ try {
+ localStorage.setItem('theme', theme)
+ } catch {
+ // Private mode / storage disabled — the choice just won't persist.
+ }
+ set({ theme })
+ },
+ toggle: () => get().setTheme(get().theme === 'dark' ? 'light' : 'dark'),
+}))
diff --git a/apps/web/src/styles.css b/apps/web/src/styles.css
index d840f32..9a66256 100644
--- a/apps/web/src/styles.css
+++ b/apps/web/src/styles.css
@@ -4,6 +4,7 @@
@custom-variant dark (&:is(.dark *));
:root {
+ color-scheme: light;
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
@@ -24,6 +25,7 @@
}
.dark {
+ color-scheme: dark;
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.205 0 0);
From 65663373db5051138dcff55bd58f423ded8edd01 Mon Sep 17 00:00:00 2001
From: ankitsejwal
Date: Mon, 29 Jun 2026 01:42:03 +0530
Subject: [PATCH 2/2] Add header light/dark toggle
---
apps/web/src/components/theme-toggle.tsx | 32 ++++++++++++++++++++++++
apps/web/src/routes/index.tsx | 6 ++++-
2 files changed, 37 insertions(+), 1 deletion(-)
create mode 100644 apps/web/src/components/theme-toggle.tsx
diff --git a/apps/web/src/components/theme-toggle.tsx b/apps/web/src/components/theme-toggle.tsx
new file mode 100644
index 0000000..d19ed59
--- /dev/null
+++ b/apps/web/src/components/theme-toggle.tsx
@@ -0,0 +1,32 @@
+import { Moon, Sun } from 'lucide-react'
+
+import { Button } from '@/components/ui/button'
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from '@/components/ui/tooltip'
+import { useThemeStore } from '@/stores/theme-store'
+
+export function ThemeToggle() {
+ const theme = useThemeStore((state) => state.theme)
+ const toggle = useThemeStore((state) => state.toggle)
+ const dark = theme === 'dark'
+
+ return (
+
+
+
+
+ {dark ? 'Light mode' : 'Dark mode'}
+
+ )
+}
diff --git a/apps/web/src/routes/index.tsx b/apps/web/src/routes/index.tsx
index b4b71a9..55ce00f 100644
--- a/apps/web/src/routes/index.tsx
+++ b/apps/web/src/routes/index.tsx
@@ -4,6 +4,7 @@ import { A4Preview } from '@/components/a4-preview'
import { OptionsPanel } from '@/components/options-panel'
import { PhotoSidebar } from '@/components/photo-sidebar'
import { ProjectControls } from '@/components/project-controls'
+import { ThemeToggle } from '@/components/theme-toggle'
export const Route = createFileRoute('/')({
component: Home,
@@ -19,7 +20,10 @@ function Home() {
Edit each frame on the page — everything stays on your device.
-
+