Skip to content

fix(whitelabeling): eliminate logo flash by fetching org settings server-side#4057

Merged
waleedlatif1 merged 8 commits intostagingfrom
feat/enterprise-whitelabeling
Apr 8, 2026
Merged

fix(whitelabeling): eliminate logo flash by fetching org settings server-side#4057
waleedlatif1 merged 8 commits intostagingfrom
feat/enterprise-whitelabeling

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

Summary

  • Fix logo flash on hard refresh: workspace layout now fetches org whitelabel settings directly from the DB server-side so the correct org logo is baked into the initial HTML
  • Simplify BrandingProvider: drop the cookie-based cache mechanism entirely — effectiveOrgSettings falls back to the server-fetched initialOrgSettings while React Query is in flight, then switches to live data once resolved
  • Fix missing 'whitelabeling' entry in SECTION_TITLES so the page title renders correctly

Type of Change

  • Bug fix

Testing

Tested manually — hard refresh no longer flashes the Sim default logo before showing org branding

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 8, 2026

PR Summary

Medium Risk
Medium risk because it changes the workspace layout/branding initialization path (server-side session + DB fetch) and removes the prior cookie cache, which could affect initial render branding and hydration behavior across workspaces.

Overview
Prevents whitelabel logo/theme flashing on hard refresh by fetching org whitelabel settings server-side in workspace/[workspaceId]/layout.tsx (via session org id) and passing them into BrandingProvider as the initial source of truth.

Simplifies BrandingProvider by removing the cookie-based branding cache entirely and computing config/theme from effectiveOrgSettings (server-fetched settings until React Query resolves). Also drops the unused merged-config helper in org-branding.ts.

Polishes related UI: adds missing whitelabeling settings title, disables SSR for WhitelabelingSettings, improves tooltip video previews (preload + loading placeholder), shows skeletons for workspace color badges while data loads, enables SVG uploads for branding/profile images, and tweaks an auto-connect tooltip preview to loop.

Reviewed by Cursor Bugbot for commit 0209873. Configure here.

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Apr 8, 2026 8:56pm

Request Review

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

Also added SVG support for logo/wordmark uploads in this commit — server already accepted it, just needed the client validation and accept attributes updated.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 8, 2026

Greptile Summary

This PR eliminates the logo flash on hard refresh by fetching org whitelabel settings server-side in the workspace layout and passing them as initialOrgSettings to BrandingProvider. The provider uses these as a synchronous fallback until React Query resolves, so the correct branding is baked into the initial HTML. It also fixes the missing 'whitelabeling' entry in SECTION_TITLES and bundles SVG support for logo/wordmark uploads.

Confidence Score: 5/5

Safe to merge — the server-side fetch correctly eliminates the logo flash, the undefined vs null distinction in the fallback logic is sound, and there are no runtime errors or data-integrity concerns.

All changes are P2 or lower. The core fix is architecturally clean: initialOrgSettings is fetched once at SSR time and used synchronously on hydration so the React Query transition never shows the default logo. Error handling in getOrgWhitelabelSettings ensures the layout never throws even on DB failure.

No files require special attention.

Vulnerabilities

