fix(web): Add scheme-aware theme-color for dark mode - #3051
Conversation
The web app declares no `theme-color` at all, and the manifest carries a single light `theme_color: "#ffffff"`. Browser and installed-web-app chrome is painted from that value, so on macOS (Safari > Add to Dock) the title bar stays white while the UI is in dark mode. Adds `themeColor` to the existing `viewport` export with light and dark variants, so the chrome follows the active scheme. This mirrors the `prefers-color-scheme` pattern already used for the icons in `metadata`. The dark value is `#020817`, the hex form of the `--background` token defined for `.dark` in `tooling/tailwind/globals.css` (`222.2 84% 4.9%`), so the title bar matches the app background exactly. The manifest is left alone, as `theme_color` there accepts only a single value.
Greptile SummaryThe PR adds light and dark browser theme colors to the root Next.js viewport metadata using
Confidence Score: 4/5The theme-color synchronization issue should be fixed before merging because explicit app-theme overrides can still produce mismatched browser chrome. The metadata shape is valid for the installed Next.js version, but its media queries follow only the OS preference while the existing user-facing theme toggle can independently select the opposite page theme. Files Needing Attention: apps/web/app/layout.tsx Important Files Changed
Prompt To Fix All With AI### Issue 1
apps/web/app/layout.tsx:60-62
**Theme override leaves chrome mismatched**
When a user selects an app theme opposite to the operating-system preference, these static `prefers-color-scheme` entries retain the OS color while `next-themes` applies the selected theme to the page, causing light browser chrome over dark UI or dark chrome over light UI.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "fix(web): Add scheme-aware theme-color f..." | Re-trigger Greptile |
There was a problem hiding this comment.
🟢 Approval recommended
The change is low-risk static metadata; the only feedback is a minor comment clarification.
Pull request overview
Adds scheme-aware theme-color metadata to the Next.js app router viewport export so browser / installed PWA chrome can match light vs dark mode.
Changes:
- Add
viewport.themeColorentries for(prefers-color-scheme: light)and(prefers-color-scheme: dark). - Document intent to align the
theme-colorvalues with the Tailwind--backgroundtoken.
File summaries
| File | Description |
|---|---|
| apps/web/app/layout.tsx | Adds scheme-aware themeColor values to the exported viewport metadata. |
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Fixes #3029
What
The web app declares no
theme-colorat all —grepfinds nothemeColorortheme-coloranywhere — andapps/web/app/manifest.tscarries a single light value:Browser and installed-web-app chrome is painted from that, so on macOS (Safari → Add to Dock) the title bar stays white while the UI is in dark mode.
This adds
themeColorto the existingviewportexport inapps/web/app/layout.tsxwith light and dark variants, so the chrome follows the active scheme. It mirrors theprefers-color-schemepattern already used for the icons inmetadatajust above it.On the dark value
The issue suggested
#0f172a. I used#020817instead, which is the hex form of this project's own--backgroundtoken for.darkintooling/tailwind/globals.css:hsl(222.2 84% 4.9%)converts to#020817, so the title bar matches the actual app background exactly rather than approximating it withslate-900. The light value#ffffffis likewise the:root--background(0 0% 100%).Scope
manifest.tsis left unchanged — the manifest'stheme_coloraccepts only a single value, so the scheme-aware<meta>tags are the right mechanism here.Viewport.themeColoraccepts an array of{ media, color }descriptors, which is what generates the two tags.Verification
Ran against this branch (
c17504f) on a clean checkout, Node 22.23.2 / pnpm 11.2.1:pnpm install --frozen-lockfilepnpm --filter @karakeep/web typechecktsc --noEmit, exit 0pnpm --filter @karakeep/web lintTo be precise about the limits: this confirms the change compiles and conforms to the repo's style. It does not confirm the chrome renders as intended — that check is manual, on a real macOS installed web app, which is the scenario #3029 reports and which I have not been able to run. A maintainer sanity-check there would be worthwhile.