Skip to content

Commit e43e78f

Browse files
authored
feat(whitelabel): add in the ability to whitelabel via envvars (#887)
* feat(whitelabel): add in the ability to whitelabel via envvars * restore site.webmanifest * fix(dynamic): remove force-dynamic from routes that don't need it (#888) * Reinstall dependencies * Update docs
1 parent 1b0d304 commit e43e78f

File tree

26 files changed

+583
-205
lines changed

26 files changed

+583
-205
lines changed

.github/CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ This visibility system ensures clean user interfaces while maintaining full flex
537537
538538
### Guidelines & Best Practices
539539
540-
- **Code Style:** Follow the project's ESLint and Prettier configurations. Use meaningful variable names and small, focused functions.
540+
- **Code Style:** Follow the project's Biome configurations. Use meaningful variable names and small, focused functions.
541541
- **Documentation:** Clearly document the purpose, inputs, outputs, and any special behavior for your block/tool.
542542
- **Error Handling:** Implement robust error handling and provide user-friendly error messages.
543543
- **Parameter Visibility:** Always specify the appropriate visibility level for each parameter to ensure proper UI behavior and LLM integration.

apps/docs/content/docs/tools/file.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ The File Parser tool is particularly useful for scenarios where your agents need
5050

5151
## Usage Instructions
5252

53-
Upload and extract contents from structured file formats including PDFs, CSV spreadsheets, and Word documents (DOCX). Upload files directly. Specialized parsers extract text and metadata from each format. You can upload multiple files at once and access them individually or as a combined document.
53+
Upload and extract contents from structured file formats including PDFs, CSV spreadsheets, and Word documents (DOCX). You can either provide a URL to a file or upload files directly. Specialized parsers extract text and metadata from each format. You can upload multiple files at once and access them individually or as a combined document.
5454

5555

5656

apps/docs/content/docs/tools/hunter.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ With Hunter.io, you can:
3838
In Sim, the Hunter.io integration enables your agents to programmatically search for and verify email addresses, discover companies, and enrich contact data using Hunter.io’s API. This allows you to automate lead generation, contact enrichment, and email verification directly within your workflows. Your agents can leverage Hunter.io’s tools to streamline outreach, keep your CRM up-to-date, and power intelligent automation scenarios for sales, recruiting, and more.
3939
{/* MANUAL-CONTENT-END */}
4040

41+
4142
## Usage Instructions
4243

4344
Search for email addresses, verify their deliverability, discover companies, and enrich contact data using Hunter.io's powerful email finding capabilities.

apps/docs/content/docs/tools/knowledge.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Search for similar content in a knowledge base using vector similarity
6464
| Parameter | Type | Required | Description |
6565
| --------- | ---- | -------- | ----------- |
6666
| `knowledgeBaseId` | string | Yes | ID of the knowledge base to search in |
67-
| `query` | string | Yes | Search query text |
67+
| `query` | string | No | Search query text \(optional when using tag filters\) |
6868
| `topK` | number | No | Number of most similar results to return \(1-100\) |
6969
| `tagFilters` | any | No | Array of tag filters with tagName and tagValue properties |
7070

apps/docs/content/docs/tools/mistral_parse.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ The Mistral Parse tool is particularly useful for scenarios where your agents ne
7979

8080
## Usage Instructions
8181

82-
Extract text and structure from PDF documents using Mistral's OCR API. Configure processing options and get the content in your preferred format. For URLs, they must be publicly accessible and point to a valid PDF file. Note: Google Drive, Dropbox, and other cloud storage links are not supported; use a direct download URL from a web server instead.
82+
Extract text and structure from PDF documents using Mistral's OCR API. Either enter a URL to a PDF document or upload a PDF file directly. Configure processing options and get the content in your preferred format. For URLs, they must be publicly accessible and point to a valid PDF file. Note: Google Drive, Dropbox, and other cloud storage links are not supported; use a direct download URL from a web server instead.
8383

8484

8585

apps/docs/content/docs/tools/outlook.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ Send emails using Outlook
158158
| `to` | string | Yes | Recipient email address |
159159
| `subject` | string | Yes | Email subject |
160160
| `body` | string | Yes | Email body content |
161+
| `replyToMessageId` | string | No | Message ID to reply to \(for threading\) |
162+
| `conversationId` | string | No | Conversation ID for threading |
163+
| `cc` | string | No | CC recipients \(comma-separated\) |
164+
| `bcc` | string | No | BCC recipients \(comma-separated\) |
161165

162166
#### Output
163167

apps/sim/app/(auth)/layout.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
import Image from 'next/image'
44
import Link from 'next/link'
5+
import { useBrandConfig } from '@/lib/branding/branding'
56
import { GridPattern } from '@/app/(landing)/components/grid-pattern'
67

78
export default function AuthLayout({ children }: { children: React.ReactNode }) {
9+
const brand = useBrandConfig()
10+
811
return (
912
<main className='relative flex min-h-screen flex-col bg-[#0C0C0C] font-geist-sans text-white'>
1013
{/* Background pattern */}
@@ -21,7 +24,17 @@ export default function AuthLayout({ children }: { children: React.ReactNode })
2124
<div className='relative z-10 px-6 pt-9'>
2225
<div className='mx-auto max-w-7xl'>
2326
<Link href='/' className='inline-flex'>
24-
<Image src='/sim.svg' alt='Sim Logo' width={42} height={42} />
27+
{brand.logoUrl ? (
28+
<img
29+
src={brand.logoUrl}
30+
alt={`${brand.name} Logo`}
31+
width={42}
32+
height={42}
33+
className='h-[42px] w-[42px] object-contain'
34+
/>
35+
) : (
36+
<Image src='/sim.svg' alt={`${brand.name} Logo`} width={42} height={42} />
37+
)}
2538
</Link>
2639
</div>
2740
</div>

apps/sim/app/(landing)/components/nav-client.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
SheetTitle,
1616
SheetTrigger,
1717
} from '@/components/ui/sheet'
18+
import { useBrandConfig } from '@/lib/branding/branding'
1819
import { usePrefetchOnHover } from '@/app/(landing)/utils/prefetch'
1920

2021
// --- Framer Motion Variants ---
@@ -165,6 +166,7 @@ export default function NavClient({
165166
const [isMobile, setIsMobile] = useState(initialIsMobile ?? false)
166167
const [isSheetOpen, setIsSheetOpen] = useState(false)
167168
const _router = useRouter()
169+
const brand = useBrandConfig()
168170

169171
useEffect(() => {
170172
setMounted(true)
@@ -199,7 +201,17 @@ export default function NavClient({
199201
<div className='flex flex-1 items-center'>
200202
<div className='inline-block'>
201203
<Link href='/' className='inline-flex'>
202-
<Image src='/sim.svg' alt='Sim Logo' width={42} height={42} />
204+
{brand.logoUrl ? (
205+
<img
206+
src={brand.logoUrl}
207+
alt={`${brand.name} Logo`}
208+
width={42}
209+
height={42}
210+
className='h-[42px] w-[42px] object-contain'
211+
/>
212+
) : (
213+
<Image src='/sim.svg' alt={`${brand.name} Logo`} width={42} height={42} />
214+
)}
203215
</Link>
204216
</div>
205217
</div>

apps/sim/app/layout.tsx

Lines changed: 22 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { Analytics } from '@vercel/analytics/next'
22
import { SpeedInsights } from '@vercel/speed-insights/next'
3-
import { GeistSans } from 'geist/font/sans'
43
import type { Metadata, Viewport } from 'next'
54
import { PublicEnvScript } from 'next-runtime-env'
5+
import { BrandedLayout } from '@/components/branded-layout'
6+
import { generateBrandedMetadata, generateStructuredData } from '@/lib/branding/metadata'
7+
import { env } from '@/lib/env'
68
import { isHosted } from '@/lib/environment'
79
import { createLogger } from '@/lib/logs/console/logger'
810
import { getAssetUrl } from '@/lib/utils'
@@ -51,149 +53,20 @@ export const viewport: Viewport = {
5153
userScalable: false,
5254
}
5355

54-
export const metadata: Metadata = {
55-
title: {
56-
template: '',
57-
default: 'Sim',
58-
},
59-
description:
60-
'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.',
61-
applicationName: 'Sim',
62-
authors: [{ name: 'Sim' }],
63-
generator: 'Next.js',
64-
keywords: [
65-
'AI agent',
66-
'AI agent builder',
67-
'AI agent workflow',
68-
'AI workflow automation',
69-
'visual workflow editor',
70-
'AI agents',
71-
'workflow canvas',
72-
'intelligent automation',
73-
'AI tools',
74-
'workflow designer',
75-
'artificial intelligence',
76-
'business automation',
77-
'AI agent workflows',
78-
'visual programming',
79-
],
80-
referrer: 'origin-when-cross-origin',
81-
creator: 'Sim',
82-
publisher: 'Sim',
83-
metadataBase: new URL('https://sim.ai'),
84-
alternates: {
85-
canonical: '/',
86-
languages: {
87-
'en-US': '/en-US',
88-
},
89-
},
90-
robots: {
91-
index: true,
92-
follow: true,
93-
googleBot: {
94-
index: true,
95-
follow: true,
96-
'max-image-preview': 'large',
97-
'max-video-preview': -1,
98-
'max-snippet': -1,
99-
},
100-
},
101-
openGraph: {
102-
type: 'website',
103-
locale: 'en_US',
104-
url: 'https://sim.ai',
105-
title: 'Sim',
106-
description:
107-
'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.',
108-
siteName: 'Sim',
109-
images: [
110-
{
111-
url: getAssetUrl('social/facebook.png'),
112-
width: 1200,
113-
height: 630,
114-
alt: 'Sim',
115-
},
116-
],
117-
},
118-
twitter: {
119-
card: 'summary_large_image',
120-
title: 'Sim',
121-
description:
122-
'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.',
123-
images: [getAssetUrl('social/twitter.png')],
124-
creator: '@simstudioai',
125-
site: '@simstudioai',
126-
},
127-
manifest: '/favicon/site.webmanifest',
128-
icons: {
129-
icon: [
130-
{ url: '/favicon/favicon-16x16.png', sizes: '16x16', type: 'image/png' },
131-
{ url: '/favicon/favicon-32x32.png', sizes: '32x32', type: 'image/png' },
132-
{
133-
url: '/favicon/favicon-192x192.png',
134-
sizes: '192x192',
135-
type: 'image/png',
136-
},
137-
{
138-
url: '/favicon/favicon-512x512.png',
139-
sizes: '512x512',
140-
type: 'image/png',
141-
},
142-
{ url: '/sim.png', sizes: 'any', type: 'image/png' },
143-
],
144-
apple: '/favicon/apple-touch-icon.png',
145-
shortcut: '/favicon/favicon.ico',
146-
},
147-
appleWebApp: {
148-
capable: true,
149-
statusBarStyle: 'default',
150-
title: 'Sim',
151-
},
152-
formatDetection: {
153-
telephone: false,
154-
},
155-
category: 'technology',
156-
other: {
157-
'apple-mobile-web-app-capable': 'yes',
158-
'mobile-web-app-capable': 'yes',
159-
'msapplication-TileColor': '#ffffff',
160-
'msapplication-config': '/favicon/browserconfig.xml',
161-
},
162-
}
56+
// Generate dynamic metadata based on brand configuration
57+
export const metadata: Metadata = generateBrandedMetadata()
16358

16459
export default function RootLayout({ children }: { children: React.ReactNode }) {
60+
const structuredData = generateStructuredData()
61+
16562
return (
166-
<html lang='en' suppressHydrationWarning className={GeistSans.className}>
63+
<html lang='en' suppressHydrationWarning>
16764
<head>
16865
{/* Structured Data for SEO */}
16966
<script
17067
type='application/ld+json'
17168
dangerouslySetInnerHTML={{
172-
__html: JSON.stringify({
173-
'@context': 'https://schema.org',
174-
'@type': 'SoftwareApplication',
175-
name: 'Sim',
176-
description:
177-
'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.',
178-
url: 'https://sim.ai',
179-
applicationCategory: 'BusinessApplication',
180-
operatingSystem: 'Web Browser',
181-
offers: {
182-
'@type': 'Offer',
183-
category: 'SaaS',
184-
},
185-
creator: {
186-
'@type': 'Organization',
187-
name: 'Sim',
188-
url: 'https://sim.ai',
189-
},
190-
featureList: [
191-
'Visual AI Agent Builder',
192-
'Workflow Canvas Interface',
193-
'AI Agent Automation',
194-
'Custom AI Workflows',
195-
],
196-
}),
69+
__html: JSON.stringify(structuredData),
19770
}}
19871
/>
19972

@@ -226,24 +99,26 @@ export default function RootLayout({ children }: { children: React.ReactNode })
22699
<PublicEnvScript />
227100

228101
{/* RB2B Script - Only load on hosted version */}
229-
{/* {isHosted && env.NEXT_PUBLIC_RB2B_KEY && (
102+
{isHosted && env.NEXT_PUBLIC_RB2B_KEY && (
230103
<script
231104
dangerouslySetInnerHTML={{
232105
__html: `!function () {var reb2b = window.reb2b = window.reb2b || [];if (reb2b.invoked) return;reb2b.invoked = true;reb2b.methods = ["identify", "collect"];reb2b.factory = function (method) {return function () {var args = Array.prototype.slice.call(arguments);args.unshift(method);reb2b.push(args);return reb2b;};};for (var i = 0; i < reb2b.methods.length; i++) {var key = reb2b.methods[i];reb2b[key] = reb2b.factory(key);}reb2b.load = function (key) {var script = document.createElement("script");script.type = "text/javascript";script.async = true;script.src = "https://b2bjsstore.s3.us-west-2.amazonaws.com/b/" + key + "/${env.NEXT_PUBLIC_RB2B_KEY}.js.gz";var first = document.getElementsByTagName("script")[0];first.parentNode.insertBefore(script, first);};reb2b.SNIPPET_VERSION = "1.0.1";reb2b.load("${env.NEXT_PUBLIC_RB2B_KEY}");}();`,
233106
}}
234107
/>
235-
)} */}
108+
)}
236109
</head>
237110
<body suppressHydrationWarning>
238-
<ZoomPrevention />
239-
<TelemetryConsentDialog />
240-
{children}
241-
{isHosted && (
242-
<>
243-
<SpeedInsights />
244-
<Analytics />
245-
</>
246-
)}
111+
<BrandedLayout>
112+
<ZoomPrevention />
113+
<TelemetryConsentDialog />
114+
{children}
115+
{isHosted && (
116+
<>
117+
<SpeedInsights />
118+
<Analytics />
119+
</>
120+
)}
121+
</BrandedLayout>
247122
</body>
248123
</html>
249124
)

apps/sim/app/manifest.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import type { MetadataRoute } from 'next'
2+
import { getBrandConfig } from '@/lib/branding/branding'
3+
4+
export default function manifest(): MetadataRoute.Manifest {
5+
const brand = getBrandConfig()
6+
7+
return {
8+
name: brand.name,
9+
short_name: brand.name,
10+
description:
11+
'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.',
12+
start_url: '/',
13+
display: 'standalone',
14+
background_color: brand.primaryColor || '#ffffff',
15+
theme_color: brand.primaryColor || '#ffffff',
16+
icons: [
17+
{
18+
src: '/favicon/android-chrome-192x192.png',
19+
sizes: '192x192',
20+
type: 'image/png',
21+
},
22+
{
23+
src: '/favicon/android-chrome-512x512.png',
24+
sizes: '512x512',
25+
type: 'image/png',
26+
},
27+
],
28+
}
29+
}

0 commit comments

Comments
 (0)