No security concerns identified. The server-side DB fetch is gated behind a session check (orgId comes from the authenticated session). The new SVG upload support is scoped to org-admin level whitelabeling (trusted users), and SVG blob preview URLs don't execute scripts. The org-branding.ts DB query uses parameterized Drizzle ORM calls with eq() — no SQL injection risk.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/layout.tsx Core fix: adds a server-side DB query for org whitelabel settings and passes initialOrgSettings to BrandingProvider; sequential with getSession() (unavoidable since orgId comes from the session), gracefully returns null on failure.
apps/sim/ee/whitelabeling/components/branding-provider.tsx Simplified: drops cookie cache, uses orgSettings !== undefined ? orgSettings : (initialOrgSettings ?? null) to serve server-fetched settings until React Query resolves; correctly distinguishes "loading" (undefined) from "no settings" (null).
apps/sim/ee/whitelabeling/org-branding.ts New server-only module exposing getOrgWhitelabelSettings; uses Drizzle ORM with eq(), has error handling that returns null on failure so layout never throws.
apps/sim/ee/whitelabeling/org-branding-utils.ts Clean utility module for mergeOrgBrandConfig and CSS variable generation; isDarkBackground luminance math is correct; no issues.
apps/sim/app/workspace/[workspaceId]/settings/[section]/page.tsx Adds the missing whitelabeling: 'Whitelabeling' entry to SECTION_TITLES, fixing the broken page title for this settings section.
apps/sim/app/workspace/[workspaceId]/settings/hooks/use-profile-picture-upload.ts Adds image/svg+xml to accepted types; blob preview URLs don't execute SVG scripts; file is properly cleaned up on unmount.
apps/sim/ee/whitelabeling/components/whitelabeling-settings.tsx Settings UI for org branding; uses useProfilePictureUpload for logo/wordmark uploads with proper drag-and-drop and preview; no issues found.
apps/sim/components/emcn/components/tooltip/tooltip.tsx Adds Preview sub-component for video/image tooltips with a shimmer placeholder while video loads; clean implementation.
apps/sim/lib/uploads/utils/file-utils.ts Adds image/svg+xml to MIME_TYPE_MAPPING with a comment explaining it's handled specially for Claude API; createFileContent correctly converts SVG to XML document type.
apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/workspace-header.tsx Updates workspace color fallback to var(--brand-accent) so it respects org-level color theming; no issues.
apps/sim/app/workspace/[workspaceId]/settings/[section]/settings.tsx Adds ssr: false to the WhitelabelingSettings dynamic import, appropriate since it's a client-only interactive settings panel.
apps/sim/app/workspace/[workspaceId]/settings/components/general/general.tsx Integrates new Tooltip.Preview component for the auto-connect and error-notification tooltips; no logic changes.

Sequence Diagram

sequenceDiagram
    participant Browser
    participant NextServer as Next.js Server
    participant DB as Database
    participant ReactQuery as React Query (client)

    Browser->>NextServer: Hard refresh /workspace/[id]
    NextServer->>NextServer: getSession()
    NextServer->>DB: getOrgWhitelabelSettings(orgId)
    DB-->>NextServer: OrganizationWhitelabelSettings | null
    NextServer-->>Browser: HTML with initialOrgSettings baked in

    Note over Browser: BrandingProvider hydrates
    Note over Browser: effectiveOrgSettings = initialOrgSettings
    Note over Browser: (orgSettings still undefined)

    Browser->>ReactQuery: useWhitelabelSettings(orgId) fires
    ReactQuery-->>Browser: OrganizationWhitelabelSettings
    Note over Browser: effectiveOrgSettings = orgSettings (live data)
Loading

Reviews (4): Last reviewed commit: "chore(whitelabeling): inline hasOrgBrand" | Re-trigger Greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

Both issues addressed:

P1 — Blob preview dep cycle (Greptile): Fixed in a3c959e. Removed previewUrl from the useEffect deps entirely — the effect's only job is to sync when the external currentImage prop changes, so [currentImage] is the correct dep array. Also dropped the now-unnecessary currentImage !== previewUrl guard since we no longer read previewUrl inside the effect, eliminating the circular trigger.

Missing color fallback (Cursor): Fixed in c70c8ef — using activeWorkspaceFull.color ?? 'var(--brand-accent)' on all three avatar instances. Skeleton still shows while activeWorkspaceFull is null (loading); the fallback only applies when the workspace object exists but has no color set.

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 0209873. Configure here.

@waleedlatif1 waleedlatif1 merged commit 91ce55e into staging Apr 8, 2026
11 of 12 checks passed
@waleedlatif1 waleedlatif1 deleted the feat/enterprise-whitelabeling branch April 8, 2026 21:07
@waleedlatif1 waleedlatif1 restored the feat/enterprise-whitelabeling branch April 8, 2026 22:54
TheodoreSpeaks pushed a commit that referenced this pull request Apr 8, 2026
…ver-side (#4057)

* fix(whitelabeling): eliminate logo flash by fetching org settings server-side

* improvement(whitelabeling): add SVG support for logo and wordmark uploads

* skelly in workspace header

* remove dead code

* fix(whitelabeling): hydration error, SVG support, skeleton shimmer, dead code removal

* fix(whitelabeling): blob preview dep cycle and missing color fallback

* fix(whitelabeling): use brand-accent as color fallback when workspace color is undefined

* chore(whitelabeling): inline hasOrgBrand
TheodoreSpeaks added a commit that referenced this pull request Apr 8, 2026
* fix(billing): skip billing on streamed workflows with byok

* Simplify logic

* Address comments, skip tokenization billing fallback

* Fix tool usage billing for streamed outputs

* fix(webhook): throw webhook errors as 4xxs (#4050)

* fix(webhook): throw webhook errors as 4xxs

* Fix shadowing body var

---------

Co-authored-by: Theodore Li <theo@sim.ai>

* feat(enterprise): cloud whitelabeling for enterprise orgs (#4047)

* feat(enterprise): cloud whitelabeling for enterprise orgs

* fix(enterprise): scope enterprise plan check to target org in whitelabel PUT

* fix(enterprise): use isOrganizationOnEnterprisePlan for org-scoped enterprise check

* fix(enterprise): allow clearing whitelabel fields and guard against empty update result

* fix(enterprise): remove webp from logo accept attribute to match upload hook validation

* improvement(billing): use isBillingEnabled instead of isProd for plan gate bypasses

* fix(enterprise): show whitelabeling nav item when billing is enabled on non-hosted environments

* fix(enterprise): accept relative paths for logoUrl since upload API returns /api/files/serve/ paths

* fix(whitelabeling): prevent logo flash on refresh by hiding logo while branding loads

* fix(whitelabeling): wire hover color through CSS token on tertiary buttons

* fix(whitelabeling): show sim logo by default, only replace when org logo loads

* fix(whitelabeling): cache org logo url in localstorage to eliminate flash on repeat visits

* feat(whitelabeling): add wordmark support with drag/drop upload

* updated turbo

* fix(whitelabeling): defer localstorage read to effect to prevent hydration mismatch

* fix(whitelabeling): use layout effect for cache read to eliminate logo flash before paint

* fix(whitelabeling): cache theme css to eliminate color flash before org settings resolve

* fix(whitelabeling): deduplicate HEX_COLOR_REGEX into lib/branding and remove mutation from useCallback deps

* fix(whitelabeling): use cookie-based SSR cache to eliminate brand flash on all page loads

* fix(whitelabeling): use !orgSettings condition to fix SSR brand cache injection

React Query returns isLoading: false with data: undefined during SSR, so the
previous brandingLoading condition was always false on the server — initialCache
was never injected into brandConfig. Changing to !orgSettings correctly applies
the cookie cache both during SSR and while the client-side query loads, eliminating
the logo flash on hard refresh.

* fix(editor): stop highlighting start.input as blue when block is not connected to starter (#4054)

* fix: merge subblock values in auto-layout to prevent losing router context (#4055)

Auto-layout was reading from getWorkflowState() without merging subblock
store values, then persisting stale subblock data to the database. This
caused runtime-edited values (e.g. router_v2 context) to be overwritten
with their initial/empty values whenever auto-layout was triggered.

* fix(whitelabeling): eliminate logo flash by fetching org settings server-side (#4057)

* fix(whitelabeling): eliminate logo flash by fetching org settings server-side

* improvement(whitelabeling): add SVG support for logo and wordmark uploads

* skelly in workspace header

* remove dead code

* fix(whitelabeling): hydration error, SVG support, skeleton shimmer, dead code removal

* fix(whitelabeling): blob preview dep cycle and missing color fallback

* fix(whitelabeling): use brand-accent as color fallback when workspace color is undefined

* chore(whitelabeling): inline hasOrgBrand

---------

Co-authored-by: Theodore Li <theo@sim.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant