From 7b0aaec3c4d7d33aa31aff126c5ac47435516db6 Mon Sep 17 00:00:00 2001 From: waleed Date: Sun, 30 Nov 2025 10:19:00 -0800 Subject: [PATCH 1/2] feat(statuspage): added statuspage, updated list of tools in footer, renamed routes --- apps/sim/app/(landing)/actions/github.ts | 4 +- .../footer/components/compliance-badges.tsx | 26 ++ .../components/footer/components/index.ts | 6 + .../components/footer/components/logo.tsx | 17 ++ .../footer/components/social-links.tsx | 44 ++++ .../footer/components/status-indicator.tsx | 72 +++++ .../app/(landing)/components/footer/consts.ts | 96 +++++++ .../(landing)/components/footer/footer.tsx | 249 ++++-------------- apps/sim/app/(landing)/components/nav/nav.tsx | 2 +- .../app/api/{github-stars => stars}/route.ts | 0 apps/sim/app/api/status/route.ts | 94 +++++++ apps/sim/app/api/status/types.ts | 48 ++++ .../app/api/{wand-generate => wand}/route.ts | 0 .../w/[workflowId]/hooks/use-wand.ts | 2 +- apps/sim/components/icons.tsx | 52 +++- apps/sim/lib/logs/get-trigger-options.ts | 10 +- apps/sim/lib/logs/search-suggestions.ts | 11 +- 17 files changed, 508 insertions(+), 225 deletions(-) create mode 100644 apps/sim/app/(landing)/components/footer/components/compliance-badges.tsx create mode 100644 apps/sim/app/(landing)/components/footer/components/index.ts create mode 100644 apps/sim/app/(landing)/components/footer/components/logo.tsx create mode 100644 apps/sim/app/(landing)/components/footer/components/social-links.tsx create mode 100644 apps/sim/app/(landing)/components/footer/components/status-indicator.tsx create mode 100644 apps/sim/app/(landing)/components/footer/consts.ts rename apps/sim/app/api/{github-stars => stars}/route.ts (100%) create mode 100644 apps/sim/app/api/status/route.ts create mode 100644 apps/sim/app/api/status/types.ts rename apps/sim/app/api/{wand-generate => wand}/route.ts (100%) diff --git a/apps/sim/app/(landing)/actions/github.ts b/apps/sim/app/(landing)/actions/github.ts index efd28a2124d..527f29ea442 100644 --- a/apps/sim/app/(landing)/actions/github.ts +++ b/apps/sim/app/(landing)/actions/github.ts @@ -1,12 +1,12 @@ import { createLogger } from '@/lib/logs/console/logger' -const DEFAULT_STARS = '15.4k' +const DEFAULT_STARS = '18.6k' const logger = createLogger('GitHubStars') export async function getFormattedGitHubStars(): Promise { try { - const response = await fetch('/api/github-stars', { + const response = await fetch('/api/stars', { headers: { 'Cache-Control': 'max-age=3600', // Cache for 1 hour }, diff --git a/apps/sim/app/(landing)/components/footer/components/compliance-badges.tsx b/apps/sim/app/(landing)/components/footer/components/compliance-badges.tsx new file mode 100644 index 00000000000..3288fee422f --- /dev/null +++ b/apps/sim/app/(landing)/components/footer/components/compliance-badges.tsx @@ -0,0 +1,26 @@ +import Image from 'next/image' +import Link from 'next/link' +import { HIPAABadgeIcon } from '@/components/icons' + +export default function ComplianceBadges() { + return ( +
+ {/* SOC2 badge */} + + SOC2 Compliant + + {/* HIPAA badge */} + + + +
+ ) +} diff --git a/apps/sim/app/(landing)/components/footer/components/index.ts b/apps/sim/app/(landing)/components/footer/components/index.ts new file mode 100644 index 00000000000..2f9863a65e1 --- /dev/null +++ b/apps/sim/app/(landing)/components/footer/components/index.ts @@ -0,0 +1,6 @@ +import ComplianceBadges from './compliance-badges' +import Logo from './logo' +import SocialLinks from './social-links' +import StatusIndicator from './status-indicator' + +export { ComplianceBadges, Logo, SocialLinks, StatusIndicator } diff --git a/apps/sim/app/(landing)/components/footer/components/logo.tsx b/apps/sim/app/(landing)/components/footer/components/logo.tsx new file mode 100644 index 00000000000..f9c2ec12cde --- /dev/null +++ b/apps/sim/app/(landing)/components/footer/components/logo.tsx @@ -0,0 +1,17 @@ +import Image from 'next/image' +import Link from 'next/link' + +export default function Logo() { + return ( + + Sim - Workflows for LLMs + + ) +} diff --git a/apps/sim/app/(landing)/components/footer/components/social-links.tsx b/apps/sim/app/(landing)/components/footer/components/social-links.tsx new file mode 100644 index 00000000000..ccc6ef8d70b --- /dev/null +++ b/apps/sim/app/(landing)/components/footer/components/social-links.tsx @@ -0,0 +1,44 @@ +import { DiscordIcon, GithubIcon, LinkedInIcon, xIcon as XIcon } from '@/components/icons' + +export default function SocialLinks() { + return ( +
+ + + + + + + + +
+ ) +} diff --git a/apps/sim/app/(landing)/components/footer/components/status-indicator.tsx b/apps/sim/app/(landing)/components/footer/components/status-indicator.tsx new file mode 100644 index 00000000000..f1a245517a6 --- /dev/null +++ b/apps/sim/app/(landing)/components/footer/components/status-indicator.tsx @@ -0,0 +1,72 @@ +'use client' + +import { useCallback, useEffect, useState } from 'react' +import Link from 'next/link' +import { StatusDotIcon } from '@/components/icons' +import type { StatusResponse, StatusType } from '@/app/api/status/types' + +const POLLING_INTERVAL = 60000 + +const STATUS_COLORS: Record = { + operational: 'text-[#10B981] hover:text-[#059669]', + degraded: 'text-[#F59E0B] hover:text-[#D97706]', + outage: 'text-[#EF4444] hover:text-[#DC2626]', + maintenance: 'text-[#3B82F6] hover:text-[#2563EB]', + loading: 'text-muted-foreground hover:text-foreground', + error: 'text-muted-foreground hover:text-foreground', +} + +export default function StatusIndicator() { + const [status, setStatus] = useState('loading') + const [message, setMessage] = useState('Checking Status...') + const [statusUrl, setStatusUrl] = useState('https://status.sim.ai') + + const fetchStatus = useCallback(async () => { + try { + const response = await fetch('/api/status') + + if (!response.ok) { + throw new Error('Failed to fetch status') + } + + const data: StatusResponse = await response.json() + + setStatus(data.status) + setMessage(data.message) + setStatusUrl(data.url) + } catch (error) { + console.error('Error fetching status:', error) + setStatus('error') + setMessage('Status Unknown') + } + }, []) + + useEffect(() => { + fetchStatus() + + const poll = () => { + fetchStatus().finally(() => { + setTimeout(poll, POLLING_INTERVAL) + }) + } + + const timeoutId = setTimeout(poll, POLLING_INTERVAL) + + return () => { + clearTimeout(timeoutId) + } + }, [fetchStatus]) + + return ( + +