diff --git a/apps/sim/app/(landing)/components/footer/footer.tsx b/apps/sim/app/(landing)/components/footer/footer.tsx index 09b07babd54..ebf30480172 100644 --- a/apps/sim/app/(landing)/components/footer/footer.tsx +++ b/apps/sim/app/(landing)/components/footer/footer.tsx @@ -1,4 +1,5 @@ import Link from 'next/link' +import { ALL_COMPETITORS } from '@/app/(landing)/comparisons/utils' import { SimWordmark } from '@/app/(landing)/components/navbar/components/sim-wordmark' import { MODEL_PROVIDERS_WITH_CATALOGS } from '@/app/(landing)/models/utils' @@ -41,7 +42,7 @@ const PRODUCT_LINKS: FooterItem[] = [ const RESOURCES_LINKS: FooterItem[] = [ { label: 'Blog', href: '/blog' }, { label: 'Docs', href: 'https://docs.sim.ai', external: true }, - { label: 'Compare', href: '/comparisons' }, + { label: 'Library', href: '/library' }, { label: 'Careers', href: '/careers' }, { label: 'Changelog', href: '/changelog' }, { label: 'Contact', href: '/contact' }, @@ -56,17 +57,13 @@ const MODEL_LINKS: FooterItem[] = [ })), ] -const BLOCK_LINKS: FooterItem[] = [ - { label: 'Agent', href: 'https://docs.sim.ai/workflows/blocks/agent', external: true }, - { label: 'Router', href: 'https://docs.sim.ai/workflows/blocks/router', external: true }, - { label: 'Function', href: 'https://docs.sim.ai/workflows/blocks/function', external: true }, - { label: 'Condition', href: 'https://docs.sim.ai/workflows/blocks/condition', external: true }, - { label: 'API Block', href: 'https://docs.sim.ai/workflows/blocks/api', external: true }, - { label: 'Workflow', href: 'https://docs.sim.ai/workflows/blocks/workflow', external: true }, - { label: 'Parallel', href: 'https://docs.sim.ai/workflows/blocks/parallel', external: true }, - { label: 'Guardrails', href: 'https://docs.sim.ai/workflows/blocks/guardrails', external: true }, - { label: 'Evaluator', href: 'https://docs.sim.ai/workflows/blocks/evaluator', external: true }, - { label: 'Loop', href: 'https://docs.sim.ai/workflows/blocks/loop', external: true }, +/** Top comparison pages, sourced from the competitor catalog so labels/hrefs never drift. */ +const COMPARE_LINKS: FooterItem[] = [ + { label: 'All Comparisons', href: '/comparisons' }, + ...ALL_COMPETITORS.slice(0, 9).map((competitor) => ({ + label: competitor.name, + href: `/comparisons/${competitor.id}`, + })), ] const INTEGRATION_LINKS: FooterItem[] = [ @@ -153,7 +150,7 @@ export function Footer() { - + diff --git a/apps/sim/app/(landing)/components/navbar/components/mobile-nav/mobile-nav.tsx b/apps/sim/app/(landing)/components/navbar/components/mobile-nav/mobile-nav.tsx index f0963c229d4..4790edb28d1 100644 --- a/apps/sim/app/(landing)/components/navbar/components/mobile-nav/mobile-nav.tsx +++ b/apps/sim/app/(landing)/components/navbar/components/mobile-nav/mobile-nav.tsx @@ -43,10 +43,7 @@ interface MobileNavProps { * a grouped section automatically - the sheet mirrors the desktop nav's * information architecture with no extra edit. */ -const STANDALONE_LINKS = [ - { label: 'Enterprise', href: '/enterprise' }, - { label: 'Pricing', href: '/pricing' }, -] as const +const STANDALONE_LINKS = [{ label: 'Pricing', href: '/pricing' }] as const /** Shared row chrome for every tappable text link in the sheet. */ const SHEET_ROW = diff --git a/apps/sim/app/(landing)/components/navbar/components/nav-menu-chip/constants.ts b/apps/sim/app/(landing)/components/navbar/components/nav-menu-chip/constants.ts index 9a74b6142c4..b598d046e72 100644 --- a/apps/sim/app/(landing)/components/navbar/components/nav-menu-chip/constants.ts +++ b/apps/sim/app/(landing)/components/navbar/components/nav-menu-chip/constants.ts @@ -41,8 +41,8 @@ export const PLATFORM_MENU: NavMenu = { } /** - * The Resources menu - learning and reference surfaces. Six items in a - * three-column grid. Docs is the one off-site link. + * The Resources menu - learning and reference surfaces plus the Enterprise + * page. Six items in a three-column grid. Docs is the one off-site link. */ export const RESOURCES_MENU: NavMenu = { label: 'Resources', @@ -59,9 +59,9 @@ export const RESOURCES_MENU: NavMenu = { href: '/blog', }, { - title: 'Library', - description: 'Comparisons, how-tos, and roundups', - href: '/library', + title: 'Enterprise', + description: 'Govern AI agents at enterprise scale', + href: '/enterprise', }, { title: 'Changelog', @@ -82,15 +82,16 @@ export const RESOURCES_MENU: NavMenu = { } /** - * The Solutions menu - agent use cases by team. Six items in a three-column grid. + * The Solutions menu - agent use cases by team, Sales first. Six items in a + * three-column grid. */ export const SOLUTIONS_MENU: NavMenu = { label: 'Solutions', items: [ { - title: 'Enterprise', - description: 'Govern AI agents at enterprise scale', - href: '/enterprise', + title: 'Sales', + description: 'Automate outreach and CRM upkeep', + href: '/solutions/sales', }, { title: 'Engineering', diff --git a/apps/sim/app/(landing)/components/navbar/navbar.tsx b/apps/sim/app/(landing)/components/navbar/navbar.tsx index ee7cbb30444..2cf7458cac6 100644 --- a/apps/sim/app/(landing)/components/navbar/navbar.tsx +++ b/apps/sim/app/(landing)/components/navbar/navbar.tsx @@ -34,6 +34,7 @@ import { DEMO_HREF, SIGNUP_HREF } from '@/app/(landing)/constants' * chip-height slot, chip-text color) → the {@link NAV_MENUS} mega-menus * (pure-CSS hover/focus dropdowns) → Pricing → GitHub stars. Right side: Log in * (default chip), Contact sales (outline chip), Sign up (filled chip). + * Enterprise lives inside the Resources mega-menu, not as a standalone chip. */ interface NavbarProps { @@ -75,9 +76,6 @@ export function Navbar({ stars, logoOnly = false }: NavbarProps) { {NAV_MENUS.map((menu) => ( ))} - diff --git a/apps/sim/app/(landing)/scheduled-tasks/components/scheduled-tasks-calendar-loop/index.ts b/apps/sim/app/(landing)/scheduled-tasks/components/scheduled-tasks-calendar-loop/index.ts new file mode 100644 index 00000000000..35e43aa2af3 --- /dev/null +++ b/apps/sim/app/(landing)/scheduled-tasks/components/scheduled-tasks-calendar-loop/index.ts @@ -0,0 +1 @@ +export { ScheduledTasksCalendarLoop } from './scheduled-tasks-calendar-loop' diff --git a/apps/sim/app/(landing)/scheduled-tasks/components/scheduled-tasks-calendar-loop/scheduled-tasks-calendar-loop.module.css b/apps/sim/app/(landing)/scheduled-tasks/components/scheduled-tasks-calendar-loop/scheduled-tasks-calendar-loop.module.css new file mode 100644 index 00000000000..ea6ba04bb0a --- /dev/null +++ b/apps/sim/app/(landing)/scheduled-tasks/components/scheduled-tasks-calendar-loop/scheduled-tasks-calendar-loop.module.css @@ -0,0 +1,28 @@ +/** + * The ScheduledTasksCalendarLoop's motion: a newly scheduled task pill stamps + * in once when the parent clock mounts it on its calendar day. A one-shot + * mount animation - the loop's restart unmounts and remounts the pills, so a + * new cycle replays them naturally. Under prefers-reduced-motion the parent + * renders the finished frame and this never plays. + */ + +.pillIn { + animation: scheduled-tasks-pill-in 0.35s cubic-bezier(0.22, 1, 0.36, 1) backwards; +} + +@keyframes scheduled-tasks-pill-in { + from { + opacity: 0; + transform: translateY(-4px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@media (prefers-reduced-motion: reduce) { + .pillIn { + animation: none; + } +} diff --git a/apps/sim/app/(landing)/scheduled-tasks/components/scheduled-tasks-calendar-loop/scheduled-tasks-calendar-loop.tsx b/apps/sim/app/(landing)/scheduled-tasks/components/scheduled-tasks-calendar-loop/scheduled-tasks-calendar-loop.tsx new file mode 100644 index 00000000000..73824540eae --- /dev/null +++ b/apps/sim/app/(landing)/scheduled-tasks/components/scheduled-tasks-calendar-loop/scheduled-tasks-calendar-loop.tsx @@ -0,0 +1,300 @@ +'use client' + +import { useState } from 'react' +import { Chip, chipContentGap, chipPrimaryFillTokens, cn } from '@sim/emcn' +import { Calendar, Plus } from '@sim/emcn/icons' +import { ChevronLeft, ChevronRight } from 'lucide-react' +import { HeroLoopShell } from '@/app/(landing)/components/shared/hero-loop-shell' +import { RESET_FADE_MS } from '@/app/(landing)/hooks/use-design-scale' +import { useMotionSafeCycle } from '@/app/(landing)/hooks/use-motion-safe-cycle' +import styles from '@/app/(landing)/scheduled-tasks/components/scheduled-tasks-calendar-loop/scheduled-tasks-calendar-loop.module.css' + +/** Sidebar content for the scheduled-tasks hero - a recurring-ops workspace. */ +const SIDEBAR_CHATS = [ + 'Morning digest setup', + 'Move sync to nightly', + 'Weekly KPI report', + 'Retry failed runs', +] as const + +/** Deployed workflows in the sidebar - five fill the design height. */ +const SIDEBAR_WORKFLOWS = [ + 'Morning digest', + 'Nightly data sync', + 'Weekly KPI report', + 'Invoice sweep', + 'Churn-risk alerts', +] as const + +/** Weekday header labels, Sunday-start, matching the real month grid. */ +const WEEKDAY_LABELS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] as const + +/** Month the fixed calendar shows - June 2026 opens on a Monday and fills five Sunday-start weeks. */ +const MONTH_LABEL = 'June 2026' +/** Day-of-month carrying the today ring, a mid-month Wednesday. */ +const TODAY = 10 +/** Days in June - the grid's in-month cells span indexes 1..30. */ +const DAYS_IN_MONTH = 30 +/** Total cells in the five-week Sunday-start grid. */ +const CELL_COUNT = 35 + +interface CalendarPill { + /** Occurrence start time, preformatted like the real event chip's `h:mm a`. */ + time: string + /** Scheduled task title. */ + title: string + /** Paused schedules render dimmed - the one status the real pill signals. */ + paused?: boolean + /** + * Position of this pill in the animated stamp-in series (the Weekly KPI + * report being scheduled across the month's Mondays); unset pills are the + * settled base calendar. + */ + stampIndex?: number +} + +interface CalendarCell { + /** Day-of-month number the cell shows. */ + day: number + /** In-month days get body-colored numbers; leading/trailing days go muted. */ + inMonth: boolean + /** Today's number gets the real grid's 26px primary-filled square. */ + isToday: boolean + /** Task occurrences on this day, in start-time order. */ + pills: CalendarPill[] +} + +/** Mondays in the grid (cell indexes), in stamp order for the animated series. */ +const MONDAY_CELLS: readonly number[] = [1, 8, 15, 22, 29] + +/** + * Derives one day's task pills from the workspace's recurring schedules: + * the Morning digest on weekdays at 9:00 AM, the paused Churn-risk alerts on + * Thursdays, the Nightly data sync every night, a monthly Invoice sweep on + * the 30th, and - as the animated series - the Weekly KPI report landing on + * each Monday as the schedule is created. + */ +function pillsForCell(index: number): CalendarPill[] { + const weekday = index % 7 + const pills: CalendarPill[] = [] + const mondayOrder = MONDAY_CELLS.indexOf(index) + if (mondayOrder !== -1) { + pills.push({ time: '8:00 AM', title: 'Weekly KPI report', stampIndex: mondayOrder }) + } + if (weekday >= 1 && weekday <= 5) { + pills.push({ time: '9:00 AM', title: 'Morning digest' }) + } + if (index === DAYS_IN_MONTH) { + pills.push({ time: '3:00 PM', title: 'Invoice sweep' }) + } + if (weekday === 4) { + pills.push({ time: '4:00 PM', title: 'Churn-risk alerts', paused: true }) + } + pills.push({ time: '11:00 PM', title: 'Nightly data sync' }) + return pills +} + +/** + * The fixed June 2026 grid: May 31 leads the first week, June fills the + * middle, and July 1-4 close the fifth week - every cell's pills derived + * from the recurring schedules above. + */ +const CALENDAR_CELLS: readonly CalendarCell[] = Array.from({ length: CELL_COUNT }, (_, index) => { + const inMonth = index >= 1 && index <= DAYS_IN_MONTH + const day = index === 0 ? 31 : inMonth ? index : index - DAYS_IN_MONTH + return { + day, + inMonth, + isToday: index === TODAY, + pills: pillsForCell(index), + } +}) + +/** Total pills the animated Weekly KPI series stamps onto the month's Mondays. */ +const TOTAL_STAMPED_PILLS = MONDAY_CELLS.length + +/** The settled calendar holds this long before the first KPI pill lands. */ +const IDLE_HOLD_MS = 900 +/** Stamped pill N lands at IDLE_HOLD_MS + N * PILL_STEP_MS. */ +const PILL_STEP_MS = 620 +/** The fully scheduled month holds this long before the fade. */ +const SCHEDULED_HOLD_MS = 5200 + +interface CalendarPanePillProps { + pill: CalendarPill + /** Stamped pills replay the mount animation each cycle. */ + animate: boolean +} + +/** + * One task pill in a day cell - the real calendar event chip's exact + * chrome (primary fill, start time + title, paused schedules dimmed) rendered + * as a plain `
` since the whole frame is `aria-hidden` decoration. + */ +function CalendarPanePill({ pill, animate }: CalendarPanePillProps) { + return ( +
+ {pill.time} + {pill.title} +
+ ) +} + +interface ScheduledTasksCalendarPaneProps { + /** How many Weekly KPI pills the stamp-in series has landed (0..5). */ + stampedCount: number +} + +/** + * The static Scheduled Tasks page in the real workspace's exact vocabulary - + * the resource header (Calendar icon + title + primary "New scheduled task" + * chip), the calendar toolbar (Today jump, period label, prev/next chevrons, + * scope chip), the sticky weekday header, and the five-week month grid of day + * cells with the today square and stacked task pills - rendered from the + * parent clock's `stampedCount` beat. + */ +function ScheduledTasksCalendarPane({ stampedCount }: ScheduledTasksCalendarPaneProps) { + return ( +
+
+ + + Scheduled Tasks + + + New scheduled task + +
+ +
+
+ Today + {MONTH_LABEL} +
+
+ + + Month +
+
+ +
+ {WEEKDAY_LABELS.map((label, index) => ( +
+ {label} +
+ ))} +
+ +
+ {CALENDAR_CELLS.map((cell, index) => ( +
+ + {cell.day} + +
+ {cell.pills.map((pill) => + pill.stampIndex !== undefined && pill.stampIndex >= stampedCount ? null : ( + + ) + )} +
+
+ ))} +
+
+ ) +} + +/** + * The scheduled-tasks hero's calendar loop - the workspace's real Scheduled + * Tasks surface as the workspace pane. Same architecture as the sibling hero + * loops (the {@link HeroLoopShell}'s fixed 1280x735 design-space layer scaled + * to the window, a parent-owned clock driving a presentational pane, + * reduced-motion showing the finished frame) and the same live sidebar with + * its Scheduled tasks nav row highlighted, but the pane is the month calendar + * itself: the settled recurring schedules hold, then a new Weekly KPI report + * schedule lands pill by pill across the month's Mondays, the fully + * scheduled month holds, and the scene fades before the cycle restarts. + * + * Everything is `pointer-events-none` decorative, matching the hero's + * `aria-hidden` frame. Under `prefers-reduced-motion` the loop never starts: + * the fully scheduled calendar renders statically. + */ +export function ScheduledTasksCalendarLoop() { + const [stampedCount, setStampedCount] = useState(0) + const [fading, setFading] = useState(false) + const [cycleId, setCycleId] = useState(0) + + useMotionSafeCycle({ + scheduleCycle: () => { + setFading(false) + setStampedCount(0) + setCycleId((c) => c + 1) + const totalMs = IDLE_HOLD_MS + (TOTAL_STAMPED_PILLS - 1) * PILL_STEP_MS + SCHEDULED_HOLD_MS + return { + timers: [ + ...Array.from({ length: TOTAL_STAMPED_PILLS }, (_, i) => + setTimeout(() => setStampedCount(i + 1), IDLE_HOLD_MS + i * PILL_STEP_MS) + ), + setTimeout(() => setFading(true), totalMs - RESET_FADE_MS), + ], + totalMs, + } + }, + showFinished: () => { + setFading(false) + setStampedCount(TOTAL_STAMPED_PILLS) + }, + }) + + return ( + +
+
+ +
+
+
+ ) +} diff --git a/apps/sim/app/(landing)/scheduled-tasks/components/scheduled-tasks-hero-loop.tsx b/apps/sim/app/(landing)/scheduled-tasks/components/scheduled-tasks-hero-loop.tsx deleted file mode 100644 index ef0ccaaf3c7..00000000000 --- a/apps/sim/app/(landing)/scheduled-tasks/components/scheduled-tasks-hero-loop.tsx +++ /dev/null @@ -1,117 +0,0 @@ -'use client' - -import { AgentIcon, GmailIcon, GoogleSheetsIcon, ScheduleIcon, SlackIcon } from '@/components/icons' -import { EditorLoop, type EditorLoopContent } from '@/app/(landing)/components/shared/editor-loop' - -/** - * The scheduled-tasks hero's content for the shared {@link EditorLoop}: a - * recurring-ops workspace sidebar and the complete scheduled digest workflow - - * a schedule trigger holding the cadence, the digest agent, and a three-way - * fan-out to Slack, Gmail, and Sheets. The schedule trigger is the block the - * "editing" beat selects, since the cadence is this page's story. Colors - * follow the stage convention - grey ramp for platform blocks, brand tiles - * only for real third-party marks (multicolor Gmail/Sheets glyphs sit on - * white tiles with a hairline, the Jira treatment). Blocks are ordered by - * build sequence; an edge draws once both endpoints are on canvas. - */ -const SCHEDULED_TASKS_EDITOR_CONTENT: EditorLoopContent = { - activeNav: 'Scheduled tasks', - sidebarChats: [ - 'Morning digest setup', - 'Move sync to nightly', - 'Weekly KPI report', - 'Retry failed runs', - ], - sidebarWorkflows: [ - 'Morning digest', - 'Nightly data sync', - 'Weekly KPI report', - 'Invoice sweep', - 'Churn-risk alerts', - ], - blocks: [ - { - id: 'schedule', - name: 'Schedule', - icon: ScheduleIcon, - bgColor: 'var(--text-muted)', - isTrigger: true, - rows: [ - { title: 'Cadence', value: 'Weekdays' }, - { title: 'Time', value: '9:00 AM PT' }, - ], - x: 555, - y: 20, - }, - { - id: 'agent', - name: 'Digest agent', - icon: AgentIcon, - bgColor: 'var(--text-primary)', - rows: [ - { title: 'Messages', value: '-' }, - { title: 'Model', value: '-' }, - ], - x: 555, - y: 280, - }, - { - id: 'slack', - name: 'Post to Slack', - icon: SlackIcon, - bgColor: '#611F69', - isTerminal: true, - rows: [ - { title: 'Channel', value: '-' }, - { title: 'Message', value: '-' }, - ], - x: 100, - y: 560, - }, - { - id: 'gmail', - name: 'Send by email', - icon: GmailIcon, - bgColor: '#FFFFFF', - tileBorder: true, - isTerminal: true, - rows: [ - { title: 'To', value: '-' }, - { title: 'Subject', value: '-' }, - ], - x: 555, - y: 560, - }, - { - id: 'sheets', - name: 'Append to Sheets', - icon: GoogleSheetsIcon, - bgColor: '#FFFFFF', - tileBorder: true, - isTerminal: true, - rows: [ - { title: 'Spreadsheet', value: '-' }, - { title: 'Range', value: '-' }, - ], - x: 1010, - y: 560, - }, - ], - edges: [ - ['schedule', 'agent'], - ['agent', 'slack'], - ['agent', 'gmail'], - ['agent', 'sheets'], - ], - canvas: { width: 1360, height: 780 }, - selectedBlockId: 'schedule', -} - -/** - * The scheduled-tasks hero's editor loop - the shared {@link EditorLoop} - * replaying the morning-digest workflow with the schedule trigger as the - * "being edited" beat, the cadence being this page's story. - */ -export function ScheduledTasksHeroLoop() { - return -} diff --git a/apps/sim/app/(landing)/scheduled-tasks/scheduled-tasks.tsx b/apps/sim/app/(landing)/scheduled-tasks/scheduled-tasks.tsx index 6a862acccc3..8a8113f25f3 100644 --- a/apps/sim/app/(landing)/scheduled-tasks/scheduled-tasks.tsx +++ b/apps/sim/app/(landing)/scheduled-tasks/scheduled-tasks.tsx @@ -10,7 +10,7 @@ import { OperationsTeamsGraphic, RunMonitoringGraphic, } from '@/app/(landing)/enterprise/components/feature-graphics' -import { ScheduledTasksHeroLoop } from '@/app/(landing)/scheduled-tasks/components/scheduled-tasks-hero-loop' +import { ScheduledTasksCalendarLoop } from '@/app/(landing)/scheduled-tasks/components/scheduled-tasks-calendar-loop' import { DocumentDraftGraphic } from '@/app/(landing)/solutions/components/feature-graphics' /** @@ -21,7 +21,9 @@ import { DocumentDraftGraphic } from '@/app/(landing)/solutions/components/featu * schedule triggers (from every-15-minutes intervals through daily, weekly, * and monthly cadences to custom cron, timezone-aware), and the workspace's * Scheduled Tasks calendar shows every upcoming and finished run with - * pause/resume and full run history. Every visual slot reuses a + * pause/resume and full run history. The hero replays that calendar itself - + * the month grid filling with recurring task pills as a new schedule lands + * on its cadence. Every card visual slot reuses a * parametrized enterprise feature graphic retold for recurring runs - the * policy checklist as a schedule card, the routing fan as the delivery * fan-out, the drafted document as the digest that arrives on time, the @@ -42,7 +44,7 @@ const SCHEDULED_TASKS_CONFIG: SolutionsPageConfig = { 'Scheduled Tasks is the scheduler in Sim, the open-source AI workspace where teams build, deploy, and manage AI agents. Put any workflow on a cadence, from 15-minute intervals to daily, weekly, and monthly runs or custom cron, timezone-aware, then watch every scheduled run land on the workspace calendar with full run history.', visual: ( - + ), }, diff --git a/apps/sim/app/(landing)/solutions/sales/components/sales-hero-loop.tsx b/apps/sim/app/(landing)/solutions/sales/components/sales-hero-loop.tsx new file mode 100644 index 00000000000..27355ac0b4a --- /dev/null +++ b/apps/sim/app/(landing)/solutions/sales/components/sales-hero-loop.tsx @@ -0,0 +1,125 @@ +'use client' + +import { + AgentIcon, + ConditionalIcon, + SalesforceIcon, + SlackIcon, + StartIcon, +} from '@/components/icons' +import { EnterprisePlatformLoop } from '@/app/(landing)/enterprise/components/enterprise-platform-loop' +import type { EnterpriseLoopContent } from '@/app/(landing)/enterprise/components/enterprise-platform-loop/stage-data' + +/** + * Sales content for the shared platform loop - an inbound-lead agent: the + * prompt asks for lead research, fit scoring, and Salesforce record creation + * with a Slack alert to the owner, the sidebar reads like the sales team's + * Brightwave workspace, and the staged workflow builds the routing flow on + * the enterprise stage geometry. The Salesforce mark is a colored brand + * mark, so its tile follows the Jira convention - the real mark on a + * hairlined white tile. + */ +const SALES_LOOP_CONTENT: EnterpriseLoopContent = { + workspaceName: 'Brightwave Sales', + greeting: 'What should we get done, Marcus?', + placeholder: 'Ask Sim to automate a process.', + prompt: + 'When a new lead comes in, research the company, score the fit, create the record in Salesforce, and alert the account owner in Slack.', + reply: + "On it. I'll research every new lead, score the fit against your best customers, create the Salesforce record, and alert the owner in Slack.", + sidebarChats: [ + 'Inbound lead backlog', + 'Acme Co renewal prep', + 'Q3 forecast review', + 'Stale opportunity cleanup', + ], + sidebarWorkflows: [ + 'Lead research', + 'Inbound routing', + 'CRM hygiene', + 'Meeting prep briefs', + 'Weekly pipeline digest', + ], + suggestedActions: [ + 'Research this week\u2019s inbound leads', + 'Update stale opportunities', + 'Draft follow-ups from yesterday\u2019s calls', + 'Summarize the Q3 pipeline', + ], + stageBlocks: [ + { + id: 'start', + name: 'Start', + icon: StartIcon, + bgColor: 'var(--text-muted)', + isTrigger: true, + rows: [{ title: 'Inputs', value: '-' }], + x: 155, + y: 12, + }, + { + id: 'research', + name: 'Research lead', + icon: AgentIcon, + bgColor: 'var(--text-primary)', + rows: [ + { title: 'Messages', value: '-' }, + { title: 'Model', value: '-' }, + ], + x: 155, + y: 172, + }, + { + id: 'score', + name: 'Score the fit', + icon: ConditionalIcon, + bgColor: 'var(--text-secondary)', + rows: [{ title: 'Conditions', value: '-' }], + x: 155, + y: 372, + }, + { + id: 'salesforce', + name: 'Create in Salesforce', + icon: SalesforceIcon, + bgColor: '#FFFFFF', + tileBorder: true, + isTerminal: true, + rows: [ + { title: 'Object', value: '-' }, + { title: 'Action', value: '-' }, + ], + x: 0, + y: 560, + }, + { + id: 'notify', + name: 'Alert owner', + icon: SlackIcon, + bgColor: '#611F69', + isTerminal: true, + rows: [ + { title: 'Channel', value: '-' }, + { title: 'Message', value: '-' }, + ], + x: 310, + y: 560, + }, + ], + stageEdges: [ + ['start', 'research'], + ['research', 'score'], + ['score', 'salesforce'], + ['score', 'notify'], + ], + stageCanvas: { width: 560, height: 680 }, +} + +/** + * The sales hero's platform loop - the shared enterprise loop replayed with + * the inbound-lead story above. Client wrapper so the icon-bearing content + * object never crosses a server/client boundary. + */ +export function SalesHeroLoop() { + return +} diff --git a/apps/sim/app/(landing)/solutions/sales/page.tsx b/apps/sim/app/(landing)/solutions/sales/page.tsx new file mode 100644 index 00000000000..15b36cec945 --- /dev/null +++ b/apps/sim/app/(landing)/solutions/sales/page.tsx @@ -0,0 +1,21 @@ +import { buildLandingMetadata } from '@/lib/landing/seo' +import SalesSolution from '@/app/(landing)/solutions/sales/sales' + +export const revalidate = 3600 + +const TITLE = 'AI Agents for Lead Research & CRM Updates | Sim' +const DESCRIPTION = + 'Sales teams use Sim, the open-source AI workspace, to build and deploy AI agents that automate lead research, personalized outreach, and CRM updates.' + +export const metadata = buildLandingMetadata({ + title: TITLE, + description: DESCRIPTION, + path: '/solutions/sales', + keywords: + 'AI workspace, AI agents for sales, sales automation, lead research, CRM automation, pipeline reporting, open-source AI agent platform', + twitterImageAlt: 'Sim', +}) + +export default function Page() { + return +} diff --git a/apps/sim/app/(landing)/solutions/sales/sales.tsx b/apps/sim/app/(landing)/solutions/sales/sales.tsx new file mode 100644 index 00000000000..5fb08b5d3c8 --- /dev/null +++ b/apps/sim/app/(landing)/solutions/sales/sales.tsx @@ -0,0 +1,159 @@ +import { + PlatformHeroVisual, + SolutionsPage, + type SolutionsPageConfig, +} from '@/app/(landing)/components' +import { + ItPlatformTeamsGraphic, + OperationsTeamsGraphic, + RunMonitoringGraphic, + StagingGraphic, +} from '@/app/(landing)/enterprise/components/feature-graphics' +import { + DocumentDraftGraphic, + KnowledgeAnswerGraphic, +} from '@/app/(landing)/solutions/components/feature-graphics' +import { SalesHeroLoop } from '@/app/(landing)/solutions/sales/components/sales-hero-loop' + +/** + * Sales solution page - a consumer of {@link SolutionsPage} rendered with + * the enterprise page's feature-tile treatment. + * + * The whole page is one typed {@link SolutionsPageConfig} rendered inside + * the shared route-group layout's chrome. Every visual slot carries a + * feature graphic in the enterprise design language, retold through the + * graphics' content props for sales' use cases - inbound lead routing + * across systems, a research brief grounded in real account context, + * outreach drafting, CRM stage updates, meeting prep, and the pipeline + * digest. + */ +const SALES_CONFIG: SolutionsPageConfig = { + module: 'Sales', + path: '/solutions/sales', + hero: { + eyebrow: 'Sales', + heading: 'Automate lead research, outreach, and CRM updates with Sim agents.', + description: + 'Sales teams build AI agents in Sim, the open-source AI workspace, wired into Salesforce, HubSpot, and 1,000+ integrations, so reps spend their time selling, not updating records.', + summary: + 'Sim is the open-source AI workspace where sales teams build, deploy, and manage AI agents that automate lead research, personalized outreach, and CRM updates, wired into Salesforce, HubSpot, and 1,000+ integrations so the pipeline stays current and reps spend their time selling.', + visual: ( + + + + ), + }, + rows: [ + { + id: 'pipeline', + title: 'Fill the pipeline.', + subtitle: 'Sim agents handle research, outreach, and follow-up around the clock.', + cta: { label: 'See sales agents', href: '/signup' }, + cards: [ + { + title: 'Route inbound leads', + description: 'Sim scores, routes, and follows up on new leads the moment they arrive.', + featureTileTone: 'dark', + featureTileDescriptionTone: 'soft', + visual: ( + + ), + }, + { + title: 'Research every lead', + description: + 'Sim researches the company, the news, and the stack, and writes the brief before you call.', + visual: ( + + ), + }, + { + title: 'Draft outreach', + description: + 'Sim drafts personalized outbound from the research, in your voice, ready to send.', + visual: ( + + ), + }, + ], + }, + { + id: 'crm', + title: 'Keep the CRM true.', + subtitle: 'Sim keeps records current so the forecast is built on real data.', + cta: { label: 'Explore CRM automation', href: '/signup' }, + cards: [ + { + title: 'Update the CRM', + description: 'Sim logs calls, sets next steps, and moves stages after every touchpoint.', + visual: ( + + ), + }, + { + title: 'Prep every meeting', + description: 'Sim assembles a brief before every call from your CRM, email, and notes.', + visual: ( + + ), + }, + { + title: 'Report the pipeline', + description: 'Sim assembles pipeline and forecast digests from your CRM on schedule.', + visual: ( + + ), + }, + ], + }, + ], +} + +export default function SalesSolution() { + return +} diff --git a/apps/sim/app/sitemap.ts b/apps/sim/app/sitemap.ts index e05670f1cfc..b468d883742 100644 --- a/apps/sim/app/sitemap.ts +++ b/apps/sim/app/sitemap.ts @@ -104,6 +104,9 @@ export default async function sitemap(): Promise { { url: `${baseUrl}/solutions/it`, }, + { + url: `${baseUrl}/solutions/sales`, + }, { url: `${baseUrl}/blog`, lastModified: latestPostDateValue,