From 09211224ff3ef6dc21ebd156328af462dac53992 Mon Sep 17 00:00:00 2001 From: waleedlatif1 Date: Tue, 5 Aug 2025 18:20:40 -0700 Subject: [PATCH 1/5] feat(whitelabel): add in the ability to whitelabel via envvars --- apps/sim/app/(auth)/layout.tsx | 15 +- .../app/(landing)/components/nav-client.tsx | 14 +- apps/sim/app/layout.tsx | 169 +++--------------- apps/sim/app/manifest.ts | 29 +++ apps/sim/app/unsubscribe/page.tsx | 18 +- .../components/search-modal/search-modal.tsx | 11 +- apps/sim/components/branded-layout.tsx | 55 ++++++ .../emails/batch-invitation-email.tsx | 10 +- apps/sim/components/emails/footer.tsx | 11 +- .../components/emails/invitation-email.tsx | 7 +- .../emails/otp-verification-email.tsx | 25 +-- .../emails/reset-password-email.tsx | 15 +- .../emails/workspace-invitation.tsx | 7 +- apps/sim/lib/branding/branding.ts | 81 +++++++++ apps/sim/lib/branding/metadata.ts | 153 ++++++++++++++++ apps/sim/lib/env.ts | 30 ++++ apps/sim/public/favicon/site.webmanifest | 19 -- helm/sim/examples/values-whitelabeled.yaml | 91 ++++++++++ helm/sim/values.yaml | 16 ++ 19 files changed, 571 insertions(+), 205 deletions(-) create mode 100644 apps/sim/app/manifest.ts create mode 100644 apps/sim/components/branded-layout.tsx create mode 100644 apps/sim/lib/branding/branding.ts create mode 100644 apps/sim/lib/branding/metadata.ts delete mode 100644 apps/sim/public/favicon/site.webmanifest create mode 100644 helm/sim/examples/values-whitelabeled.yaml diff --git a/apps/sim/app/(auth)/layout.tsx b/apps/sim/app/(auth)/layout.tsx index 76a3726817d..3d1f4bcb30e 100644 --- a/apps/sim/app/(auth)/layout.tsx +++ b/apps/sim/app/(auth)/layout.tsx @@ -2,9 +2,12 @@ import Image from 'next/image' import Link from 'next/link' +import { useBrandConfig } from '@/lib/branding/branding' import { GridPattern } from '@/app/(landing)/components/grid-pattern' export default function AuthLayout({ children }: { children: React.ReactNode }) { + const brand = useBrandConfig() + return (
{/* Background pattern */} @@ -21,7 +24,17 @@ export default function AuthLayout({ children }: { children: React.ReactNode })
- Sim Logo + {brand.logoUrl ? ( + {`${brand.name} + ) : ( + {`${brand.name} + )}
diff --git a/apps/sim/app/(landing)/components/nav-client.tsx b/apps/sim/app/(landing)/components/nav-client.tsx index 6bc96ea1cc0..e312b7e09d9 100644 --- a/apps/sim/app/(landing)/components/nav-client.tsx +++ b/apps/sim/app/(landing)/components/nav-client.tsx @@ -15,6 +15,7 @@ import { SheetTitle, SheetTrigger, } from '@/components/ui/sheet' +import { useBrandConfig } from '@/lib/branding/branding' import { usePrefetchOnHover } from '@/app/(landing)/utils/prefetch' // --- Framer Motion Variants --- @@ -165,6 +166,7 @@ export default function NavClient({ const [isMobile, setIsMobile] = useState(initialIsMobile ?? false) const [isSheetOpen, setIsSheetOpen] = useState(false) const _router = useRouter() + const brand = useBrandConfig() useEffect(() => { setMounted(true) @@ -199,7 +201,17 @@ export default function NavClient({
- Sim Logo + {brand.logoUrl ? ( + {`${brand.name} + ) : ( + {`${brand.name} + )}
diff --git a/apps/sim/app/layout.tsx b/apps/sim/app/layout.tsx index 06e9f2d919b..07ef379bb35 100644 --- a/apps/sim/app/layout.tsx +++ b/apps/sim/app/layout.tsx @@ -1,8 +1,10 @@ import { Analytics } from '@vercel/analytics/next' import { SpeedInsights } from '@vercel/speed-insights/next' -import { GeistSans } from 'geist/font/sans' import type { Metadata, Viewport } from 'next' import { PublicEnvScript } from 'next-runtime-env' +import { BrandedLayout } from '@/components/branded-layout' +import { generateBrandedMetadata, generateStructuredData } from '@/lib/branding/metadata' +import { env } from '@/lib/env' import { isHosted } from '@/lib/environment' import { createLogger } from '@/lib/logs/console/logger' import { getAssetUrl } from '@/lib/utils' @@ -51,149 +53,20 @@ export const viewport: Viewport = { userScalable: false, } -export const metadata: Metadata = { - title: { - template: '', - default: 'Sim', - }, - description: - 'Build and deploy AI agents using our Figma-like canvas. Build, write evals, and deploy AI agent workflows that automate workflows and streamline your business processes.', - applicationName: 'Sim', - authors: [{ name: 'Sim' }], - generator: 'Next.js', - keywords: [ - 'AI agent', - 'AI agent builder', - 'AI agent workflow', - 'AI workflow automation', - 'visual workflow editor', - 'AI agents', - 'workflow canvas', - 'intelligent automation', - 'AI tools', - 'workflow designer', - 'artificial intelligence', - 'business automation', - 'AI agent workflows', - 'visual programming', - ], - referrer: 'origin-when-cross-origin', - creator: 'Sim', - publisher: 'Sim', - metadataBase: new URL('https://sim.ai'), - alternates: { - canonical: '/', - languages: { - 'en-US': '/en-US', - }, - }, - robots: { - index: true, - follow: true, - googleBot: { - index: true, - follow: true, - 'max-image-preview': 'large', - 'max-video-preview': -1, - 'max-snippet': -1, - }, - }, - openGraph: { - type: 'website', - locale: 'en_US', - url: 'https://sim.ai', - title: 'Sim', - description: - 'Build and deploy AI agents using our Figma-like canvas. Build, write evals, and deploy AI agent workflows that automate workflows and streamline your business processes.', - siteName: 'Sim', - images: [ - { - url: getAssetUrl('social/facebook.png'), - width: 1200, - height: 630, - alt: 'Sim', - }, - ], - }, - twitter: { - card: 'summary_large_image', - title: 'Sim', - description: - 'Build and deploy AI agents using our Figma-like canvas. Build, write evals, and deploy AI agent workflows that automate workflows and streamline your business processes.', - images: [getAssetUrl('social/twitter.png')], - creator: '@simstudioai', - site: '@simstudioai', - }, - manifest: '/favicon/site.webmanifest', - icons: { - icon: [ - { url: '/favicon/favicon-16x16.png', sizes: '16x16', type: 'image/png' }, - { url: '/favicon/favicon-32x32.png', sizes: '32x32', type: 'image/png' }, - { - url: '/favicon/favicon-192x192.png', - sizes: '192x192', - type: 'image/png', - }, - { - url: '/favicon/favicon-512x512.png', - sizes: '512x512', - type: 'image/png', - }, - { url: '/sim.png', sizes: 'any', type: 'image/png' }, - ], - apple: '/favicon/apple-touch-icon.png', - shortcut: '/favicon/favicon.ico', - }, - appleWebApp: { - capable: true, - statusBarStyle: 'default', - title: 'Sim', - }, - formatDetection: { - telephone: false, - }, - category: 'technology', - other: { - 'apple-mobile-web-app-capable': 'yes', - 'mobile-web-app-capable': 'yes', - 'msapplication-TileColor': '#ffffff', - 'msapplication-config': '/favicon/browserconfig.xml', - }, -} +// Generate dynamic metadata based on brand configuration +export const metadata: Metadata = generateBrandedMetadata() export default function RootLayout({ children }: { children: React.ReactNode }) { + const structuredData = generateStructuredData() + return ( - + {/* Structured Data for SEO */}