Skip to content

improvement(ui): align all public pages with dark landing theme and improve whitelabeling#3604

Open
waleedlatif1 wants to merge 17 commits intostagingfrom
fix/sidebar-loading
Open

improvement(ui): align all public pages with dark landing theme and improve whitelabeling#3604
waleedlatif1 wants to merge 17 commits intostagingfrom
fix/sidebar-loading

Conversation

@waleedlatif1
Copy link
Collaborator

Summary

  • Migrated all public-facing pages (auth, privacy, terms, changelog, blog, 404, invite, form, resume, unsubscribe) to dark theme matching the new landing page
  • Replaced Soehne/Inter fonts with Season font across all pages
  • Replaced old Nav/Footer components with new landing Navbar/Footer
  • Added whitelabel support to Navbar (brand logo), BrandedButton (brand primary color), sidebar icon, Run/Deploy buttons (CSS variable override), and email templates (hide socials/address for whitelabeled instances)
  • Migrated auth pages to use emcn components (Input, Label, Modal, InputOTP, Button)
  • Removed unused shadcn components (Alert, Dialog, InputOTP)
  • Auth background now uses landing page card SVG outlines instead of old wire pattern

Type of Change

  • Enhancement / Improvement

Testing

Tested manually

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)

@vercel
Copy link

vercel bot commented Mar 15, 2026

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Mar 16, 2026 7:35am

Request Review

@cursor
Copy link

cursor bot commented Mar 15, 2026

PR Summary

Medium Risk
Wide-ranging UI refactor across auth/public pages (layouts, components, CSS) with some whitelabel-dependent styling; risk is mainly visual regressions and inconsistent theming/scroll behavior rather than data/security issues.

Overview
Unifies public/auth UI with the new dark landing theme. Auth layouts now force dark mode, swap Nav for the new Navbar (often logoOnly), and restyle copy/links/forms across login/signup/verify/reset/status/404/invite/unsubscribe/form/resume/studio/changelog/legal pages.

Refactors shared auth UI primitives. AuthBackground becomes a fixed, scrollable dark container and replaces the old wireframe SVG with new “card outline” artwork; BrandedButton is rewritten as a native button with whitelabel-driven inline colors; multiple screens migrate from shadcn components to emcn (Input, Label, Modal, InputOTP, Button) and remove related auth CSS helpers.

Improves branding/SEO and a few UI interactions. Navbar now pulls getBrandConfig() to display a whitelabel logo/name and supports logoOnly; landing structured data adds speakable and home metadata adds x-default; studio share UI switches to DropdownMenu; deploy/chat error rendering and settings sidebar loading skeletons are tweaked for better UX.

Written by Cursor Bugbot for commit 3cb33e5. Configure here.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 15, 2026

Greptile Summary

This PR aligns all public-facing pages (auth, 404, invite, form, resume, changelog, blog, legal) to the dark landing theme by replacing old Nav/Footer components with the new shared Navbar/Footer, swapping fonts to Season, and migrating auth forms to emcn components (Input, Label, Modal, InputOTP). It also introduces whitelabeling support across BrandedButton, the sidebar icon, Run/Deploy button CSS variables, and email templates.

Key changes and findings:

  • email-footer.tsx: Whitelabeling support added to hide socials/address rows, but Privacy Policy and Terms of Service links still use hardcoded ${baseUrl}/privacy and ${baseUrl}/terms, ignoring brand.privacyUrl and brand.termsUrl already present on BrandConfig. Whitelabeled operators who set NEXT_PUBLIC_PRIVACY_URL / NEXT_PUBLIC_TERMS_URL will receive incorrect URLs in all outgoing emails.
  • invite/components/layout.tsx: The <header> is missing the shrink-0 class present on all equivalent layouts updated in this PR (auth-layout-client.tsx, status-page-layout.tsx, and the fixed email-auth.tsx/sso-auth.tsx headers).
  • signup-form.tsx: SSO/email/social visibility logic is re-computed in three separate IIFEs inside JSX, inconsistent with login-form.tsx (updated in this same PR) which correctly declares these as named variables at the top of the component.
  • The isWhitelabeled flag, BrandedButton fallback fix, 'use client' removal from not-found.tsx (now correctly re-added due to useRouter), and the --brand-tertiary-2 comment were all addressed in prior rounds of review.

Confidence Score: 4/5

  • Safe to merge after fixing the email footer Privacy/Terms URL bug for whitelabeled instances.
  • The bulk of the changes are presentational and well-executed. The whitelabeling infrastructure (isWhitelabeled, hasCustomColor, inject-theme comments) is solid. One logic bug exists: email footers use hardcoded /privacy and /terms paths instead of brand.privacyUrl/brand.termsUrl, silently sending wrong URLs to users of whitelabeled deployments. The remaining findings are style/consistency issues that don't block functionality.
  • apps/sim/components/emails/components/email-footer.tsx — Privacy/Terms links ignore brand config URLs

Important Files Changed

Filename Overview
apps/sim/components/emails/components/email-footer.tsx Adds whitelabeling support (hides socials/address for white-labeled instances) but incorrectly hardcodes Privacy Policy and Terms of Service URLs, ignoring brand.privacyUrl and brand.termsUrl from BrandConfig.
apps/sim/app/(auth)/components/branded-button.tsx Properly migrated to use isWhitelabeled flag with hasCustomColor guard; fallback to white style when no primary color is set.
apps/sim/ee/whitelabeling/branding.ts Added isWhitelabeled flag computed from presence of any brand env var; clean implementation replacing the fragile name-comparison approach.
apps/sim/app/(auth)/signup/signup-form.tsx Successfully migrated to emcn Input/Label and dark theme, but SSO/email/social visibility logic is duplicated in three IIFEs in JSX rather than being extracted to named variables as in login-form.tsx.
apps/sim/app/invite/components/layout.tsx Migrated to dark landing theme; <header> is missing shrink-0 (present on all equivalent layouts updated in this PR).
apps/sim/app/(auth)/auth-layout-client.tsx Cleanly replaces old Nav with Navbar, adds dark class to <html> via effect with proper cleanup, correct shrink-0 bg-[#1C1C1C] header.
apps/sim/app/not-found.tsx Now uses BrandedButton for the "Return to Home" action and matches the dark landing theme; correctly requires 'use client' due to useRouter.
apps/sim/app/(home)/components/navbar/navbar.tsx New shared Navbar used across auth, landing, 404, and invite pages; supports logoOnly prop and brand logo override via BrandConfig.
apps/sim/components/emails/_styles/base.ts Brand-aware color tokens now use isWhitelabeled for primary/accent color overrides; module-level evaluation is safe for compile-time NEXT_PUBLIC_* env vars.
apps/sim/components/emcn/components/input-otp/input-otp.tsx New InputOTP component added to emcn library; correctly uses emcn design tokens and is exported from the index.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Public Page Request] --> B{Page Type}
    B --> |Auth pages| C[auth-layout-client.tsx]
    B --> |404| D[not-found.tsx]
    B --> |Invite| E[invite/layout.tsx]
    B --> |Status pages| F[status-page-layout.tsx]
    B --> |Landing/Legal/Blog| G[Landing layouts]

    C --> H[AuthBackground + Navbar logoOnly]
    D --> H
    E --> I[Plain div + Navbar logoOnly]
    F --> H

    H --> J[getBrandConfig]
    I --> J

    J --> K{isWhitelabeled?}
    K --> |Yes + primaryColor| L[BrandedButton uses brand color]
    K --> |No| M[BrandedButton uses white default]
    K --> |Yes, no primaryColor| M

    J --> N[Navbar]
    N --> O{brand.logoUrl?}
    O --> |Yes| P[Custom logo image]
    O --> |No| Q[Default sim-landing.svg]

    J --> R[Email Templates]
    R --> S{isWhitelabeled?}
    S --> |Yes| T[Hide socials + address rows]
    S --> |No| U[Show all footer rows]
    R --> V[Privacy/Terms links - always baseUrl/privacy + baseUrl/terms]
Loading

Comments Outside Diff (2)

  1. apps/sim/components/emails/components/email-footer.tsx, line 193-201 (link)

    Whitelabel privacyUrl/termsUrl ignored in email footer

    This PR adds whitelabeling to the email footer (hiding socials/address for whitelabeled instances) but the Privacy Policy and Terms of Service links still use hardcoded ${baseUrl}/privacy and ${baseUrl}/terms. The BrandConfig already carries brand.privacyUrl and brand.termsUrl (populated from NEXT_PUBLIC_PRIVACY_URL / NEXT_PUBLIC_TERMS_URL), so whitelabeled operators who point to their own legal pages will still receive the wrong URLs in all outgoing emails.

  2. apps/sim/app/(auth)/signup/signup-form.tsx, line 349-363 (link)

    Repeated IIFE auth-method logic — inconsistent with login-form.tsx

    The SSO/email/social visibility logic is computed in three separate IIFEs inside JSX (here on lines 349–363, again on lines 481–498, and again on lines 500–528), each re-evaluating the same ssoEnabled/emailEnabled/hasOnlySSO/showBottomSection/showDivider variables. The companion login-form.tsx (updated in this same PR) correctly derives these as named variables once at the top of the component (lines 375–381), which is easier to read and avoids the repeated calls to getEnv.

    Extract these to named variables at the top of SignupFormContent to match the login-form.tsx pattern:

    const ssoEnabled = isTruthy(getEnv('NEXT_PUBLIC_SSO_ENABLED'))
    const emailEnabled = !isFalsy(getEnv('NEXT_PUBLIC_EMAIL_PASSWORD_SIGNUP_ENABLED'))
    const hasSocial = githubAvailable || googleAvailable
    const hasOnlySSO = ssoEnabled && !emailEnabled && !hasSocial
    const showBottomSection = hasSocial || (ssoEnabled && !hasOnlySSO)
    const showDivider = (emailEnabled || hasOnlySSO) && showBottomSection

    Then replace all three IIFEs with direct references to these variables.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Last reviewed commit: 3cb33e5

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

