diff --git a/website/CLAUDE.md b/website/CLAUDE.md index 3997a5f1b0..6c1e71798b 100644 --- a/website/CLAUDE.md +++ b/website/CLAUDE.md @@ -61,3 +61,19 @@ Import from `@rivet-gg/icons`. The full Font Awesome Pro library is available. C - Do not split related multi-file examples into separate non-workspace code blocks. - If any code block fails type checking, the build fails. + +## Typography + +- Marketing headings and card titles use `font-medium` (h1 heroes, section h2s, h3/h4 card titles, FAQ headings, price figures). Do not introduce `font-normal` headings. +- `font-normal` remains correct only for deliberate de-emphasis: table `th` de-bolding, quiet `dt` labels, and input-like UI (TypesenseSearch). +- Hero h1s and section h2s use the class constants in `src/components/marketing/typography.tsx` (`tracking-[-0.015em]`, h1 `leading-[1.06]`). Do not hand-write `tracking-tight` on headings at `text-2xl` or larger; `tracking-tight` stays acceptable on `text-base` and smaller card titles. +- Manrope is the only marketing typeface; JetBrains Mono covers code, eyebrows, and captions. No serif headings on marketing pages; the Learn section's serif treatment is the only exception. +- Section labels use the eyebrow convention (`EYEBROW_CLASS` or `editorial/Eyebrow`): mono, uppercase, `tracking-[0.18em]`, pine on porcelain, sage inside ink panels. Plate and panel captions use `CAPTION_CLASS` (`Fig. NN — ...`). + +## Theme + +- Marketing pages and docs are light: cool porcelain (`paper`, `#EFEFEF`) with a `paper-deep` radial pooling bottom-left (`.depth-wash`) and a fine grain (`.paper-grain`). Warmth comes from warm-black `ink` text, classical imagery, and oil-paint textures, never from synthetic color gradients. Do not use the cream `mat` token as a surface/background design element on light surfaces (panels, dropdowns, badges, plate frames); use `paper`/`paper-mid`/`white` or `ink`-tint neutrals instead. `cream` stays valid only as the off-white text/fill inside dark `ink` panels. Docs paint the same porcelain field, render prose via `Prose surface="paper"`, and use `pine` for the active sidebar/TOC selected state; only the Learn section keeps a dark shell, and no other page may introduce a dark base. +- Dark `ink` panels (`editorial/InkPanel`) are reserved for code, terminal, screenshot, and data moments. Code and data plates stay flat ink; the oil-texture backdrop (`textureSrc`) is for editorial moments only (CTA colophon, 404). +- Orange is the spark: at most one `accent`/ember CTA per page. White text sits only on `accent-deep` (`#D63E00`) or `ink` fills, never on `accent`. Pine (`#2E4034`) is the structural color for links, eyebrows, diagrams, and selected states; sage (`#93A286`) replaces it inside ink panels. +- No drop shadows on marketing cards or imagery; depth comes from `border-ink/10..25` hairlines, `bg-white/55` card fills, and `paper-mid`/`paper-deep` layering (inside ink panels: `border-cream/10..15`). Shadows stay acceptable on functional overlays (dropdowns, tooltips, modals) and the header's glass inset highlight. +- `ink-faint` text is for captions and metadata at 12px+; body copy uses `ink-soft` or `ink`. diff --git a/website/public/fonts/jetbrains-mono/JetBrainsMono-Variable-latin.woff2 b/website/public/fonts/jetbrains-mono/JetBrainsMono-Variable-latin.woff2 new file mode 100644 index 0000000000..c3f0666ea8 Binary files /dev/null and b/website/public/fonts/jetbrains-mono/JetBrainsMono-Variable-latin.woff2 differ diff --git a/website/public/fonts/manrope/Manrope-Variable-latin.woff2 b/website/public/fonts/manrope/Manrope-Variable-latin.woff2 new file mode 100644 index 0000000000..9d7abb17d3 Binary files /dev/null and b/website/public/fonts/manrope/Manrope-Variable-latin.woff2 differ diff --git a/website/public/images/textures/bruegel-childrens-games-hero.jpg b/website/public/images/textures/bruegel-childrens-games-hero.jpg new file mode 100644 index 0000000000..ac91d45965 Binary files /dev/null and b/website/public/images/textures/bruegel-childrens-games-hero.jpg differ diff --git a/website/public/images/textures/monet-water-lilies-hero.jpg b/website/public/images/textures/monet-water-lilies-hero.jpg new file mode 100644 index 0000000000..0e9bc21c58 Binary files /dev/null and b/website/public/images/textures/monet-water-lilies-hero.jpg differ diff --git a/website/public/images/textures/oil-olive-landscape.jpg b/website/public/images/textures/oil-olive-landscape.jpg new file mode 100644 index 0000000000..40c10f21cf Binary files /dev/null and b/website/public/images/textures/oil-olive-landscape.jpg differ diff --git a/website/redirects.mjs b/website/redirects.mjs index a77d8605c0..3137f0ed40 100644 --- a/website/redirects.mjs +++ b/website/redirects.mjs @@ -36,6 +36,7 @@ export const redirects = { // Self-hosting redirect '/docs/general/self-hosting': '/docs/self-hosting/', // Removed solution pages + '/agent': '/actors/', '/solutions/agents': '/', '/solutions/app-generators': '/', '/solutions/collaborative-state': '/', diff --git a/website/src/components/Accordion.jsx b/website/src/components/Accordion.jsx index e267e4103d..1bf0b49d53 100644 --- a/website/src/components/Accordion.jsx +++ b/website/src/components/Accordion.jsx @@ -6,19 +6,16 @@ function getAccordionStyleFromVariant(variant) { // Minimal padding. Shows a border along the left when open. return { parentClass: "", - coverClass: - "[&>div]:ml-2 py-1 text-charcole-700 hover:text-charcole-900 dark:text-cream-400 dark:hover:text-cream-200", - contentClass: - "mt-2 pt-1 mb-4 mx-[7px] px-4 border-l border-cream-100 dark:border-charcole-800", + coverClass: "[&>div]:ml-2 py-1 text-ink-soft hover:text-ink", + contentClass: "mt-2 pt-1 mb-4 mx-[7px] px-4 border-l border-ink/10", }; } // Rounding is handled in Accordion by passing in isRounded to AccordionCover. return { - parentClass: - "border dark:border-charcole-800 rounded-xl mb-3 overflow-hidden", + parentClass: "border border-ink/10 rounded-xl mb-3 overflow-hidden", coverClass: - "py-4 px-5 space-x-2 hover:bg-violet-100 hover:dark:bg-white/10 rounded-t-xl transition", + "py-4 px-5 space-x-2 hover:bg-ink/[0.04] rounded-t-xl transition", contentClass: "mt-2 mb-4 mx-6", }; } @@ -56,22 +53,22 @@ export function Accordion({ icon={faCaretRight} data-accordion-icon className={clsx( - "h-3 w-3 text-charcole-800 opacity-75 dark:text-cream-100 transition-transform duration-200", + "h-3 w-3 text-ink-faint opacity-75 transition-transform duration-200", defaultOpen && "rotate-90" )} /> {icon ? ( -
+
{icon}
) : null}
-

+

{title}

{description ? ( -

+

{description}

) : null} @@ -94,7 +91,7 @@ export function AccordionGroup({ children }) { // when inside of an Accordion group. return (
{children} diff --git a/website/src/components/ArticleSocials.tsx b/website/src/components/ArticleSocials.tsx index 6687e36ae1..9f610a5a72 100644 --- a/website/src/components/ArticleSocials.tsx +++ b/website/src/components/ArticleSocials.tsx @@ -19,7 +19,7 @@ export function ArticleSocials({ title }) { const siteUrl = getSiteUrl(); const articleUrl = siteUrl + pathname; return ( -
+
diff --git a/website/src/components/BlogArticle.astro b/website/src/components/BlogArticle.astro index 5cb2456e3c..7de3c7c2bb 100644 --- a/website/src/components/BlogArticle.astro +++ b/website/src/components/BlogArticle.astro @@ -44,13 +44,13 @@ const otherArticles = allPosts }); --- -
+
Blog @@ -58,14 +58,14 @@ const otherArticles = allPosts
-
{otherArticles.length > 0 && ( -
-

Read next

+
+

Read next

{otherArticles.map((article) => ( @@ -105,21 +105,21 @@ const otherArticles = allPosts alt={article.title} width={600} height={300} - class="aspect-[2/1] w-full rounded-xl border border-white/10 object-cover transition-colors group-hover:border-white/25" + class="aspect-[2/1] w-full rounded-xl border border-ink/10 object-cover transition-colors group-hover:border-ink/25" loading="lazy" decoding="async" /> )}
- {article.category.name} -
-

+

{article.title}

- + Read article @@ -136,7 +136,7 @@ const otherArticles = allPosts .blog-article .blog-prose { font-size: 1.0625rem; line-height: 1.8; - color: hsl(var(--muted-foreground)); + color: #56524a; } .blog-article .blog-prose p, @@ -152,33 +152,36 @@ const otherArticles = allPosts .blog-article .blog-prose h2 { font-size: 1.75rem; + font-weight: 500; line-height: 1.2; letter-spacing: -0.02em; margin-top: 2.75rem; margin-bottom: 1rem; - color: #fff; + color: #1b1916; } .blog-article .blog-prose h3 { font-size: 1.3rem; + font-weight: 500; line-height: 1.3; letter-spacing: -0.015em; margin-top: 2.25rem; margin-bottom: 0.75rem; - color: #fff; + color: #1b1916; } .blog-article .blog-prose h4 { font-size: 1.075rem; + font-weight: 500; margin-top: 2rem; margin-bottom: 0.5rem; - color: #fff; + color: #1b1916; } .blog-article .blog-prose a { - color: #ff6a33; + color: #2e4034; text-decoration: underline; - text-decoration-color: rgb(255 69 0 / 0.35); + text-decoration-color: rgb(46 64 52 / 0.35); text-underline-offset: 0.2em; text-decoration-thickness: 1px; font-weight: 500; @@ -186,28 +189,28 @@ const otherArticles = allPosts } .blog-article .blog-prose a:hover { - color: #ff8a5c; - text-decoration-color: rgb(255 69 0 / 0.9); + color: #1b1916; + text-decoration-color: rgb(46 64 52 / 0.9); } .blog-article .blog-prose strong { - color: #fff; + color: #1b1916; font-weight: 600; } .blog-article .blog-prose :not(pre) > code { - background: rgb(255 255 255 / 0.06); - border: 1px solid rgb(255 255 255 / 0.08); + background: rgb(27 25 22 / 0.05); + border: 1px solid rgb(27 25 22 / 0.1); border-radius: 0.375rem; padding: 0.1em 0.4em; font-size: 0.875em; - color: #e6e6e6; + color: #1b1916; } .blog-article .blog-prose pre { border-radius: 0.75rem; - border: 1px solid rgb(255 255 255 / 0.1); - background: rgb(255 255 255 / 0.025); + border: 1px solid rgb(27 25 22 / 0.2); + background: #1b1916; padding: 1.25rem 1.4rem; font-size: 0.9rem; line-height: 1.7; @@ -216,22 +219,22 @@ const otherArticles = allPosts } .blog-article .blog-prose blockquote { - border-left: 2px solid #ff4500; + border-left: 2px solid #2e4034; padding-left: 1.25rem; font-style: normal; - color: hsl(var(--muted-foreground)); + color: #56524a; } .blog-article .blog-prose img, .blog-article .blog-prose video { border-radius: 0.75rem; - border: 1px solid rgb(255 255 255 / 0.1); + border: 1px solid rgb(27 25 22 / 0.1); margin-top: 2rem; margin-bottom: 2rem; } .blog-article .blog-prose hr { - border-color: rgb(255 255 255 / 0.1); + border-color: rgb(27 25 22 / 0.1); margin-top: 2.75rem; margin-bottom: 2.75rem; } diff --git a/website/src/components/Card.tsx b/website/src/components/Card.tsx index 5855597abf..9bc0df70c9 100644 --- a/website/src/components/Card.tsx +++ b/website/src/components/Card.tsx @@ -25,8 +25,8 @@ export function Card({ const content = (
@@ -34,7 +34,7 @@ export function Card({
@@ -42,7 +42,7 @@ export function Card({ {icon && } {title &&

{title}

} {badge && ( - + {badge} )} @@ -50,7 +50,7 @@ export function Card({ {href && ( )}
diff --git a/website/src/components/CollapsibleSidebarItem.tsx b/website/src/components/CollapsibleSidebarItem.tsx index cd4ca4137a..91a57ca86f 100644 --- a/website/src/components/CollapsibleSidebarItem.tsx +++ b/website/src/components/CollapsibleSidebarItem.tsx @@ -89,7 +89,7 @@ export function CollapsibleSidebarItem({ - + Copy link to Markdown diff --git a/website/src/components/DocsTableOfContents.tsx b/website/src/components/DocsTableOfContents.tsx index adfcb9751d..ab28a6d5c7 100644 --- a/website/src/components/DocsTableOfContents.tsx +++ b/website/src/components/DocsTableOfContents.tsx @@ -92,7 +92,7 @@ function NavLink({ id, isActive, children }) {
{children} @@ -109,13 +109,13 @@ export function ActiveSectionMarker({ prefix }) { layoutId={`${prefix}current-background`} initial={{ opacity: 0 }} animate={{ opacity: 1 }} - className="absolute inset-0 -left-2 bg-charcole-800/2.5 will-change-transform dark:bg-white/2.5" + className="absolute inset-0 -left-2 bg-ink/[0.04] will-change-transform" style={{ borderRadius: 8 }} /> diff --git a/website/src/components/DocsTabs.tsx b/website/src/components/DocsTabs.tsx index d0e2c1b4ef..575c4b7957 100644 --- a/website/src/components/DocsTabs.tsx +++ b/website/src/components/DocsTabs.tsx @@ -5,13 +5,13 @@ import { findPageForHref } from "@/lib/sitemap"; import { sitemap } from "@/sitemap/mod"; import { cn } from "@rivet-gg/components"; -export function DocsTabs() { +export function DocsTabs({ light = false }: { light?: boolean }) { const pathname = usePathname() || ""; // Remove trailing slash for consistency const normalizedPath = pathname.replace(/\/$/, ""); return ( -
+
{sitemap.map((tab) => { const isActive = findPageForHref(normalizedPath, tab); return ( @@ -21,13 +21,18 @@ export function DocsTabs() { target={tab.target} aria-current={isActive ? "page" : undefined} className={cn( - "text-muted-foreground px-0 text-sm hover:bg-transparent flex items-center border-b-2 border-transparent rounded-none h-full transition-colors", - "aria-[current=page]:text-foreground aria-[current=page]:border-primary" + "px-0 text-sm hover:bg-transparent flex items-center border-b-2 border-transparent rounded-none h-full transition-colors", + light + ? "text-ink-faint aria-[current=page]:text-ink aria-[current=page]:border-pine" + : "text-muted-foreground aria-[current=page]:text-foreground aria-[current=page]:border-primary" )} > {tab.title} {tab.badge && ( - + {tab.badge} )} diff --git a/website/src/components/Footer.jsx b/website/src/components/Footer.jsx index 4b9509b6b8..fcc23e6743 100644 --- a/website/src/components/Footer.jsx +++ b/website/src/components/Footer.jsx @@ -25,6 +25,7 @@ const footer = { { name: "Sandbox Agent SDK", href: "https://sandboxagent.dev" }, { name: "Secure Exec SDK", href: "https://secureexec.dev" }, { name: "Cloud Pricing", href: "/cloud#pricing" }, + { name: "Enterprise", href: "/enterprise" }, { name: "Talk to an engineer", href: "/talk-to-an-engineer" }, { name: "Sales", href: "/sales" }, ], @@ -37,7 +38,8 @@ const footer = { ], resources: [ { name: "Cookbooks", href: "/cookbook" }, - { name: "Compare", href: "/compare" }, + { name: "Rivet vs Cloudflare Durable Objects", href: "/compare/rivet-vs-cloudflare-durable-objects" }, + { name: "Rivet vs Temporal", href: "/compare/rivet-vs-temporal" }, { name: "Blog", href: "/blog" }, { name: "YC & Speedrun Deal", href: "/startups" }, { name: "Open-Source Friends", href: "/oss-friends" }, @@ -134,12 +136,12 @@ export function PageNextPrevious({ navigation }) { function SmallPrint() { return ( -
+
{/* Brand column */}
Rivet -

+

Infrastructure for the agentic era

@@ -147,7 +149,7 @@ function SmallPrint() { {item.name}
-

Product

+

Product

    {footer.product.map((item) => (
  • {item.name} @@ -176,14 +178,14 @@ function SmallPrint() { {/* Developers */}
    -

    Developers

    +

    Developers

      {footer.devs.map((item) => (
    • {item.name} @@ -194,14 +196,14 @@ function SmallPrint() { {/* Resources */}
      -

      Resources

      +

      Resources

        {footer.resources.map((item) => (
      • {item.name} @@ -212,13 +214,13 @@ function SmallPrint() { {/* Legal */}
        -

        Legal

        +

        Legal

          {footer.legal.map((item) => (
        • {item.name} @@ -230,20 +232,20 @@ function SmallPrint() { {/* Investor badges */}
          - Backed by + Backed by
          -
          +
          Y Combinator Y Combinator
          -
          +
          a16z a16z Speedrun
          Are you as well? - + @@ -269,11 +271,11 @@ function SmallPrint() {
          {/* Copyright */} -
          -

          +

          +

          © {new Date().getFullYear()} Rivet Gaming, Inc. All rights reserved.

          -

          +

          Cloudflare® and Durable Objects™ are trademarks of Cloudflare, Inc. No affiliation or endorsement implied.

          @@ -281,15 +283,26 @@ function SmallPrint() { ); } -const WHITE_THEMED_PATHS = ['/agent-os', '/agent-os/use-cases', '/agent-os/pricing', '/agent-os/registry', '/from-unix-to-agents', '/install']; +// The footer is light by default to match the porcelain surfaces (marketing +// and docs). Only the Learn section keeps its dark shell, so that path applies +// a dark override wrapper instead. +const DARK_THEMED_PATH_PREFIXES = ['/learn']; -export function Footer() { - const pathname = usePathname(); - const isWhite = WHITE_THEMED_PATHS.some((p) => pathname === p || pathname === p + '/') || pathname.startsWith('/agent-os/registry/'); +export function Footer({ initialPathname = "" }) { + // usePathname returns "" during SSR; fall back to the server-provided path + // so docs pages do not flash a light footer before hydration. + const pathname = usePathname() || initialPathname; + const isDark = DARK_THEMED_PATH_PREFIXES.some((p) => pathname === p || pathname.startsWith(p + '/')); return ( -
          -
          +
          +