mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
feat(branding): sim wordmark favicon/OG, docs footer parity, footer peel (#5587)
* feat(branding): sim wordmark favicon/OG, docs footer parity, footer peel - replace apps/sim favicon and default OG image with the sim wordmark logo (OG image widened, logo kept at native size) - swap the docs navbar logo to the icon-only mark (no wordmark text) - add a scroll "peel" reveal effect to the landing footer using a sticky-positioned illustration, pure CSS, no scroll listeners - port the same footer (link directory + peel effect) to the docs app so both apps are visually consistent; add Academy to Resources - rebuild the docs OG image template to match the site's existing blog/library cover style (wordmark top-left, arrow top-right, title bottom-left), working around a Satori text-measurement bug that doubled the gap after certain words * fix(docs): correct OG font, mobile logo, and footer stacking - switch the docs OG image title font from Geist to the site's real brand font (Season Sans), instantiated as a static TTF weight since Satori can't parse WOFF2 or variable fonts; served from /static/ so the i18n proxy's matcher (which excludes static but not fonts) doesn't intercept it - fix DocsLayout's nav.title (fumadocs' own mobile menu slot) to show the wordmark instead of the icon mark - add an isolated stacking context + higher z-index to both the docs and sim app footers so fumadocs' sticky z-20 sidebar can't paint over the footer content or the peel reveal * fix(docs): match OG template exactly, fix gradient/origin bugs - recalibrate the OG image to the reference cover template's actual measured values: 1200x675 canvas (was 630), ~26px margins (was 56-64px), ink #525252 (was #3f3f3f), larger wordmark/arrow/title sizing — confirmed by direct pixel measurement of the reference cover.jpg, not estimation - fix SimLogoIcon/SimLogoFull's SVG gradient ids to be unique via useId() instead of a fixed string, so multiple instances on one page don't collide (Greptile P2) - fix SIM_SITE_URL to be a hardcoded sim.ai constant instead of deriving from NEXT_PUBLIC_APP_URL, which reflects wherever this deployment runs, not the fixed public marketing site (Greptile P1) * fix(docs): route Jira footer link to the docs guide, not sim.ai Every other integration in the footer's Integrations column links to its own docs.sim.ai guide; Jira was the only one pointing at the marketing site's landing page instead, despite docs having its own /integrations/jira guide. Matches the established pattern. * fix(docs): fix sidebar-divider grid regression, footer-peel path/positioning, OG sizing, and prune stray comments - #nd-docs-layout::before divider now spans the full grid explicitly (grid-row/grid-column: 1 / -1) instead of being auto-placed into a real content cell, which was pushing page content down - footer-peel.jpg moved under /static/landing/ (was 404ing behind the i18n proxy's non-static path matcher) and wrapped in a relative div so next/image's fill positioning is valid under the sticky container - OG route: corrected title font sizes and char-width ratio so long titles wrap to 2 lines instead of 3, and resized the corner arrow to match the reference cover template's proportions - swapped the icon-only desktop navbar logo back to the wordmark - removed stray non-TSDoc comments, folded into TSDoc where the explanation was worth keeping * fix(footer): remove sticky peel reveal, keep clean footer link directory The peel's "reveal window" relied on position: sticky bottom-detaching into a containing block whose extra height came from padding-bottom — that combination doesn't reliably work in WebKit/Safari (sticky never gets room to engage when the surplus height is padding rather than an explicit height or content), so the peel stayed permanently covered by the footer regardless of viewport size. Rather than carry that unreliable technique further, removing it entirely from both apps and reverting to the plain footer link directory.
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
import Link from 'next/link'
|
||||
import { SimWordmark } from '@/components/ui/sim-logo'
|
||||
import { SIM_SITE_URL } from '@/lib/urls'
|
||||
|
||||
/**
|
||||
* Docs footer - the same site link directory as the main app's landing
|
||||
* footer (`apps/sim/app/(landing)/components/footer`), ported here so both
|
||||
* apps share one consistent footer. Links that live on sim.ai are absolute
|
||||
* (docs.sim.ai is a different origin); links that live on docs.sim.ai itself
|
||||
* (Academy, API Reference, blocks, integrations guides, …) stay relative.
|
||||
*/
|
||||
|
||||
const LINK_CLASS =
|
||||
'text-sm text-[var(--text-muted)] transition-colors hover:text-[var(--text-primary)]'
|
||||
|
||||
interface FooterItem {
|
||||
label: string
|
||||
href: string
|
||||
external?: boolean
|
||||
}
|
||||
|
||||
const PRODUCT_LINKS: FooterItem[] = [
|
||||
{ label: 'Enterprise', href: `${SIM_SITE_URL}/enterprise`, external: true },
|
||||
{ label: 'Mothership', href: '/mothership' },
|
||||
{ label: 'Workflows', href: '/introduction' },
|
||||
{ label: 'Knowledge Base', href: '/knowledgebase' },
|
||||
{ label: 'Tables', href: '/tables' },
|
||||
{ label: 'MCP', href: '/agents/mcp' },
|
||||
{ label: 'API', href: '/api-reference/getting-started' },
|
||||
{ label: 'Self Hosting', href: '/platform/self-hosting' },
|
||||
{ label: 'Status', href: 'https://status.sim.ai', external: true },
|
||||
]
|
||||
|
||||
const RESOURCES_LINKS: FooterItem[] = [
|
||||
{ label: 'Blog', href: `${SIM_SITE_URL}/blog`, external: true },
|
||||
{ label: 'Academy', href: '/academy' },
|
||||
{ label: 'Compare', href: `${SIM_SITE_URL}/comparison`, external: true },
|
||||
{ label: 'Careers', href: `${SIM_SITE_URL}/careers`, external: true },
|
||||
{ label: 'Changelog', href: `${SIM_SITE_URL}/changelog`, external: true },
|
||||
{ label: 'Contact', href: `${SIM_SITE_URL}/contact`, external: true },
|
||||
]
|
||||
|
||||
/** Top model providers — mirrors the landing footer's top 8 catalog providers. */
|
||||
const MODEL_LINKS: FooterItem[] = [
|
||||
{ label: 'All Models', href: `${SIM_SITE_URL}/models`, external: true },
|
||||
{ label: 'OpenAI', href: `${SIM_SITE_URL}/models/openai`, external: true },
|
||||
{ label: 'Anthropic', href: `${SIM_SITE_URL}/models/anthropic`, external: true },
|
||||
{ label: 'Google', href: `${SIM_SITE_URL}/models/google`, external: true },
|
||||
{ label: 'DeepSeek', href: `${SIM_SITE_URL}/models/deepseek`, external: true },
|
||||
{ label: 'xAI', href: `${SIM_SITE_URL}/models/xai`, external: true },
|
||||
{ label: 'Cerebras', href: `${SIM_SITE_URL}/models/cerebras`, external: true },
|
||||
{ label: 'Groq', href: `${SIM_SITE_URL}/models/groq`, external: true },
|
||||
{ label: 'Sakana AI', href: `${SIM_SITE_URL}/models/sakana`, external: true },
|
||||
]
|
||||
|
||||
const BLOCK_LINKS: FooterItem[] = [
|
||||
{ label: 'Agent', href: '/workflows/blocks/agent' },
|
||||
{ label: 'Router', href: '/workflows/blocks/router' },
|
||||
{ label: 'Function', href: '/workflows/blocks/function' },
|
||||
{ label: 'Condition', href: '/workflows/blocks/condition' },
|
||||
{ label: 'API Block', href: '/workflows/blocks/api' },
|
||||
{ label: 'Workflow', href: '/workflows/blocks/workflow' },
|
||||
{ label: 'Parallel', href: '/workflows/blocks/parallel' },
|
||||
{ label: 'Guardrails', href: '/workflows/blocks/guardrails' },
|
||||
{ label: 'Evaluator', href: '/workflows/blocks/evaluator' },
|
||||
{ label: 'Loop', href: '/workflows/blocks/loop' },
|
||||
]
|
||||
|
||||
const INTEGRATION_LINKS: FooterItem[] = [
|
||||
{ label: 'All Integrations', href: `${SIM_SITE_URL}/integrations`, external: true },
|
||||
{ label: 'Slack', href: '/integrations/slack' },
|
||||
{ label: 'GitHub', href: '/integrations/github' },
|
||||
{ label: 'Gmail', href: '/integrations/gmail' },
|
||||
{ label: 'Notion', href: '/integrations/notion' },
|
||||
{ label: 'Salesforce', href: '/integrations/salesforce' },
|
||||
{ label: 'Jira', href: '/integrations/jira' },
|
||||
{ label: 'Linear', href: '/integrations/linear' },
|
||||
{ label: 'Supabase', href: '/integrations/supabase' },
|
||||
{ label: 'Stripe', href: '/integrations/stripe' },
|
||||
]
|
||||
|
||||
const SOCIAL_LINKS: FooterItem[] = [
|
||||
{ label: 'X (Twitter)', href: 'https://x.com/simdotai', external: true },
|
||||
{
|
||||
label: 'LinkedIn',
|
||||
href: 'https://www.linkedin.com/company/simstudioai/',
|
||||
external: true,
|
||||
},
|
||||
{ label: 'Discord', href: 'https://discord.gg/Hr4UWYEcTT', external: true },
|
||||
{
|
||||
label: 'GitHub',
|
||||
href: 'https://github.com/simstudioai/sim',
|
||||
external: true,
|
||||
},
|
||||
]
|
||||
|
||||
const LEGAL_LINKS: FooterItem[] = [
|
||||
{ label: 'Terms of Service', href: `${SIM_SITE_URL}/terms`, external: true },
|
||||
{ label: 'Privacy Policy', href: `${SIM_SITE_URL}/privacy`, external: true },
|
||||
]
|
||||
|
||||
function FooterColumn({ title, items }: { title: string; items: FooterItem[] }) {
|
||||
return (
|
||||
<div>
|
||||
<h3 className='mb-4 text-[var(--text-primary)] text-sm'>{title}</h3>
|
||||
<div className='flex flex-col gap-2.5'>
|
||||
{items.map(({ label, href, external }) =>
|
||||
external ? (
|
||||
<a
|
||||
key={label}
|
||||
href={href}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
className={LINK_CLASS}
|
||||
>
|
||||
{label}
|
||||
</a>
|
||||
) : (
|
||||
<Link key={label} href={href} className={LINK_CLASS}>
|
||||
{label}
|
||||
</Link>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function Footer() {
|
||||
return (
|
||||
<footer className='mt-[120px] w-full border-[var(--border)] border-t bg-[var(--bg)] max-sm:mt-16 max-lg:mt-[88px]'>
|
||||
<div className='mx-auto w-full max-w-[1460px] px-20 pt-16 pb-16 max-sm:px-5 max-lg:px-8 max-lg:pt-12 max-lg:pb-12'>
|
||||
<nav
|
||||
aria-label='Footer navigation'
|
||||
itemScope
|
||||
itemType='https://schema.org/SiteNavigationElement'
|
||||
className='grid grid-cols-8 gap-x-8 gap-y-10 max-sm:grid-cols-2 max-sm:gap-y-8 max-lg:grid-cols-3'
|
||||
>
|
||||
<a
|
||||
href={SIM_SITE_URL}
|
||||
aria-label='Sim home'
|
||||
className='flex h-[18px] items-center max-lg:col-span-full max-lg:mb-2'
|
||||
>
|
||||
<SimWordmark />
|
||||
</a>
|
||||
|
||||
<FooterColumn title='Product' items={PRODUCT_LINKS} />
|
||||
<FooterColumn title='Resources' items={RESOURCES_LINKS} />
|
||||
<FooterColumn title='Blocks' items={BLOCK_LINKS} />
|
||||
<FooterColumn title='Integrations' items={INTEGRATION_LINKS} />
|
||||
<FooterColumn title='Models' items={MODEL_LINKS} />
|
||||
<FooterColumn title='Socials' items={SOCIAL_LINKS} />
|
||||
<FooterColumn title='Legal' items={LEGAL_LINKS} />
|
||||
</nav>
|
||||
|
||||
<p className='mt-16 text-[var(--text-muted)] text-sm'>© 2026 Sim. All rights reserved.</p>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import Link from 'next/link'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import { LanguageDropdown } from '@/components/ui/language-dropdown'
|
||||
import { SearchTrigger } from '@/components/ui/search-trigger'
|
||||
import { SimLogoFull } from '@/components/ui/sim-logo'
|
||||
import { SimWordmark } from '@/components/ui/sim-logo'
|
||||
import { ThemeToggle } from '@/components/ui/theme-toggle'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
@@ -44,8 +44,8 @@ export function Navbar() {
|
||||
paddingRight: 'calc(var(--toc-offset) + var(--nav-inset))',
|
||||
}}
|
||||
>
|
||||
<Link href='/' className='flex min-w-[100px] items-center'>
|
||||
<SimLogoFull className='h-[20px] w-auto' />
|
||||
<Link href='/' className='flex items-center'>
|
||||
<SimWordmark className='h-[18px]' />
|
||||
</Link>
|
||||
|
||||
<div className='-translate-x-1/2 absolute left-1/2 flex items-center justify-center'>
|
||||
|
||||
@@ -1,17 +1,93 @@
|
||||
'use client'
|
||||
|
||||
import { useId } from 'react'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
interface SimLogoProps {
|
||||
className?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Inline "sim" wordmark, no separate icon mark — same paths as the landing
|
||||
* footer's `SimWordmark` (`apps/sim/app/(landing)/components/navbar/components/sim-wordmark`),
|
||||
* ported here so the docs footer can match it exactly. Filled with
|
||||
* `var(--text-body)` so it reads as one solid ink matching surrounding text.
|
||||
*/
|
||||
export function SimWordmark({ className }: SimLogoProps) {
|
||||
return (
|
||||
<svg
|
||||
viewBox='0 0 441 212'
|
||||
width={37}
|
||||
height={18}
|
||||
fill='none'
|
||||
aria-hidden='true'
|
||||
className={cn('-translate-y-[1.5px] h-[18px] w-auto', className)}
|
||||
>
|
||||
<g fill='var(--text-body)'>
|
||||
<path d='M0 160.9H29.51C29.51 169.08 32.46 175.61 38.37 180.48C44.27 185.12 52.25 187.44 62.31 187.44C73.24 187.44 81.65 185.34 87.56 181.14C93.46 176.71 96.41 170.85 96.41 163.55C96.41 158.24 94.77 153.82 91.49 150.28C88.43 146.74 82.75 143.86 74.44 141.65L46.24 135.01C32.03 131.47 21.42 126.05 14.43 118.75C7.65 111.45 4.26 101.83 4.26 89.88C4.26 79.93 6.78 71.3 11.81 64C17.05 56.7 24.16 51.06 33.12 47.08C42.3 43.09 52.8 41.1 64.6 41.1C76.41 41.1 86.57 43.2 95.1 47.41C103.84 51.61 110.62 57.47 115.43 64.99C120.46 72.52 123.08 81.48 123.3 91.87H93.79C93.57 83.47 90.84 76.94 85.59 72.3C80.34 67.65 73.02 65.33 63.62 65.33C54 65.33 46.57 67.43 41.32 71.63C36.07 75.83 33.45 81.59 33.45 88.89C33.45 99.73 41.32 107.14 57.06 111.12L85.26 118.09C98.81 121.19 108.98 126.28 115.76 133.35C122.53 140.21 125.92 149.61 125.92 161.56C125.92 171.74 123.19 180.7 117.73 188.44C112.26 195.96 104.72 201.82 95.1 206.03C85.7 210.01 74.55 212 61.65 212C42.85 212 27.87 207.35 16.72 198.06C5.57 188.77 0 176.38 0 160.9Z' />
|
||||
<path d='M232.8 212H202.13L202.13 49.76H229.54V77.39C232.8 68.34 239.11 60.66 247.81 54.7C256.73 48.52 267.5 45.43 280.12 45.43C294.26 45.43 306.01 49.29 315.36 57.02C324.72 64.75 330.81 75.01 333.64 87.82H328.09C330.27 75.01 336.25 64.75 346.04 57.02C355.83 49.29 367.9 45.43 382.26 45.43C400.54 45.43 414.89 50.84 425.34 61.66C435.78 72.47 441 87.26 441 106.03V212H410.98V113.65C410.98 100.84 407.71 91.02 401.19 84.17C394.88 77.11 386.29 73.58 375.41 73.58C367.79 73.58 361.05 75.34 355.17 78.88C349.52 82.19 345.06 87.04 341.8 93.45C338.53 99.85 336.9 107.36 336.9 115.97V212H306.55V113.32C306.55 100.51 303.4 90.8 297.09 84.17C290.78 77.33 282.19 73.91 271.31 73.91C263.69 73.91 256.95 75.67 251.08 79.21C245.42 82.52 240.96 87.38 237.7 93.78C234.43 99.96 232.8 107.36 232.8 115.97V212Z' />
|
||||
<path d='M184.83 20.55C184.83 31.9 175.64 41.1 164.29 41.1C152.95 41.1 143.76 31.9 143.76 20.55C143.76 9.2 152.95 0 164.29 0C175.64 0 184.83 9.2 184.83 20.55Z' />
|
||||
<path d='M179.43 212H149.16V49.76C153.76 51.91 158.88 53.12 164.29 53.12C169.7 53.12 174.83 51.91 179.43 49.76V212Z' />
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Icon-only Sim mark, no wordmark text. Same brandbook icon geometry as
|
||||
* {@link SimLogoFull}'s icon, at its native square viewBox.
|
||||
*/
|
||||
export function SimLogoIcon({ className }: SimLogoProps) {
|
||||
const gradientId = `sim-logo-icon-gradient-${useId()}`
|
||||
|
||||
return (
|
||||
<svg
|
||||
viewBox='0 0 222 222'
|
||||
fill='none'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
className={cn('size-7', className)}
|
||||
aria-label='Sim'
|
||||
>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id={gradientId}
|
||||
gradientUnits='userSpaceOnUse'
|
||||
x1='129.434'
|
||||
y1='129.266'
|
||||
x2='185.629'
|
||||
y2='185.33'
|
||||
>
|
||||
<stop offset='0' />
|
||||
<stop offset='1' stopOpacity='0' />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path
|
||||
clipRule='evenodd'
|
||||
d='m107.822 93.7612c0 3.5869-1.419 7.0308-3.938 9.5668l-.361.364c-2.517 2.544-5.9375 3.966-9.4994 3.966h-80.5781c-7.42094 0-13.4455 6.06-13.4455 13.533v87.141c0 7.474 6.02456 13.534 13.4455 13.534h86.5167c7.4208 0 13.4378-6.06 13.4378-13.534v-81.587c0-3.326 1.31-6.517 3.647-8.871 2.33-2.347 5.499-3.667 8.802-3.667h81.928c7.421 0 13.437-6.059 13.437-13.533v-87.1407c0-7.47374-6.016-13.5333-13.437-13.5333h-86.517c-7.421 0-13.438 6.05956-13.438 13.5333zm26.256-75.2112h60.874c4.337 0 7.844 3.5393 7.844 7.9003v61.3071c0 4.3604-3.507 7.9003-7.844 7.9003h-60.874c-4.33 0-7.845-3.5399-7.845-7.9003v-61.3071c0-4.361 3.515-7.9003 7.845-7.9003z'
|
||||
fill='#33C482'
|
||||
fillRule='evenodd'
|
||||
/>
|
||||
<path
|
||||
d='m207.878 129.57h-64.324c-7.798 0-14.12 6.367-14.12 14.221v63.993c0 7.854 6.322 14.221 14.12 14.221h64.324c7.799 0 14.121-6.367 14.121-14.221v-63.993c0-7.854-6.322-14.221-14.121-14.221z'
|
||||
fill='#33C482'
|
||||
/>
|
||||
<path
|
||||
d='m207.878 129.266h-64.324c-7.798 0-14.12 6.366-14.12 14.221v63.992c0 7.854 6.322 14.22 14.12 14.22h64.324c7.799 0 14.121-6.366 14.121-14.22v-63.992c0-7.855-6.322-14.221-14.121-14.221z'
|
||||
fill={`url(#${gradientId})`}
|
||||
fillOpacity='0.2'
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Full Sim logo with icon and "Sim" text.
|
||||
* Uses the same SVG source as the landing page navbar for exact visual alignment.
|
||||
* The icon stays green (#33C482), text adapts to light/dark mode.
|
||||
*/
|
||||
export function SimLogoFull({ className }: SimLogoProps) {
|
||||
const gradientId = `sim-logo-full-gradient-${useId()}`
|
||||
|
||||
return (
|
||||
<svg
|
||||
viewBox='0 0 71 22'
|
||||
@@ -22,7 +98,7 @@ export function SimLogoFull({ className }: SimLogoProps) {
|
||||
>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id='sim-logo-full-gradient'
|
||||
id={gradientId}
|
||||
gradientUnits='userSpaceOnUse'
|
||||
x1='171.406'
|
||||
y1='171.18'
|
||||
@@ -47,7 +123,7 @@ export function SimLogoFull({ className }: SimLogoProps) {
|
||||
/>
|
||||
<path
|
||||
d='m275.293 171.18h-85.187c-10.327 0-18.7 8.432-18.7 18.834v84.749c0 10.402 8.373 18.833 18.7 18.833h85.187c10.328 0 18.701-8.431 18.701-18.833v-84.749c0-10.402-8.373-18.834-18.701-18.834z'
|
||||
fill='url(#sim-logo-full-gradient)'
|
||||
fill={`url(#${gradientId})`}
|
||||
fillOpacity='0.2'
|
||||
/>
|
||||
</g>
|
||||
|
||||
Reference in New Issue
Block a user