Copy link

@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.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: OTP inputs render white on dark background
    • Removed light-theme styles (bg-white, border-gray-300, focus:ring-gray-100) from OTP inputs and email Input, keeping only error states for proper dark theme display.
  • ✅ Fixed: Chat password input keeps light-theme focus styling
    • Updated Label import to @/components/emcn and removed light-theme focus styles (focus:ring-gray-100, focus:border-gray-400, shadow-sm) from password Input, consistent with other migrated auth pages.

Create PR

Or push these changes by commenting:

@cursor push ba5d1575b3
Preview (ba5d1575b3)
diff --git a/apps/sim/app/chat/components/auth/email/email-auth.tsx b/apps/sim/app/chat/components/auth/email/email-auth.tsx
--- a/apps/sim/app/chat/components/auth/email/email-auth.tsx
+++ b/apps/sim/app/chat/components/auth/email/email-auth.tsx
@@ -225,10 +225,9 @@
                         onChange={handleEmailChange}
                         onKeyDown={handleEmailKeyDown}
                         className={cn(
-                          'rounded-[10px] shadow-sm transition-colors focus:border-gray-400 focus:ring-2 focus:ring-gray-100',
                           showEmailValidationError &&
                             emailErrors.length > 0 &&
-                            'border-red-500 focus:border-red-500 focus:ring-red-100 focus-visible:ring-red-500'
+                            'border-red-500 focus:border-red-500'
                         )}
                         autoFocus
                       />
@@ -270,13 +269,7 @@
                             <InputOTPSlot
                               key={index}
                               index={index}
-                              className={cn(
-                                '!rounded-[10px] h-12 w-12 border bg-white text-center font-medium text-lg shadow-sm transition-all duration-200',
-                                'border-gray-300 hover:border-gray-400',
-                                'focus:border-gray-400 focus:outline-none focus:ring-2 focus:ring-gray-100',
-                                authError &&
-                                  'border-red-500 focus:border-red-500 focus:ring-red-100'
-                              )}
+                              className={cn('!rounded-[10px] h-12 w-12', authError && 'border-red-500')}
                             />
                           ))}
                         </InputOTPGroup>

diff --git a/apps/sim/app/chat/components/auth/password/password-auth.tsx b/apps/sim/app/chat/components/auth/password/password-auth.tsx
--- a/apps/sim/app/chat/components/auth/password/password-auth.tsx
+++ b/apps/sim/app/chat/components/auth/password/password-auth.tsx
@@ -3,8 +3,7 @@
 import { type KeyboardEvent, useState } from 'react'
 import { createLogger } from '@sim/logger'
 import { Eye, EyeOff } from 'lucide-react'
-import { Input } from '@/components/emcn'
-import { Label } from '@/components/ui/label'
+import { Input, Label } from '@/components/emcn'
 import { cn } from '@/lib/core/utils/cn'
 import AuthBackground from '@/app/(auth)/components/auth-background'
 import { BrandedButton } from '@/app/(auth)/components/branded-button'
@@ -122,10 +121,10 @@
                       onChange={handlePasswordChange}
                       onKeyDown={handleKeyDown}
                       className={cn(
-                        'rounded-[10px] pr-10 shadow-sm transition-colors focus:border-gray-400 focus:ring-2 focus:ring-gray-100',
+                        'pr-10',
                         showValidationError &&
                           passwordErrors.length > 0 &&
-                          'border-red-500 focus:border-red-500 focus:ring-red-100 focus-visible:ring-red-500'
+                          'border-red-500 focus:border-red-500'
                       )}
                       autoFocus
                     />

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

Copy link

@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.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

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.

2 participants