Skip to content

feat(theme): sync light and dark mode across web apps - #261

Open
iDorgham wants to merge 1 commit into
masterfrom
cursor/sync-theme-across-apps-c803
Open

feat(theme): sync light and dark mode across web apps#261
iDorgham wants to merge 1 commit into
masterfrom
cursor/sync-theme-across-apps-c803

Conversation

@iDorgham

@iDorgham iDorgham commented Aug 16, 2026

Copy link
Copy Markdown
Owner

Summary

  • Share light/dark/system preference across GateFlow web apps (www, app, admin, portal, design) via a parent-domain gateflow-theme cookie on .gateflow.site.
  • Centralize this in @gateflow/theme: ThemeScript copies the cookie into localStorage before paint, and ThemeProvider writes the cookie plus re-reads it when another app tab is focused.
  • Resident Portal now has a theme toggle (sidebar + profile). Native scanner/resident-mobile apps stay local because they cannot share that cookie.

Type of change

  • feat — New feature

Plan reference

None — product request to keep color mode in sync across apps.

Checklist

Code

  • Follows conventional commit format (feat(scope): description)
  • No hardcoded secrets, API keys, or credentials
  • No console.log left in production code

Tests

  • New tests added for cookie domain, parse, serialize, and bootstrap script
  • @gateflow/theme typecheck + tests pass
  • Typecheck passes for client-dashboard and resident-portal (with turbo ^build)

Database

  • No schema changes

Env & Config

  • No new env vars

Release

  • CHANGELOG updated

Breaking changes

None. Existing theme localStorage/cookie values are migrated by the bootstrap script.

How it works

  1. Toggling theme in any web app updates next-themes and writes gateflow-theme (Path=/, SameSite=Lax, Domain=.gateflow.site in production, host-only on localhost so all local ports share it).
  2. Opening or focusing another app copies that cookie into localStorage (ThemeScript + visibility/focus sync) so next-themes applies the same mode.
  3. Both class="dark" and data-color-mode="dark" are set so Tailwind dark: utilities, @gateflow/tokens, and .dark CSS variables stay aligned.
Open in Web Open in Cursor 

Summary by cubic

Syncs light/dark mode across GateFlow web apps using a shared gateflow-theme cookie and @gateflow/theme. Previously each app stored theme locally; now apps on *.gateflow.site read/write the shared cookie and apply the same mode on load and focus, avoiding a flash of the wrong color.

Review and rollout

  • Required: render ThemeScript in <head> and wrap the root with ThemeProvider from @gateflow/theme in www, app, admin, portal, and design.
  • Required: remove manual cookie writes in theme toggles; call setTheme only.
  • Cookie behavior: Path=/, SameSite=Lax; Domain=.gateflow.site in production, host-only on localhost; Secure when https. Preview hosts and native/mobile clients remain local.
  • ThemeProvider sets both class and data-color-mode and re-syncs on focus/visibility; @gateflow/tokens and Tailwind dark: variants now respect .dark as well.
  • Resident Portal adds a theme toggle (sidebar and profile).
  • apps/marketing updates next-themes to ^0.4.6; @gateflow/theme now exports from src/index.ts and includes cookie/domain tests.

Written for commit 79b3e41. Summary will update on new commits.

Review in cubic

Share color mode through a parent-domain gateflow-theme cookie so
marketing, dashboards, portal, and design-system stay in sync on
*.gateflow.site (and across localhost ports).

Co-authored-by: Dorgham <iDorgham@users.noreply.github.com>
@iDorgham
iDorgham marked this pull request as ready for review August 16, 2026 22:48
@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@iDorgham, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 46 minutes

Limit details: You’ve used all 1 included review currently available under your plan.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e32f1688-e881-4506-83bf-372bae4ed96a

📥 Commits

Reviewing files that changed from the base of the PR and between e36ed2b and 79b3e41.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (33)
  • CHANGELOG.md
  • apps/admin-dashboard/next.config.js
  • apps/admin-dashboard/package.json
  • apps/admin-dashboard/src/app/[locale]/layout.tsx
  • apps/admin-dashboard/src/components/theme-toggle.tsx
  • apps/client-dashboard/next.config.js
  • apps/client-dashboard/package.json
  • apps/client-dashboard/src/app/[locale]/layout.tsx
  • apps/client-dashboard/src/components/theme-provider.tsx
  • apps/client-dashboard/src/components/theme-toggle.tsx
  • apps/design-system/src/app/layout.tsx
  • apps/marketing/app/[locale]/layout.tsx
  • apps/marketing/app/providers.tsx
  • apps/marketing/components/theme-toggle.tsx
  • apps/marketing/next.config.js
  • apps/marketing/package.json
  • apps/resident-portal/next.config.js
  • apps/resident-portal/package.json
  • apps/resident-portal/src/app/(portal)/profile/page.tsx
  • apps/resident-portal/src/app/layout.tsx
  • apps/resident-portal/src/components/layout/sidebar.tsx
  • apps/resident-portal/src/components/theme-toggle.tsx
  • packages/theme/README.md
  • packages/theme/package.json
  • packages/theme/src/ThemeProvider.tsx
  • packages/theme/src/ThemeScript.tsx
  • packages/theme/src/constants.ts
  • packages/theme/src/cookie.test.ts
  • packages/theme/src/cookie.ts
  • packages/theme/src/index.ts
  • packages/theme/tsconfig.json
  • packages/tokens/css/tokens.css
  • packages/ui/src/globals.css

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the size/XL Extra large change (>500 lines) label Aug 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📦 Affected Packages

  • @gate-access/ui (component library)
  • admin-dashboard (Next.js app)
  • client-dashboard (Next.js app)
  • marketing (Next.js site)

Diff: +472 / -127 lines

Auto-generated by pr-labels.yml

Comment on lines +117 to +119
export const THEME_BOOTSTRAP_SCRIPT = `(function(){try{var KEY=${JSON.stringify(
THEME_STORAGE_KEY
)};var LEGACY=${JSON.stringify(
Comment on lines +119 to +121
)};var LEGACY=${JSON.stringify(
LEGACY_THEME_STORAGE_KEY
)};var valid={light:1,dark:1,system:1};function readCookie(name){var m=document.cookie.match(new RegExp('(?:^|; )'+name+'=([^;]*)'));return m?decodeURIComponent(m[1]):null}function pick(){var value=readCookie(KEY)||readCookie(LEGACY);if(!value||!valid[value]){try{value=localStorage.getItem(KEY)||localStorage.getItem(LEGACY)}catch(e){value=null}}return value&&valid[value]?value:null}var value=pick();if(value){try{localStorage.setItem(KEY,value)}catch(e){}}}catch(e){}})();`;
@github-actions

Copy link
Copy Markdown
Contributor

Lighthouse CI — Marketing Site

Category 📱 Mobile 🖥 Desktop
Performance 🔴 54/100 🔴 69/100
Accessibility 🟡 91/100 🟡 91/100
Best Practices 🟢 100/100 🟢 100/100
SEO 🟢 100/100 🟢 100/100

Core Web Vitals (Mobile)
LCP: 5312ms | FCP: 1422ms | TBT: 1180ms | CLS: 0.000

Thresholds in .lighthouserc.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL Extra large change (>500 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants