From 33d687f339edcd0cb80f7838143b16a4c2f66b4a Mon Sep 17 00:00:00 2001 From: deepanshupal09-datazip Date: Wed, 12 Aug 2026 19:39:34 +0530 Subject: [PATCH 1/7] feat: make landing page responsive and copy changes --- .../2025-02-21-data-partitioning-in-s3.mdx | 2 +- src/components/BlogCTA.tsx | 64 +- src/components/FusionBlogCTA.tsx | 4 +- src/components/landing/Navbar/SiteNavbar.css | 412 +++++++++--- src/components/landing/Navbar/SiteNavbar.tsx | 258 ++++++-- src/components/landing/Navbar/navData.ts | 106 +-- src/components/landing/pages/olake-fusion.css | 368 +++++++++-- src/components/landing/pages/olake-go.css | 412 ++++++++++-- src/components/landing/pages/olake-home.css | 299 +++++++-- src/components/landing/pages/overrides.css | 66 +- .../landing/pages/useFusionLogic.ts | 4 +- src/components/landing/pages/useGoLogic.ts | 57 +- src/components/landing/pages/useHomeLogic.ts | 91 ++- src/css/custom.css | 51 +- src/hooks/useGetReleases.ts | 25 +- src/pages/ai-lake.tsx | 10 +- src/pages/contact.tsx | 164 ++--- src/pages/index.tsx | 614 +++++++++++++----- src/pages/olake-fusion.tsx | 66 +- src/pages/olake-go.tsx | 228 +++++-- src/theme/Footer/index.tsx | 449 ++++++------- src/theme/Footer/styles.css | 67 ++ src/theme/Navbar/Content/index.tsx | 27 + .../MobileSidebar/PrimaryMenu/index.tsx | 73 +++ static/llm.txt | 2 +- static/llms.txt | 2 +- 26 files changed, 2758 insertions(+), 1163 deletions(-) create mode 100644 src/theme/Footer/styles.css create mode 100644 src/theme/Navbar/Content/index.tsx create mode 100644 src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx diff --git a/iceberg/2025-02-21-data-partitioning-in-s3.mdx b/iceberg/2025-02-21-data-partitioning-in-s3.mdx index 7b2835fcf..ea7ee8610 100644 --- a/iceberg/2025-02-21-data-partitioning-in-s3.mdx +++ b/iceberg/2025-02-21-data-partitioning-in-s3.mdx @@ -296,7 +296,7 @@ Although other tools like BigQuery and Hive are robust, our solution hits the sw I hope this deep dive into our implementation gives you a clearer picture of how we tackled our data challenges. If you’re considering a similar approach, I’d love to hear your thoughts or questions. -Reach out to us at [hello@olake.io](mailto:hello@olake.io) or head over to [Join Waitlist](https://olake.io/#olake-form-product) and our team will be happy to get in touch with you. +Reach out to us at [hello@olake.io](mailto:hello@olake.io) or head over to [Join Waitlist](https://olake.io/contact) and our team will be happy to get in touch with you. \ No newline at end of file diff --git a/src/components/BlogCTA.tsx b/src/components/BlogCTA.tsx index f46a64933..0914c12e7 100644 --- a/src/components/BlogCTA.tsx +++ b/src/components/BlogCTA.tsx @@ -1,59 +1,51 @@ -import React from 'react'; -import { FaExternalLinkAlt, FaGithub, FaSlack } from 'react-icons/fa'; +import React from 'react' +import { FaExternalLinkAlt, FaGithub, FaSlack } from 'react-icons/fa' const BlogCTA = () => { return ( -
-

- OLake Go -

-

- Replicate databases, Kafka, and S3 into Apache Iceberg with OLake Go, an open source EL engine built for Iceberg from the ground up. +

+

OLake Go

+

+ Replicate databases, Kafka, and S3 into Apache Iceberg with OLake Go, an open source EL + engine built for Iceberg from the ground up.

-
+ -
+
Contact us at hello@olake.io
- ); -}; - - -// https://olake.io/#olake-form-product) - + ) +} -export default BlogCTA; \ No newline at end of file +export default BlogCTA diff --git a/src/components/FusionBlogCTA.tsx b/src/components/FusionBlogCTA.tsx index 67329a437..8bdcc9835 100644 --- a/src/components/FusionBlogCTA.tsx +++ b/src/components/FusionBlogCTA.tsx @@ -23,9 +23,7 @@ const FusionBlogCTA = () => { diff --git a/src/components/landing/Navbar/SiteNavbar.css b/src/components/landing/Navbar/SiteNavbar.css index 3852cfa76..6bafd6dcc 100644 --- a/src/components/landing/Navbar/SiteNavbar.css +++ b/src/components/landing/Navbar/SiteNavbar.css @@ -1,22 +1,27 @@ -/* Shared landing-page navbar — values taken verbatim from the v2 homepage - design's NAV block. - * - * NOTE ON SPECIFICITY: the generated page stylesheets contain - * `.olakehome-page a { color: #193AE6 }` (0,1,1), which outranks a bare - * `.olake-nav-cta` (0,1,0) and repainted the CTA's white text blue-on-blue - * (invisible) and the Pricing link blue. Every rule that sets a link colour - * is therefore qualified with `.olake-nav` to reach (0,2,0) and win. */ +/* Site-wide navbar, following the v2 homepage design. Every rule that sets a + link colour is qualified with `.olake-nav` to reach (0,2,0) and outrank the + page stylesheets' `.olakehome-page a { color: #193AE6 }` (0,1,1). */ .olake-nav { - /* sticky + z-index come from the design; without them the bar scrolls away */ position: sticky; top: 0; z-index: 50; width: 100%; + background: rgba(255, 255, 255, 0.86); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border-bottom: 1px solid rgba(27, 30, 43, 0.09); + font-family: 'Space Grotesk', sans-serif; + color: #1b1e2b; +} + +/* The homepage sits on #f0f2fa, and its design tints the bar to match; white + there reads as a solid strip rather than a translucent one. */ +body:has(.olakehome-page) .olake-nav { background: rgba(240, 242, 250, 0.82); backdrop-filter: blur(14px); + -webkit-backdrop-filter: blur(14px); border-bottom: 1px solid rgba(0, 0, 0, 0.06); - font-family: 'Space Grotesk', sans-serif; } .olake-nav-inner { @@ -36,7 +41,9 @@ .olake-nav .olake-nav-logo { display: flex; - align-items: center; + flex-direction: column; + align-items: flex-start; + gap: 5px; } .olake-nav-logo img { @@ -44,13 +51,20 @@ width: auto; } +.olake-nav-tagline { + font-size: 8px; + letter-spacing: 0.02em; + color: #8890a8; + white-space: nowrap; +} + .olake-nav-links { display: flex; align-items: center; gap: 30px; - font-size: 14px; + font-size: 15px; font-weight: 500; - color: #424865; + color: #5b6070; } .olake-nav-item { @@ -63,7 +77,7 @@ align-items: center; gap: 5px; cursor: pointer; - color: #121212; + color: #5b6070; } .olake-nav-caret { @@ -75,11 +89,12 @@ position: absolute; top: 36px; left: -16px; - background: #e7ecff; - border: 1px solid rgba(0, 0, 0, 0.09); + background: #fff; + border: 1px solid rgba(27, 30, 43, 0.1); border-radius: 12px; + box-shadow: 0 18px 40px -16px rgba(27, 30, 43, 0.22); padding: 8px; - min-width: 190px; + min-width: 220px; display: flex; flex-direction: column; visibility: hidden; @@ -88,18 +103,32 @@ z-index: 60; } -/* Invisible bridge across the gap between the trigger and the panel. - * - * The panel is offset to `top: 36px` but the trigger's box ends a few pixels - * above that, leaving a strip where the pointer is over neither element — - * which fires mouseleave on .olake-nav-item and closes the menu while you are - * still moving toward it. - * - * This works because the panel is a DOM child of .olake-nav-item, so the - * pointer never actually leaves that subtree (mouseleave does not fire when - * moving onto a descendant, even one positioned outside the parent's box). - * The pseudo-element inherits `visibility: hidden` while closed, so it never - * blocks clicks on whatever sits underneath. */ +/* Nested submenu — opens beside its parent panel rather than below it. */ +.olake-nav-flyout { + position: relative; +} + +.olake-nav .olake-nav-flyout-trigger { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + cursor: pointer; +} + +.olake-nav-flyout-caret { + font-size: 10px; +} + +.olake-nav-panel--side { + top: -8px; + left: 100%; + min-width: 200px; +} + +/* Invisible bridge across the gap between the trigger and the panel: without + it, the pointer crossing that strip fires mouseleave on .olake-nav-item and + closes the menu. Inherits `visibility: hidden`, so it never blocks clicks. */ .olake-nav-panel::before { content: ''; position: absolute; @@ -117,20 +146,21 @@ .olake-nav .olake-nav-panel-link { padding: 10px 14px; border-radius: 8px; - color: #0a0f23; + color: #1b1e2b; font-weight: 500; text-decoration: none; white-space: nowrap; } -.olake-nav .olake-nav-panel-link:hover { - background: rgba(0, 0, 0, 0.05); - color: #0a0f23; +.olake-nav .olake-nav-panel-link:hover, +.olake-nav .olake-nav-flyout-trigger:hover { + background: #f4f2ec; + color: #1b1e2b; text-decoration: none; } .olake-nav .olake-nav-plain { - color: #121212; + color: #5b6070; text-decoration: none; } @@ -142,7 +172,7 @@ .olake-nav-right { display: flex; align-items: center; - gap: 18px; + gap: 16px; } .olake-nav .olake-nav-stars { @@ -151,27 +181,35 @@ gap: 8px; font-family: 'JetBrains Mono', monospace; font-size: 12px; - color: #424865; + color: #5b6070; text-decoration: none; - border: 1px solid rgba(0, 0, 0, 0.1); + border: 1px solid rgba(27, 30, 43, 0.14); border-radius: 8px; - padding: 7px 12px; + padding: 6px 12px; white-space: nowrap; } .olake-nav .olake-nav-stars:hover { - color: #424865; + color: #5b6070; text-decoration: none; } .olake-nav-stars img { - height: 28px; + height: 29px; width: 28px; - border-radius: 5px; + border-radius: 4px; } -.olake-nav-star-mark { - color: #3fa872; +/* Icon-only GitHub link, shown in place of the pill below the breakpoint. */ +.olake-nav .olake-nav-gh-mobile { + display: none; + align-items: center; +} + +.olake-nav-gh-mobile img { + height: 30px; + width: 30px; + border-radius: 5px; } .olake-nav .olake-nav-slack { @@ -180,51 +218,64 @@ } .olake-nav-slack img { - height: 30px; - width: 30px; + height: 34px; + width: 35px; +} + +/* Docusaurus' colour-mode toggle / search box, passed in as `trailing`. */ +.olake-nav .olake-nav-colormode, +.olake-nav [class*='navbarSearchContainer'] { + display: flex; + align-items: center; + line-height: 1; +} + +/* custom.css hides these on landing routes by targeting the inner controls, + leaving the wrappers to hold open a gap where no icon is. */ +body:has(.landing-page) .olake-nav .olake-nav-colormode, +body:has(.landing-page) .olake-nav [class*='navbarSearchContainer'], +.olake-nav [class*='navbarSearchContainer']:empty { + display: none; } .olake-nav .olake-nav-cta { + display: inline-flex; + align-items: center; + justify-content: center; background: #193ae6; color: #fff; - padding: 9px 20px; + padding: 10px 20px; border-radius: 8px; font-weight: 600; font-size: 14px; text-decoration: none; white-space: nowrap; - box-shadow: - 0 4px 0 #5762da, - 0 5px 8px rgba(255, 255, 255, 0.18), - inset 0 1px 0 rgba(0, 0, 0, 0.32); - transition: transform 0.06s ease, box-shadow 0.06s ease; } .olake-nav .olake-nav-cta:hover { color: #fff; text-decoration: none; - transform: translateY(4px); - box-shadow: 0 0 0 #5762da, inset 0 1px 0 rgba(0, 0, 0, 0.2); } -/* --- mobile --------------------------------------------------------------- - These routes hide Docusaurus' navbar (and therefore its mobile sidebar), so - this carries its own menu. 1279px matches the navbar-breakpoint plugin. */ +/* --- mobile ------------------------------------------------------------- */ .olake-nav-burger { display: none; flex-direction: column; + align-items: center; + justify-content: center; gap: 5px; cursor: pointer; padding: 6px; background: none; border: none; + line-height: 1; } .olake-nav-burger span { width: 22px; height: 2px; - background: #121212; + background: #1b1e2b; border-radius: 2px; } @@ -233,31 +284,17 @@ flex-direction: column; gap: 2px; padding: 8px 20px 20px; - background: #f0f2fa; - border-top: 1px solid rgba(0, 0, 0, 0.06); -} - -.olake-nav-mobile-group { - display: flex; - flex-direction: column; - padding-bottom: 6px; -} - -.olake-nav-mobile-heading { - font-family: 'JetBrains Mono', monospace; - font-size: 11px; - letter-spacing: 0.08em; - color: #7b84a4; - padding: 12px 6px 4px; + background: #fff; + border-top: 1px solid rgba(27, 30, 43, 0.09); } .olake-nav .olake-nav-mobile-link { - padding: 11px 6px; - color: #0a0f23; + padding: 13px 6px; + color: #1b1e2b; font-weight: 600; - font-size: 15px; + font-size: 16px; text-decoration: none; - border-bottom: 1px solid rgba(0, 0, 0, 0.06); + border-bottom: 1px solid #eef0f5; } .olake-nav .olake-nav-mobile-link:hover { @@ -265,36 +302,147 @@ text-decoration: none; } -.olake-nav .olake-nav-mobile-cta { - margin-top: 14px; - background: #193ae6; - color: #fff; - padding: 12px 20px; - border-radius: 8px; +/* Footer of the drawer: the star pill and Slack, which have no room in the bar. */ +.olake-nav-mobile-social { + display: flex; + align-items: center; + gap: 14px; + margin-top: 18px; +} + +/* Docs row in the drawer: expands in place instead of navigating, mirroring + the desktop Docs dropdown (OLake Go / OLake Fusion). */ +.olake-nav .olake-nav-mobile-accordion-trigger { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + background: none; + border: none; + font: inherit; + cursor: pointer; + text-align: left; +} + +.olake-nav-mobile-accordion-caret { + font-size: 11px; + transition: transform 0.15s ease; +} + +.olake-nav-mobile-accordion-caret.is-open { + transform: rotate(180deg); +} + +.olake-nav-mobile-accordion-panel { + display: flex; + flex-direction: column; + padding-bottom: 4px; +} + +.olake-nav .olake-nav-mobile-sublink { + padding: 11px 6px 11px 20px; + color: #5b6070; font-weight: 600; - font-size: 14px; - text-align: center; + font-size: 15px; text-decoration: none; + border-bottom: 1px solid #eef0f5; } -.olake-nav .olake-nav-mobile-cta:hover { - color: #fff; +.olake-nav .olake-nav-mobile-sublink:hover { + color: #193ae6; text-decoration: none; } +/* The design collapses at 860px; we do it at 1279px to match the + `navbar-breakpoint` plugin, below which Docusaurus renders the mobile + sidebar that /docs relies on. */ @media (max-width: 1279px) { .olake-nav-inner { - padding: 12px 20px; + padding: 14px 20px; + } + + body:has(.olakehome-page) .olake-nav-inner { + padding: 20px 18px; + } + + .olake-nav-right { + gap: 12px; } .olake-nav-links, - .olake-nav-stars { + .olake-nav .olake-nav-stars { display: none; } + .olake-nav .olake-nav-mobile-social .olake-nav-stars { + display: flex; + } + + .olake-nav .olake-nav-gh-mobile { + display: flex; + } + .olake-nav-burger { display: flex; } + + /* custom.css's `img { max-width:100% }` mobile reset shrinks a squeezed + icon's width but not its fixed height, stretching it. Let the logo block + absorb the deficit instead. */ + .olake-nav-left { + min-width: 0; + } + + .olake-nav-logo img, + .olake-nav .olake-nav-gh-mobile img, + .olake-nav-slack img { + max-width: none; + flex-shrink: 0; + } + + .olake-nav .olake-nav-gh-mobile, + .olake-nav-slack, + .olake-nav .olake-nav-cta, + .olake-nav-burger { + flex-shrink: 0; + } + + /* Upstream absolutely-positions this below 996px, landing it on the + burger. Put it back in flow. */ + .olake-nav [class*='navbarSearchContainer'] { + position: static; + right: auto; + } + + .olake-nav [class*='navbarSearchContainer'], + .olake-nav .olake-nav-colormode { + flex-shrink: 0; + } +} + +/* Phone widths; the designs were never tested below ~860px. */ +@media (max-width: 520px) { + .olake-nav-inner { + padding-left: 14px; + padding-right: 14px; + } + + .olake-nav-right { + gap: 8px; + } + + .olake-nav-tagline { + display: none; + } + + .olake-nav-logo img { + height: 26px; + } + + .olake-nav .olake-nav-cta { + padding: 9px 14px; + font-size: 13px; + } } @media (min-width: 1280px) { @@ -302,3 +450,89 @@ display: none; } } + +/* --- dark mode — the design bundles are light-only ---------------------- */ + +/* Lighter than the page's #060606 background, so the blur stays visible. */ +html[data-theme='dark'] .olake-nav { + background: rgba(20, 21, 28, 0.88); + border-bottom: 1px solid rgba(255, 255, 255, 0.09); + color: #e7e9f5; +} + +html[data-theme='dark'] body:has(.olakehome-page) .olake-nav { + background: rgba(22, 23, 32, 0.9); + border-bottom: 1px solid rgba(255, 255, 255, 0.07); +} + +html[data-theme='dark'] .olake-nav-tagline { + color: #7c8299; +} + +html[data-theme='dark'] .olake-nav-trigger, +html[data-theme='dark'] .olake-nav .olake-nav-plain { + color: #b8bcd0; +} + +html[data-theme='dark'] .olake-nav .olake-nav-plain:hover { + color: #fff; +} + +html[data-theme='dark'] .olake-nav-panel { + background: #17181f; + border-color: rgba(255, 255, 255, 0.1); + box-shadow: 0 18px 40px -16px rgba(0, 0, 0, 0.6); +} + +html[data-theme='dark'] .olake-nav .olake-nav-panel-link { + color: #e7e9f5; +} + +html[data-theme='dark'] .olake-nav .olake-nav-panel-link:hover, +html[data-theme='dark'] .olake-nav .olake-nav-flyout-trigger:hover { + background: rgba(255, 255, 255, 0.07); + color: #fff; +} + +html[data-theme='dark'] .olake-nav .olake-nav-stars { + color: #b8bcd0; + border-color: rgba(255, 255, 255, 0.16); +} + +html[data-theme='dark'] .olake-nav .olake-nav-stars:hover { + color: #b8bcd0; +} + +/* Presentation attribute on the SVG (stroke="#10173A"); a stylesheet rule + outranks it regardless of specificity. */ +html[data-theme='dark'] .olake-nav-stars svg { + stroke: #e7e9f5; +} + +html[data-theme='dark'] .olake-nav-burger span { + background: #e7e9f5; +} + +html[data-theme='dark'] .olake-nav-mobile { + background: #0a0a0a; + border-top: 1px solid rgba(255, 255, 255, 0.09); +} + +html[data-theme='dark'] .olake-nav .olake-nav-mobile-link, +html[data-theme='dark'] .olake-nav .olake-nav-mobile-accordion-trigger { + color: #e7e9f5; + border-bottom-color: rgba(255, 255, 255, 0.08); +} + +html[data-theme='dark'] .olake-nav .olake-nav-mobile-link:hover { + color: #7c93ff; +} + +html[data-theme='dark'] .olake-nav .olake-nav-mobile-sublink { + color: #b8bcd0; + border-bottom-color: rgba(255, 255, 255, 0.08); +} + +html[data-theme='dark'] .olake-nav .olake-nav-mobile-sublink:hover { + color: #7c93ff; +} diff --git a/src/components/landing/Navbar/SiteNavbar.tsx b/src/components/landing/Navbar/SiteNavbar.tsx index 0f3e01175..d567f2270 100644 --- a/src/components/landing/Navbar/SiteNavbar.tsx +++ b/src/components/landing/Navbar/SiteNavbar.tsx @@ -3,12 +3,17 @@ import Link from '@docusaurus/Link' import { cn } from '@site/src/lib/utils' import useGetReleases from '@site/src/hooks/useGetReleases' import { - NAV_DROPDOWNS, + NAV_ENTRIES, + MOBILE_LINKS, PRICING_LINK, GITHUB_REPO_URL, SLACK_URL, CTA, - type NavDropdown + isFlyout, + isMobileGroup, + type NavEntry, + type NavLink as NavLinkType, + type NavFlyout } from './navData' /** Formats 4231 -> "4.2k", matching the design's star pill. */ @@ -17,21 +22,79 @@ function formatStars(n: number): string { return n >= 1000 ? `${(n / 1000).toFixed(1)}k` : String(n) } -function Dropdown({ dropdown }: { dropdown: NavDropdown }) { +/** The design's outlined star. */ +const StarMark = () => ( + + + +) + +/** Star count. In the bar on desktop; the design moves it into the drawer on mobile. */ +const StarPill = ({ stars }: { stars: string }) => ( + + + {stars} + +) + +const SlackLink = () => ( + + {/* the design uses the Slack artwork here, not an icon font */} + + +) + +/** A submenu opening to the side of its parent panel — the design's `▸` row. */ +function Flyout({ flyout }: { flyout: NavFlyout }) { const [open, setOpen] = useState(false) return (
setOpen(true)} onMouseLeave={() => setOpen(false)} + onKeyDown={(e) => e.key === 'Escape' && setOpen(false)} > -
- {dropdown.label} - +
setOpen((o) => !o)} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault() + setOpen((o) => !o) + } + }} + > + {flyout.label} +
- {/* Always rendered so the links are crawlable and work without JS; only visibility toggles. */} -
- {dropdown.items.map((item) => ( +
+ {flyout.items.map((item) => ( {item.label} @@ -41,33 +104,122 @@ function Dropdown({ dropdown }: { dropdown: NavDropdown }) { ) } +function Dropdown({ entry }: { entry: NavEntry }) { + const [open, setOpen] = useState(false) + return ( +
setOpen(true)} + onMouseLeave={() => setOpen(false)} + onKeyDown={(e) => e.key === 'Escape' && setOpen(false)} + > +
setOpen((o) => !o)} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault() + setOpen((o) => !o) + } + }} + > + {entry.label} + +
+ {/* Always rendered so the links are crawlable and work without JS; only visibility toggles. */} +
+ {entry.items!.map((item) => + isFlyout(item) ? ( + + ) : ( + + {item.label} + + ) + )} +
+
+ ) +} + +/** A drawer row that expands in place instead of navigating — the drawer's Docs entry. */ +function MobileAccordion({ entry, onNavigate }: { entry: NavEntry; onNavigate: () => void }) { + const [open, setOpen] = useState(false) + return ( +
+ + {open && ( +
+ {entry.items!.map((item) => ( + + {item.label} + + ))} +
+ )} +
+ ) +} + interface SiteNavbarProps { /** Optional extra content at the far right, after the CTA. */ trailing?: ReactNode + /** + * Hands the burger over to Docusaurus' mobile sidebar instead of this + * component's own drawer. Set when rendered as the theme navbar: that + * sidebar is what carries the docs secondary menu. + */ + mobileSidebar?: { shown: boolean; toggle: () => void } } /** - * The navbar shared by the three landing pages, following the v2 homepage - * design. Those routes hide Docusaurus' own navbar (see custom.css), so this - * carries its own mobile menu — without it there would be no navigation - * below the 1279px breakpoint. + * The site-wide navbar, following the v2 homepage design. Rendered through the + * `@theme/Navbar/Content` swizzle. Keeps its own drawer for standalone use (no + * `mobileSidebar` prop); inside the theme it defers to Docusaurus' sidebar. */ -export default function SiteNavbar({ trailing }: SiteNavbarProps) { +export default function SiteNavbar({ trailing, mobileSidebar }: SiteNavbarProps) { const { stargazersCount } = useGetReleases() const stars = formatStars(stargazersCount) - const [mobileOpen, setMobileOpen] = useState(false) + const [ownOpen, setOwnOpen] = useState(false) + + const mobileOpen = mobileSidebar ? mobileSidebar.shown : ownOpen + const toggleMobile = mobileSidebar ? mobileSidebar.toggle : () => setOwnOpen((o) => !o) return (
- OLake + OLake + Open Source · Apache 2.0 Licensed
- {NAV_DROPDOWNS.map((d) => ( - - ))} + {NAV_ENTRIES.map((entry) => + entry.items ? ( + + ) : ( + + {entry.label} + + ) + )} {PRICING_LINK.label} @@ -75,22 +227,19 @@ export default function SiteNavbar({ trailing }: SiteNavbarProps) {
+ + {/* Below the breakpoint the design drops the count and shows the mark + alone; the full pill moves into the drawer. */} - - - {stars} - - - - {/* the design uses the Slack artwork here, not an icon font */} - Slack + + {CTA.label} @@ -100,7 +249,7 @@ export default function SiteNavbar({ trailing }: SiteNavbarProps) { className='olake-nav-burger' aria-label='Toggle navigation menu' aria-expanded={mobileOpen} - onClick={() => setMobileOpen((o) => !o)} + onClick={toggleMobile} > @@ -109,33 +258,28 @@ export default function SiteNavbar({ trailing }: SiteNavbarProps) {
- {mobileOpen && ( + {/* Skipped when Docusaurus' sidebar is in charge; that renders the same + links via the MobileSidebar/PrimaryMenu swizzle, plus the docs menu. */} + {!mobileSidebar && mobileOpen && (
- {NAV_DROPDOWNS.map((d) => ( -
-
{d.label}
- {d.items.map((item) => ( - setMobileOpen(false)} - > - {item.label} - - ))} -
- ))} - setMobileOpen(false)} - > - {PRICING_LINK.label} - - setMobileOpen(false)}> - {CTA.label} - + {MOBILE_LINKS.map((link) => + isMobileGroup(link) ? ( + setOwnOpen(false)} /> + ) : ( + setOwnOpen(false)} + > + {link.label} + + ) + )} +
+ + +
)}
diff --git a/src/components/landing/Navbar/navData.ts b/src/components/landing/Navbar/navData.ts index 6daebd09b..0d7832566 100644 --- a/src/components/landing/Navbar/navData.ts +++ b/src/components/landing/Navbar/navData.ts @@ -3,45 +3,44 @@ export interface NavLink { href: string } -export interface NavDropdown { +/** A submenu that opens to the side of its parent panel (the design's `▸`). */ +export interface NavFlyout { label: string items: NavLink[] } +export interface NavEntry { + label: string + href?: string + /** Panel contents. Omit for a plain link. */ + items?: (NavLink | NavFlyout)[] +} + +export const isFlyout = (item: NavLink | NavFlyout): item is NavFlyout => + Array.isArray((item as NavFlyout).items) + +/** A mobile drawer row: either a plain link, or a group that expands in place. */ +export type MobileNavItem = NavLink | NavEntry + +export const isMobileGroup = (item: MobileNavItem): item is NavEntry => + Array.isArray((item as NavEntry).items) + /** - * Information architecture for the shared site-wide navbar. - * - * Styling/structure follow the v2 homepage design, but the design's nav only - * covers Products / Docs / Resources / Pricing. Everything that existed in - * docusaurus.config.js is preserved here so no destination is lost: - * - * config item -> where it lives now - * -------------------------------------------------------------- - * Docs (dropdown) -> Docs (unchanged) - * Blogs -> Resources > Blog - * Customer Stories -> Resources > Customer Stories - * Community > Webinars & Events -> Resources > Webinars & Events - * Community > OLake Community -> Community > OLake Community - * Community > Top Contributors -> Community > Top Contributors - * Community > Contributor's Prog. -> Community > Contributor's Program - * Community > GSoC -> Community > GSoC - * Iceberg (dropdown) -> Iceberg (kept top-level, as requested) - * Pricing -> Pricing - * - * NOTE: `themeConfig.navbar.items` is not read for these — the design's - * dropdown panels can't be expressed as plain Docusaurus `dropdown` items. - * That config must still stay non-empty: theme-common disables the mobile - * burger entirely when `navbar.items.length === 0`. + * Information architecture for the site-wide navbar. `themeConfig.navbar.items` + * is not read for these, but must stay non-empty: theme-common disables the + * mobile burger entirely when `navbar.items.length === 0`. */ -export const NAV_DROPDOWNS: NavDropdown[] = [ +export const NAV_ENTRIES: NavEntry[] = [ { - label: 'Products', + label: 'Product', items: [ { label: 'OLake Go', href: '/olake-go' }, { label: 'OLake Fusion', href: '/olake-fusion' } ] }, { + // A dropdown rather than the design's plain link: the two products have + // separate doc sets, and a bare /docs lands you in Go's with no way over. label: 'Docs', items: [ { label: 'OLake Go', href: '/docs' }, @@ -53,29 +52,52 @@ export const NAV_DROPDOWNS: NavDropdown[] = [ items: [ { label: 'Blog', href: '/blog' }, { label: 'Customer Stories', href: '/customer-stories' }, - { label: 'Webinars & Events', href: '/webinar' } + { label: 'Webinars & Events', href: '/webinar' }, + { + label: 'Community', + items: [ + { label: 'OLake Community', href: '/community' }, + { label: 'Top Contributors', href: '/community/contributors' }, + { label: 'Contributor Program', href: '/community/contributor-program' }, + { label: 'GSoC', href: '/community/gsoc' } + ] + }, + { + label: 'Iceberg', + items: [ + { label: 'Iceberg Blogs', href: '/iceberg' }, + { label: 'Query Engine', href: '/iceberg/query-engine' } + ] + } ] - }, + } +] + +export const PRICING_LINK: NavLink = { label: 'Pricing', href: '/contact' } + +/** + * The mobile drawer: one flat list, stopping at section level — the pages under + * Community and Iceberg are reached from those pages. Docs is the exception, + * expanding in place to mirror the desktop dropdown. + */ +export const MOBILE_LINKS: MobileNavItem[] = [ + { label: 'OLake Go', href: '/olake-go' }, + { label: 'OLake Fusion', href: '/olake-fusion' }, { - label: 'Community', + label: 'Docs', items: [ - { label: 'OLake Community', href: '/community' }, - { label: 'Top Contributors', href: '/community/contributors' }, - { label: 'Contributor Program', href: '/community/contributor-program' }, - { label: 'GSoC', href: '/community/gsoc' } + { label: 'OLake Go', href: '/docs' }, + { label: 'OLake Fusion', href: '/docs/fusion/getting-started/overview' } ] }, - { - label: 'Iceberg', - items: [ - { label: 'Iceberg Blogs', href: '/iceberg' }, - { label: 'Query Engine', href: '/iceberg/query-engine' } - ] - } + { label: 'Blog', href: '/blog' }, + { label: 'Customer Stories', href: '/customer-stories' }, + { label: 'Webinars & Events', href: '/webinar' }, + { label: 'Community', href: '/community' }, + { label: 'Iceberg', href: '/iceberg' }, + PRICING_LINK ] -export const PRICING_LINK: NavLink = { label: 'Pricing', href: '/contact' } - export const GITHUB_REPO_URL = 'https://github.com/datazip-inc/olake' export const SLACK_URL = '/slack' export const CTA = { label: "Try, it's free!", href: '/docs/getting-started/quickstart/' } diff --git a/src/components/landing/pages/olake-fusion.css b/src/components/landing/pages/olake-fusion.css index e42aa3b19..77c620fc5 100644 --- a/src/components/landing/pages/olake-fusion.css +++ b/src/components/landing/pages/olake-fusion.css @@ -1,64 +1,310 @@ -html:has(.olakefusion-page), body:has(.olakefusion-page){ height: auto; min-height: 100%; } -html:has(.olakefusion-page){ scroll-snap-type: y mandatory; } -body:has(.olakefusion-page){ margin: 0; background: #F5F6FA; } -.olakefusion-page *{ box-sizing: border-box; } -.olakefusion-page a{ color: #3D4FF0; text-decoration: none; } -.olakefusion-page a:hover{ color: #2A38C4; } -.olakefusion-page h1, .olakefusion-page h2, .olakefusion-page h3, .olakefusion-page h4, .olakefusion-page h5, .olakefusion-page h6{ margin: 0; font-weight: inherit; } -@keyframes floatBox{ 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } } -@keyframes travelDot{ 0% { left: 0%; opacity: 0; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { left: 100%; opacity: 0; } } -@keyframes pulseRow{ 0%, 100% { background: #171E44; } 50% { background: #2A3568; } } -@keyframes logoSpin{ 0%, 100% { transform: rotate(0deg) scale(1); } 50% { transform: rotate(8deg) scale(1.08); } } -@keyframes fadeSlideIn{ from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: translateX(0); } } -@keyframes wordFloat{ 0%, 100% { transform: translateY(0) rotate(var(--r, 0deg)); } 50% { transform: translateY(-5px) rotate(var(--r, 0deg)); } } -@keyframes feedIn{ 0% { transform: translateX(0) scale(1); opacity:1; } 65% { opacity:1; } 100% { transform: translateX(120px) scale(0.3); opacity:0; } } -@keyframes compactAppear{ 0%, 15% { opacity:0; transform:scale(0.5); } 35%, 85% { opacity:1; transform:scale(1); } 100% { opacity:0; transform:scale(1.1); } } -@keyframes fusionPulseRing{ 0%, 100% { box-shadow: 0 0 0 0 rgba(61,79,240,0.35); } 50% { box-shadow: 0 0 0 12px rgba(61,79,240,0); } } -@keyframes lightUp1{ 0%, 8% { background:#E4E6F0; } 16%, 88% { background:#A9D8F0; } 96%, 100% { background:#E4E6F0; } } -@keyframes lightUp2{ 0%, 32% { background:#E4E6F0; } 40%, 88% { background:#A9D8F0; } 96%, 100% { background:#E4E6F0; } } -@keyframes lightUp3{ 0%, 56% { background:#E4E6F0; } 64%, 88% { background:#A9D8F0; } 96%, 100% { background:#E4E6F0; } } -.olakefusion-page .nav-burger{ display: none; } -@media (max-width: 900px){ -.olakefusion-page .scroll-pipeline{ display: none !important; } -html:has(.olakefusion-page){ scroll-snap-type: none; } -.olakefusion-page .nav-links, .olakefusion-page .nav-star{ display: none !important; } -.olakefusion-page .nav-burger{ display: flex !important; } -.olakefusion-page .nav-inner{ padding: 14px 20px !important; } -.olakefusion-page .hero-wrap{ padding: 24px 20px 8px !important; } -.olakefusion-page .hero-title{ font-size: 32px !important; } -.olakefusion-page .hero-sub{ width: auto !important; max-width: 100% !important; height: auto !important; font-size: 16px !important; } -.olakefusion-page .hero-btns{ flex-wrap: wrap !important; gap: 12px !important; } -.olakefusion-page .problem-grid{ grid-template-columns: repeat(2, 1fr) !important; } -.olakefusion-page .problem-wrap{ padding: 32px 20px 56px !important; } -.olakefusion-page .problem-title{ font-size: 26px !important; } -.olakefusion-page .features-wrap{ padding: 48px 20px 20px !important; } -.olakefusion-page .features-grid{ grid-template-columns: 1fr !important; gap: 28px !important; } -.olakefusion-page .features-card{ padding: 24px !important; } -.olakefusion-page .sec-title{ font-size: 28px !important; } -.olakefusion-page .bench-wrap{ padding: 60px 16px 30px !important; } -.olakefusion-page .cta-wrap{ padding: 0 16px !important; } -.olakefusion-page .cta-inner{ padding: 28px 24px !important; } -.olakefusion-page .cta-title{ width: auto !important; max-width: 100% !important; height: auto !important; font-size: 24px !important; } -.olakefusion-page .faq-wrap{ padding: 48px 20px 90px !important; } -.olakefusion-page .faq-title{ font-size: 26px !important; } -.olakefusion-page .footer-wrap{ padding: 48px 24px 0 !important; } -.olakefusion-page .footer-hero{ font-size: 28px !important; } -.olakefusion-page .footer-watermark{ font-size: 120px !important; } -} -@media (max-width: 560px){ -.olakefusion-page .hero-title{ font-size: 27px !important; } -.olakefusion-page .problem-grid{ grid-template-columns: 1fr !important; } -.olakefusion-page .arch-inner{ transform: scale(0.46); transform-origin: top center; } -.olakefusion-page .arch-wrap{ height: 118px !important; overflow: hidden; padding: 6px 12px !important; margin: 8px auto 8px !important; } -.olakefusion-page .bench-row{ padding-left: 16px !important; padding-right: 16px !important; } -.olakefusion-page .bench-cell-metric{ font-size: 13px !important; } -.olakefusion-page .faq-q{ font-size: 16px !important; } -.olakefusion-page .footer-watermark{ font-size: 84px !important; } +html:has(.olakefusion-page), +body:has(.olakefusion-page) { + height: auto; + min-height: 100%; +} +body:has(.olakefusion-page) { + margin: 0; + background: #f5f6fa; +} +.olakefusion-page * { + box-sizing: border-box; +} +.olakefusion-page a { + color: #3d4ff0; + text-decoration: none; +} +.olakefusion-page a:hover { + color: #2a38c4; +} +.olakefusion-page h1, +.olakefusion-page h2, +.olakefusion-page h3, +.olakefusion-page h4, +.olakefusion-page h5, +.olakefusion-page h6 { + margin: 0; + font-weight: inherit; +} +@keyframes floatBox { + 0%, + 100% { + transform: translateY(0); + } + 50% { + transform: translateY(-8px); + } +} +@keyframes travelDot { + 0% { + left: 0%; + opacity: 0; + } + 10% { + opacity: 1; + } + 90% { + opacity: 1; + } + 100% { + left: 100%; + opacity: 0; + } +} +@keyframes pulseRow { + 0%, + 100% { + background: #171e44; + } + 50% { + background: #2a3568; + } +} +@keyframes logoSpin { + 0%, + 100% { + transform: rotate(0deg) scale(1); + } + 50% { + transform: rotate(8deg) scale(1.08); + } +} +@keyframes fadeSlideIn { + from { + opacity: 0; + transform: translateX(14px); + } + to { + opacity: 1; + transform: translateX(0); + } +} +@keyframes wordFloat { + 0%, + 100% { + transform: translateY(0) rotate(var(--r, 0deg)); + } + 50% { + transform: translateY(-5px) rotate(var(--r, 0deg)); + } +} +@keyframes feedIn { + 0% { + transform: translateX(0) scale(1); + opacity: 1; + } + 65% { + opacity: 1; + } + 100% { + transform: translateX(120px) scale(0.3); + opacity: 0; + } +} +@keyframes compactAppear { + 0%, + 15% { + opacity: 0; + transform: scale(0.5); + } + 35%, + 85% { + opacity: 1; + transform: scale(1); + } + 100% { + opacity: 0; + transform: scale(1.1); + } +} +@keyframes fusionPulseRing { + 0%, + 100% { + box-shadow: 0 0 0 0 rgba(61, 79, 240, 0.35); + } + 50% { + box-shadow: 0 0 0 12px rgba(61, 79, 240, 0); + } +} +@keyframes lightUp1 { + 0%, + 8% { + background: #e4e6f0; + } + 16%, + 88% { + background: #a9d8f0; + } + 96%, + 100% { + background: #e4e6f0; + } +} +@keyframes lightUp2 { + 0%, + 32% { + background: #e4e6f0; + } + 40%, + 88% { + background: #a9d8f0; + } + 96%, + 100% { + background: #e4e6f0; + } +} +@keyframes lightUp3 { + 0%, + 56% { + background: #e4e6f0; + } + 64%, + 88% { + background: #a9d8f0; + } + 96%, + 100% { + background: #e4e6f0; + } +} +.olakefusion-page .nav-burger { + display: none; +} +@media (max-width: 900px) { + .olakefusion-page .scroll-pipeline { + display: none !important; + } + .olakefusion-page .nav-links, + .olakefusion-page .nav-star { + display: none !important; + } + .olakefusion-page .nav-star-mobile { + display: flex !important; + } + .olakefusion-page .nav-burger { + display: flex !important; + } + .olakefusion-page .nav-inner { + padding: 14px 20px !important; + } + .olakefusion-page .hero-wrap { + padding: 24px 20px 8px !important; + } + .olakefusion-page .hero-title { + font-size: 32px !important; + } + .olakefusion-page .hero-sub { + width: auto !important; + max-width: 100% !important; + height: auto !important; + font-size: 16px !important; + } + .olakefusion-page .hero-btns { + flex-wrap: wrap !important; + gap: 12px !important; + } + .olakefusion-page .problem-grid { + grid-template-columns: repeat(2, 1fr) !important; + } + .olakefusion-page .problem-wrap { + padding: 32px 20px 56px !important; + } + .olakefusion-page .problem-title { + font-size: 26px !important; + } + .olakefusion-page .features-wrap { + padding: 48px 20px 20px !important; + } + .olakefusion-page .features-grid { + grid-template-columns: 1fr !important; + gap: 28px !important; + } + .olakefusion-page .features-card { + padding: 24px !important; + } + .olakefusion-page .sec-title { + font-size: 28px !important; + } + .olakefusion-page .bench-wrap { + padding: 60px 16px 30px !important; + } + .olakefusion-page .cta-wrap { + padding: 0 16px !important; + } + .olakefusion-page .cta-inner { + padding: 28px 24px !important; + } + .olakefusion-page .cta-title { + width: auto !important; + max-width: 100% !important; + height: auto !important; + font-size: 24px !important; + } + .olakefusion-page .faq-wrap { + padding: 48px 20px 90px !important; + } + .olakefusion-page .faq-title { + font-size: 26px !important; + } + .olakefusion-page .footer-wrap { + padding: 48px 24px 0 !important; + } + .olakefusion-page .footer-hero { + font-size: 28px !important; + } + .olakefusion-page .footer-watermark { + font-size: 120px !important; + } +} +@media (max-width: 560px) { + .olakefusion-page .hero-title { + font-size: 27px !important; + } + .olakefusion-page .problem-grid { + grid-template-columns: 1fr !important; + } + .olakefusion-page .arch-inner { + transform: scale(0.46); + transform-origin: top center; + } + .olakefusion-page .arch-wrap { + height: 118px !important; + overflow: hidden; + padding: 6px 12px !important; + margin: 8px auto 8px !important; + } + .olakefusion-page .bench-row { + padding-left: 16px !important; + padding-right: 16px !important; + } + .olakefusion-page .bench-cell-metric { + font-size: 13px !important; + } + .olakefusion-page .faq-q { + font-size: 16px !important; + } + .olakefusion-page .footer-watermark { + font-size: 84px !important; + } } /* style-hover rules */ -.olakefusion-page .olakefusion-h0:hover{background:#F4F2EC !important;} -.olakefusion-page .olakefusion-h1:hover{color:#1B1E2B !important;} -.olakefusion-page .olakefusion-h2:hover{box-shadow: 0 2px 0 #23309E !important; transform: translateY(1px) !important;} -.olakefusion-page .olakefusion-h3:hover{box-shadow: 0 2px 0 #10173A !important; transform: translateY(1px) !important;} -.olakefusion-page .olakefusion-h4:hover{border-color:#3D4FF0 !important; color:#3D4FF0 !important;} +.olakefusion-page .olakefusion-h0:hover { + background: #f4f2ec !important; +} +.olakefusion-page .olakefusion-h1:hover { + color: #1b1e2b !important; +} +.olakefusion-page .olakefusion-h2:hover { + box-shadow: 0 2px 0 #23309e !important; + transform: translateY(1px) !important; +} +.olakefusion-page .olakefusion-h3:hover { + box-shadow: 0 2px 0 #10173a !important; + transform: translateY(1px) !important; +} +.olakefusion-page .olakefusion-h4:hover { + border-color: #3d4ff0 !important; + color: #3d4ff0 !important; +} diff --git a/src/components/landing/pages/olake-go.css b/src/components/landing/pages/olake-go.css index 3b55f9cc6..51b090e07 100644 --- a/src/components/landing/pages/olake-go.css +++ b/src/components/landing/pages/olake-go.css @@ -1,63 +1,355 @@ -html:has(.olakego-page), body:has(.olakego-page){ height: auto; min-height: 100%; } -html:has(.olakego-page){ scroll-snap-type: y proximity; } -body:has(.olakego-page){ margin: 0; background: #F5F6FA; font-family: 'Space Grotesk', sans-serif; } -.olakego-page *{ box-sizing: border-box; } -.olakego-page a{ color: #3D4FF0; text-decoration: none; } -.olakego-page a:hover{ color: #2A38C4; } -@keyframes floatBox{ 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } } -@keyframes travelDot{ 0% { left: 0%; opacity: 0; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { left: 100%; opacity: 0; } } -@keyframes pulseRow{ 0%, 100% { background: #171E44; } 50% { background: #2A3568; } } -@keyframes logoSpin{ 0%, 100% { transform: rotate(0deg) scale(1); } 50% { transform: rotate(8deg) scale(1.08); } } -@keyframes fadeSlideIn{ from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: translateX(0); } } -@keyframes wordFloat{ 0%, 100% { transform: translateY(0) rotate(var(--r, 0deg)); } 50% { transform: translateY(-5px) rotate(var(--r, 0deg)); } } -@keyframes feedIn{ 0% { transform: translateX(0) scale(1); opacity:1; } 65% { opacity:1; } 100% { transform: translateX(120px) scale(0.3); opacity:0; } } -@keyframes compactAppear{ 0%, 15% { opacity:0; transform:scale(0.5); } 35%, 85% { opacity:1; transform:scale(1); } 100% { opacity:0; transform:scale(1.1); } } -@keyframes fusionPulseRing{ 0%, 100% { box-shadow: 0 0 0 0 rgba(61,79,240,0.35); } 50% { box-shadow: 0 0 0 12px rgba(61,79,240,0); } } -@keyframes lightUp1{ 0%, 8% { background:#E4E6F0; } 16%, 88% { background:#A9D8F0; } 96%, 100% { background:#E4E6F0; } } -@keyframes lightUp2{ 0%, 32% { background:#E4E6F0; } 40%, 88% { background:#A9D8F0; } 96%, 100% { background:#E4E6F0; } } -@keyframes lightUp3{ 0%, 56% { background:#E4E6F0; } 64%, 88% { background:#A9D8F0; } 96%, 100% { background:#E4E6F0; } } -.olakego-page .nav-burger{ display: none; } -@media (max-width: 900px){ -.olakego-page .scroll-pipeline{ display: none !important; } -html:has(.olakego-page){ scroll-snap-type: none; } -.olakego-page .nav-links, .olakego-page .nav-star{ display: none !important; } -.olakego-page .nav-burger{ display: flex !important; } -.olakego-page .nav-inner{ padding: 14px 20px !important; } -.olakego-page .hero-wrap{ padding: 24px 20px 8px !important; } -.olakego-page .hero-title{ font-size: 32px !important; } -.olakego-page .hero-sub{ width: auto !important; max-width: 100% !important; height: auto !important; font-size: 16px !important; } -.olakego-page .hero-btns{ flex-wrap: wrap !important; gap: 12px !important; } -.olakego-page .problem-grid{ grid-template-columns: repeat(2, 1fr) !important; } -.olakego-page .problem-wrap{ padding: 32px 20px 56px !important; } -.olakego-page .problem-title{ font-size: 26px !important; } -.olakego-page .features-wrap{ padding: 48px 20px 20px !important; } -.olakego-page .features-grid{ grid-template-columns: 1fr !important; gap: 28px !important; } -.olakego-page .features-card{ padding: 24px !important; } -.olakego-page .sec-title{ font-size: 28px !important; } -.olakego-page .bench-wrap{ padding: 60px 16px 30px !important; } -.olakego-page .bench-stats{ grid-template-columns: 1fr !important; } -.olakego-page .cta-wrap{ padding: 0 16px !important; } -.olakego-page .cta-inner{ padding: 28px 24px !important; } -.olakego-page .cta-title{ width: auto !important; max-width: 100% !important; height: auto !important; font-size: 24px !important; } -.olakego-page .faq-wrap{ padding: 48px 20px 90px !important; } -.olakego-page .faq-title{ font-size: 26px !important; } -.olakego-page .footer-wrap{ padding: 48px 24px 0 !important; } -.olakego-page .footer-hero{ font-size: 28px !important; } -.olakego-page .footer-watermark{ font-size: 120px !important; } -} -@media (max-width: 560px){ -.olakego-page .hero-title{ font-size: 27px !important; } -.olakego-page .problem-grid{ grid-template-columns: 1fr !important; } -.olakego-page .arch-inner{ transform: scale(0.46); transform-origin: top center; } -.olakego-page .arch-wrap{ height: auto !important; overflow: visible; padding: 6px 12px !important; margin: 8px auto 8px !important; } -.olakego-page .bench-row{ padding-left: 16px !important; padding-right: 16px !important; } -.olakego-page .bench-cell-metric{ font-size: 13px !important; } -.olakego-page .faq-q{ font-size: 16px !important; } -.olakego-page .footer-watermark{ font-size: 84px !important; } +html:has(.olakego-page), +body:has(.olakego-page) { + height: auto; + min-height: 100%; +} +html:has(.olakego-page) { + scroll-snap-type: y proximity; +} +body:has(.olakego-page) { + margin: 0; + background: #f5f6fa; + font-family: 'Space Grotesk', sans-serif; +} +.olakego-page * { + box-sizing: border-box; +} +.olakego-page a { + color: #3d4ff0; + text-decoration: none; +} +.olakego-page a:hover { + color: #2a38c4; +} +@keyframes floatBox { + 0%, + 100% { + transform: translateY(0); + } + 50% { + transform: translateY(-8px); + } +} +@keyframes travelDot { + 0% { + left: 0%; + opacity: 0; + } + 10% { + opacity: 1; + } + 90% { + opacity: 1; + } + 100% { + left: 100%; + opacity: 0; + } +} +@keyframes pulseRow { + 0%, + 100% { + background: #171e44; + } + 50% { + background: #2a3568; + } +} +@keyframes logoSpin { + 0%, + 100% { + transform: rotate(0deg) scale(1); + } + 50% { + transform: rotate(8deg) scale(1.08); + } +} +@keyframes fadeSlideIn { + from { + opacity: 0; + transform: translateX(14px); + } + to { + opacity: 1; + transform: translateX(0); + } +} +@keyframes wordFloat { + 0%, + 100% { + transform: translateY(0) rotate(var(--r, 0deg)); + } + 50% { + transform: translateY(-5px) rotate(var(--r, 0deg)); + } +} +@keyframes feedIn { + 0% { + transform: translateX(0) scale(1); + opacity: 1; + } + 65% { + opacity: 1; + } + 100% { + transform: translateX(120px) scale(0.3); + opacity: 0; + } +} +@keyframes compactAppear { + 0%, + 15% { + opacity: 0; + transform: scale(0.5); + } + 35%, + 85% { + opacity: 1; + transform: scale(1); + } + 100% { + opacity: 0; + transform: scale(1.1); + } +} +@keyframes fusionPulseRing { + 0%, + 100% { + box-shadow: 0 0 0 0 rgba(61, 79, 240, 0.35); + } + 50% { + box-shadow: 0 0 0 12px rgba(61, 79, 240, 0); + } +} +@keyframes lightUp1 { + 0%, + 8% { + background: #e4e6f0; + } + 16%, + 88% { + background: #a9d8f0; + } + 96%, + 100% { + background: #e4e6f0; + } +} +@keyframes lightUp2 { + 0%, + 32% { + background: #e4e6f0; + } + 40%, + 88% { + background: #a9d8f0; + } + 96%, + 100% { + background: #e4e6f0; + } +} +@keyframes lightUp3 { + 0%, + 56% { + background: #e4e6f0; + } + 64%, + 88% { + background: #a9d8f0; + } + 96%, + 100% { + background: #e4e6f0; + } +} +.olakego-page .nav-burger { + display: none; +} +@media (max-width: 900px) { + .olakego-page .scroll-pipeline { + display: none !important; + } + html:has(.olakego-page) { + scroll-snap-type: none; + } + .olakego-page .nav-links { + display: none !important; + } + .olakego-page .nav-star { + padding: 5px 8px !important; + gap: 5px !important; + } + .olakego-page .nav-star img { + height: 22px !important; + width: 21px !important; + } + .olakego-page .nav-star-count { + display: none !important; + } + .olakego-page .nav-slack img { + height: 26px !important; + width: 27px !important; + } + .olakego-page .nav-burger { + display: flex !important; + } + .olakego-page .nav-inner { + padding: 14px 20px !important; + } + .olakego-page .hero-wrap { + padding: 24px 20px 8px !important; + } + .olakego-page .hero-title { + font-size: 32px !important; + } + .olakego-page .hero-sub { + width: auto !important; + max-width: 100% !important; + height: auto !important; + font-size: 16px !important; + } + .olakego-page .hero-btns { + flex-wrap: wrap !important; + gap: 12px !important; + } + .olakego-page .problem-grid { + grid-template-columns: repeat(2, 1fr) !important; + } + .olakego-page .problem-wrap { + padding: 32px 20px 56px !important; + } + .olakego-page .problem-title { + font-size: 26px !important; + } + .olakego-page .features-wrap { + padding: 48px 20px 20px !important; + } + .olakego-page .features-grid { + grid-template-columns: 1fr !important; + gap: 28px !important; + } + .olakego-page .features-card { + padding: 24px !important; + } + .olakego-page .sec-title { + font-size: 28px !important; + } + .olakego-page .bench-wrap { + padding: 60px 16px 30px !important; + } + .olakego-page .bench-stats { + grid-template-columns: 1fr !important; + } + .olakego-page .cta-wrap { + padding: 0 16px !important; + } + .olakego-page .cta-inner { + padding: 28px 24px !important; + } + .olakego-page .cta-title { + width: auto !important; + max-width: 100% !important; + height: auto !important; + font-size: 24px !important; + } + .olakego-page .faq-wrap { + padding: 48px 20px 90px !important; + } + .olakego-page .faq-title { + font-size: 26px !important; + } + .olakego-page .footer-wrap { + padding: 48px 24px 0 !important; + } + .olakego-page .footer-hero { + font-size: 28px !important; + } + .olakego-page .footer-watermark { + font-size: 120px !important; + } +} +@media (max-width: 560px) { + .olakego-page .hero-title { + font-size: 27px !important; + } + .olakego-page .problem-grid { + grid-template-columns: 1fr !important; + } + .olakego-page .arch-inner { + display: flex !important; + flex-direction: column !important; + align-items: center !important; + gap: 16px !important; + height: auto !important; + transform: none !important; + } + .olakego-page .arch-inner > div { + transform: none !important; + justify-self: auto !important; + } + .olakego-page .arch-sources { + flex-direction: row !important; + flex-wrap: wrap !important; + justify-content: center !important; + max-width: 300px; + gap: 8px !important; + } + .olakego-page .arch-src-label { + flex-basis: 100% !important; + } + .olakego-page .arch-node::before, + .olakego-page #opt-node::before { + content: '\2193'; + display: block; + text-align: center; + color: #8ea0ff; + font-size: 22px; + line-height: 1; + margin-bottom: 4px; + } + .olakego-page #opt-node { + align-items: center !important; + } + .olakego-page .arch-wrap { + height: auto !important; + overflow: visible; + padding: 6px 12px !important; + margin: 8px auto 8px !important; + } + .olakego-page .problem-cloud { + height: 300px !important; + } + .olakego-page .problem-cloud span { + font-size: 13px !important; + } + .olakego-page .bench-row { + padding-left: 16px !important; + padding-right: 16px !important; + } + .olakego-page .bench-cell-metric { + font-size: 13px !important; + } + .olakego-page .faq-q { + font-size: 16px !important; + } + .olakego-page .footer-watermark { + font-size: 84px !important; + } } /* style-hover rules */ -.olakego-page .olakego-h0:hover{background:#F4F2EC !important;} -.olakego-page .olakego-h1:hover{color:#1B1E2B !important;} -.olakego-page .olakego-h2:hover{box-shadow: 0 2px 0 #23309E !important; transform: translateY(1px) !important;} -.olakego-page .olakego-h3:hover{box-shadow: 0 2px 0 #10173A !important; transform: translateY(1px) !important;} +.olakego-page .olakego-h0:hover { + background: #f4f2ec !important; +} +.olakego-page .olakego-h1:hover { + color: #1b1e2b !important; +} +.olakego-page .olakego-h2:hover { + box-shadow: 0 2px 0 #23309e !important; + transform: translateY(1px) !important; +} +.olakego-page .olakego-h3:hover { + box-shadow: 0 2px 0 #10173a !important; + transform: translateY(1px) !important; +} diff --git a/src/components/landing/pages/olake-home.css b/src/components/landing/pages/olake-home.css index 84216c16c..ad4ba48ac 100644 --- a/src/components/landing/pages/olake-home.css +++ b/src/components/landing/pages/olake-home.css @@ -1,53 +1,250 @@ -html:has(.olakehome-page), body:has(.olakehome-page){ height: auto; min-height: 100%; scroll-behavior: smooth; } -body:has(.olakehome-page){ margin: 0; background: #f0f2fa; } -.olakehome-page *{ box-sizing: border-box; } -.olakehome-page a{ color: #193AE6; text-decoration: none; } -.olakehome-page a:hover{ color: #1430b8; } -.olakehome-page ::selection{ background: #193AE6; color: #000000; } -@keyframes gridPan{ from { background-position: 0 0; } to { background-position: 0 -80px; } } -@keyframes blink{ 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } } -/* Seamless marquee: the track holds N identical copies and scrolls left by exactly - one copy's width. Each group's trailing padding matches its gap so the track is - exactly N copies wide; `--marquee-copies` comes from React's actual group count. */ -.olakehome-page .olakehome-marquee{ - display: flex; - width: max-content; - will-change: transform; - animation: tickerScroll 26s linear infinite; - -webkit-animation: tickerScroll 26s linear infinite; -} -.olakehome-page .olakehome-marquee-group{ - --marquee-gap: 28px; - display: flex; - gap: var(--marquee-gap); - padding-right: var(--marquee-gap); - flex-shrink: 0; -} -@keyframes tickerScroll{ - from { transform: translateX(0); } - to { transform: translateX(calc(-100% / var(--marquee-copies, 4))); } -} -@media (prefers-reduced-motion: reduce){ - .olakehome-page .olakehome-marquee{ animation: none; } -} -@keyframes glowPulse{ 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } } -@keyframes floatUp{ from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } } -@keyframes barGrow{ from { transform: scaleY(0.15); } to { transform: scaleY(1); } } -@keyframes kenburns{ 0% { transform: scale(1) translate(0,0); } 100% { transform: scale(1.14) translate(-2%,-2%); } } -@keyframes chipBlink{ - 0%, 100% { background:rgba(25,58,230,0.12); border-color:rgba(120,140,255,0.4); color:#AEB9FF; box-shadow:0 0 0 0 rgba(25,58,230,0); } - 50% { background:rgba(25,58,230,0.32); border-color:#6E7CFF; color:#ffffff; box-shadow:0 0 16px 1px rgba(79,91,255,0.5); } - } -@keyframes hubGlow{ 0%, 100% { box-shadow:0 0 0 10px rgba(25, 58, 230, 0.06), 0 0 40px -10px rgba(25, 58, 230, 0.4); } 50% { box-shadow:0 0 0 16px rgba(25, 58, 230, 0.12), 0 0 80px -4px rgba(25, 58, 230, 0.85); } } -@keyframes nodeBlink{ 0%, 80%, 100% { box-shadow:0 8px 22px -10px rgba(0,0,0,0.18); transform:scale(1); } 10% { box-shadow:0 0 0 4px rgba(25,58,230,0.22), 0 12px 28px -8px rgba(25,58,230,0.55); transform:scale(1.07); } } +html:has(.olakehome-page), +body:has(.olakehome-page) { + height: auto; + min-height: 100%; + scroll-behavior: smooth; +} +body:has(.olakehome-page) { + margin: 0; + background: #f0f2fa; +} +.olakehome-page * { + box-sizing: border-box; +} +.olakehome-page a { + color: #193ae6; + text-decoration: none; +} +.olakehome-page a:hover { + color: #1430b8; +} +.olakehome-page ::selection { + background: #193ae6; + color: #000000; +} +@keyframes gridPan { + from { + background-position: 0 0; + } + to { + background-position: 0 -80px; + } +} +@keyframes blink { + 0%, + 49% { + opacity: 1; + } + 50%, + 100% { + opacity: 0; + } +} +@keyframes tickerScroll { + from { + transform: translateX(0); + } + to { + transform: translateX(-50%); + } +} +@keyframes glowPulse { + 0%, + 100% { + opacity: 0.5; + } + 50% { + opacity: 1; + } +} +@keyframes floatUp { + from { + opacity: 0; + transform: translateY(16px); + } + to { + opacity: 1; + transform: translateY(0); + } +} +@keyframes barGrow { + from { + transform: scaleY(0.15); + } + to { + transform: scaleY(1); + } +} +@keyframes kenburns { + 0% { + transform: scale(1) translate(0, 0); + } + 100% { + transform: scale(1.14) translate(-2%, -2%); + } +} +@keyframes chipBlink { + 0%, + 100% { + background: rgba(25, 58, 230, 0.12); + border-color: rgba(120, 140, 255, 0.4); + color: #aeb9ff; + box-shadow: 0 0 0 0 rgba(25, 58, 230, 0); + } + 50% { + background: rgba(25, 58, 230, 0.32); + border-color: #6e7cff; + color: #ffffff; + box-shadow: 0 0 16px 1px rgba(79, 91, 255, 0.5); + } +} +@keyframes hubGlow { + 0%, + 100% { + box-shadow: + 0 0 0 10px rgba(25, 58, 230, 0.06), + 0 0 40px -10px rgba(25, 58, 230, 0.4); + } + 50% { + box-shadow: + 0 0 0 16px rgba(25, 58, 230, 0.12), + 0 0 80px -4px rgba(25, 58, 230, 0.85); + } +} +@keyframes nodeBlink { + 0%, + 80%, + 100% { + box-shadow: 0 8px 22px -10px rgba(0, 0, 0, 0.18); + transform: scale(1); + } + 10% { + box-shadow: + 0 0 0 4px rgba(25, 58, 230, 0.22), + 0 12px 28px -8px rgba(25, 58, 230, 0.55); + transform: scale(1.07); + } +} +.olakehome-page .nav-burger { + display: none; +} +.olakehome-page .nav-gh-m { + display: none; +} +.olakehome-page .arch-mobile { + display: none; +} +@media (max-width: 860px) { + .olakehome-page .nav-gh-m { + display: flex !important; + } + .olakehome-page .nav-actions { + gap: 12px !important; + } + .olakehome-page .arch-desktop { + display: none !important; + } + .olakehome-page .arch-mobile { + display: flex !important; + } + .olakehome-page .nav-links, + .olakehome-page .nav-star { + display: none !important; + } + .olakehome-page .nav-burger { + display: flex !important; + } + .olakehome-page .nav-inner { + padding-left: 18px !important; + padding-right: 18px !important; + } + .olakehome-page [data-r~='stack'] { + grid-template-columns: 1fr !important; + } + .olakehome-page [data-r~='pad'] { + padding-left: 22px !important; + padding-right: 22px !important; + } + .olakehome-page [data-r~='padrow'] { + padding-left: 22px !important; + padding-right: 22px !important; + } + .olakehome-page [data-r~='navwrap'] { + padding-left: 18px !important; + padding-right: 18px !important; + } + .olakehome-page [data-r~='navmenu'] { + display: none !important; + } + .olakehome-page [data-r~='herohead'] { + font-size: 40px !important; + } + .olakehome-page [data-r~='bighead'] { + font-size: 32px !important; + margin-bottom: 40px !important; + } + .olakehome-page [data-r~='fixedhead'] { + width: auto !important; + max-width: 100% !important; + height: auto !important; + font-size: 34px !important; + } + .olakehome-page [data-r~='ctapad'] { + padding: 44px 24px !important; + } + .olakehome-page [data-r~='hero'] { + padding-top: 72px !important; + padding-bottom: 64px !important; + gap: 40px !important; + } + .olakehome-page [data-r~='statrow'] { + flex-direction: column !important; + align-items: flex-start !important; + gap: 22px !important; + } + .olakehome-page [data-r~='bignum'] { + font-size: 56px !important; + } + .olakehome-page [data-r~='cardpad'] { + padding: 30px 26px !important; + } +} /* style-hover rules */ -.olakehome-page .olakehome-h0:hover{background:rgba(0, 0, 0, 0.05) !important;} -.olakehome-page .olakehome-h1:hover{color:#000000 !important;} -.olakehome-page .olakehome-h2:hover{transform:translateY(4px) !important; box-shadow:0 0 0 #5762da, inset 0 1px 0 rgba(0, 0, 0, 0.2) !important;} -.olakehome-page .olakehome-h3:hover{transform:translateY(6px) !important; box-shadow:0 0 0 #5762da, inset 0 1px 0 rgba(0, 0, 0, 0.2) !important;} -.olakehome-page .olakehome-h4:hover{transform:translateY(6px) !important; box-shadow:0 0 0 rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(0, 0, 0, 0.08) !important;} -.olakehome-page .olakehome-h5:hover{transform:translateY(-4px) !important; box-shadow:0 32px 60px -26px rgba(25, 58, 230, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.22) !important;} -.olakehome-page .olakehome-h6:hover{opacity:0.72 !important;} -.olakehome-page .olakehome-h7:hover{transform:translateY(-6px) !important; box-shadow:0 34px 60px -28px rgba(0,0,0,0.55) !important;} -.olakehome-page .olakehome-h8:hover{opacity:0.65 !important;} +.olakehome-page .olakehome-h0:hover { + background: #f4f2ec !important; +} +.olakehome-page .olakehome-h1:hover { + color: #1b1e2b !important; +} +.olakehome-page .olakehome-h2:hover { + transform: translateY(6px) !important; + box-shadow: + 0 0 0 #5762da, + inset 0 1px 0 rgba(0, 0, 0, 0.2) !important; +} +.olakehome-page .olakehome-h3:hover { + transform: translateY(6px) !important; + box-shadow: + 0 0 0 rgba(0, 0, 0, 0.1), + inset 0 1px 0 rgba(0, 0, 0, 0.08) !important; +} +.olakehome-page .olakehome-h4:hover { + transform: translateY(-4px) !important; + box-shadow: + 0 32px 60px -26px rgba(25, 58, 230, 0.55), + inset 0 1px 0 rgba(255, 255, 255, 0.22) !important; +} +.olakehome-page .olakehome-h5:hover { + background: #eef1ff !important; +} +.olakehome-page .olakehome-h6:hover { + opacity: 0.72 !important; +} +.olakehome-page .olakehome-h7:hover { + transform: translateY(-6px) !important; + box-shadow: 0 34px 60px -28px rgba(0, 0, 0, 0.55) !important; +} +.olakehome-page .olakehome-h8:hover { + opacity: 0.65 !important; +} diff --git a/src/components/landing/pages/overrides.css b/src/components/landing/pages/overrides.css index 67c25d85d..d4e99d857 100644 --- a/src/components/landing/pages/overrides.css +++ b/src/components/landing/pages/overrides.css @@ -1,18 +1,18 @@ -/* ========================================================================= - Hand-maintained overrides for the three literal-ported landing pages. - - IMPORTANT: olake-go.css / olake-fusion.css / olake-home.css are GENERATED - from the design templates and are overwritten on every regeneration. Put - any deliberate deviation from the designs HERE instead, so it survives. - ========================================================================= */ +/* Kills the design's `scroll-snap-type: y proximity` — same specificity as the + generated rule, and this file is imported after it. */ +html:has(.olakego-page) { + scroll-snap-type: none; +} -/* ------------------------------------------------------------------------- - / (v2 homepage) — USER STORIES cards. +/* The design animates the full-width logo marquee unconditionally. */ +@media (prefers-reduced-motion: reduce) { + .olakehome-page .olakehome-marquee { + animation: none; + } +} - The design draws these as plain
s. They are converted to links to - each customer's story (see postprocess_pages.js), so they need a hover - affordance — the design has none because they weren't clickable. - ------------------------------------------------------------------------- */ +/* USER STORIES cards: plain
s in the design, converted to whole-card + links by the pipeline's postprocess.js, so they need a hover affordance. */ .olakehome-page a[aria-label='Read the customer story'] { text-decoration: none; transition: transform 0.2s ease, box-shadow 0.2s ease; @@ -23,15 +23,9 @@ box-shadow: 0 32px 60px -26px rgba(0, 0, 0, 0.6); } -/* ------------------------------------------------------------------------- - Shared footer hover states. - - All three landing pages render one canonical footer, so its hover styles - live here rather than in the per-page generated stylesheets (whose hover - classes are page-scoped, e.g. `.olakego-h0`). The Go design's social boxes - are unlinked
s with no hover at all; these match the Fusion design, - which implements the same boxes as real links. - ------------------------------------------------------------------------- */ +/* Shared footer hovers: all three pages render one canonical footer, so these + can't live in the per-page generated sheets (hover classes are page-scoped). + Values match the Fusion design, the only one with the boxes as real links. */ .olake-design-page .olake-footer-social { transition: border-color 0.15s ease, color 0.15s ease; } @@ -49,22 +43,9 @@ color: #3d4ff0 !important; } -/* ------------------------------------------------------------------------- - /olake-go — benchmark table horizontal-overflow "dead zone". - - The design sizes the table's inner wrapper to `min-width: 860px`, while - `.bench-wrap` is `max-width:1080px` with 64px side padding. So the table - only fits without scrolling at viewports >= 988px (1080 - 128 = 952, and - viewport - 128 >= 860). The design's own breakpoint drops that padding to - 16px at <= 900px, which makes it fit again (900 - 32 = 868 >= 860). - - That leaves ~901-987px where the table is wider than its container and - clips its last column. This closes that gap by applying the narrower side - padding across the dead zone too (987 - 32 = 955 >= 860). - - Only the horizontal padding is touched, so the design's vertical rhythm - above the 900px breakpoint is preserved exactly. - ------------------------------------------------------------------------- */ +/* The benchmark table is min-width:860px inside a 64px-padded wrap, and the + design's own 900px breakpoint drops that padding to 16px. Between 901-987px + neither applies and the last column clips, so close the gap here. */ @media (max-width: 987px) and (min-width: 901px) { .olakego-page .bench-wrap { padding-left: 16px !important; @@ -72,13 +53,8 @@ } } -/* ------------------------------------------------------------------------- - / (v2 homepage) — footer responsive rules. - - The homepage uses the OLake Go footer verbatim (all three landing pages - share it), but the v2 design ships no media queries at all, so the Go - design's footer breakpoints have to be carried over by hand. - ------------------------------------------------------------------------- */ +/* The homepage renders the OLake Go footer verbatim, but the v2 design has no + footer breakpoints, so the Go design's are carried over by hand. */ @media (max-width: 900px) { .olakehome-page .footer-wrap { padding: 48px 24px 0 !important; diff --git a/src/components/landing/pages/useFusionLogic.ts b/src/components/landing/pages/useFusionLogic.ts index 446b3637b..279337811 100644 --- a/src/components/landing/pages/useFusionLogic.ts +++ b/src/components/landing/pages/useFusionLogic.ts @@ -1,5 +1,5 @@ // @ts-nocheck -import { useState, useRef, useEffect, useMemo } from 'react' +import { useState, useRef, useEffect } from 'react' export function useFusionLogic(props = {}) { const [state, setStateRaw] = useState({ @@ -182,7 +182,7 @@ export function useFusionLogic(props = {}) { const list = [ { title: 'TIERED COMPACTION', - body: 'Trigger-based tiers instead of one blunt job, so light cleanup runs constantly and deep rewrites only run when they\u2019re actually needed.', + body: 'Trigger-based tiers instead of one blunt job, so lightweight compaction can run constantly and deep rewrites only run when they’re actually needed.', tag: 'tiered' }, { diff --git a/src/components/landing/pages/useGoLogic.ts b/src/components/landing/pages/useGoLogic.ts index 8e298c55d..df3eb06a2 100644 --- a/src/components/landing/pages/useGoLogic.ts +++ b/src/components/landing/pages/useGoLogic.ts @@ -1,5 +1,5 @@ // @ts-nocheck -import { useState, useRef, useEffect, useMemo } from 'react' +import { useState, useRef, useEffect } from 'react' import { CONNECTORS, CONNECTOR_BENCHMARKS, @@ -43,7 +43,7 @@ export function useGoLogic(props = {}) { }, { q: 'What data platforms and tools does OLake integrate with?', - a: 'As of now, we integrate with Apache Iceberg as a destination. You can query it from most big data platforms like Snowflake, Databricks, Redshift and BigQuery.' + a: 'As of now, we integrate with Apache Iceberg and S3 as destinations. You can query it using popular query engines like Spark, AWS Athena, Snowflake, Databricks, and BigQuery.' } ], openFaq: -1, @@ -81,8 +81,25 @@ export function useGoLogic(props = {}) { const connector = CONNECTORS[stateRef.current.activeSource] || CONNECTORS[0] const dataset = stateRef.current.benchmarkMode === 'cdc' ? CONNECTOR_CDC_BENCHMARKS : CONNECTOR_BENCHMARKS - const bench = dataset[connector.id] + const bench = dataset[connector.id] || {} const comps = competitorKeys(bench) + const def = { + comps: comps.map((key) => TOOLS[key].name), + rows: BENCHMARK_METRICS.map((metric) => { + const row = bench[metric] || {} + const isCmp = metric === 'comparison' + return { + label: CONNECTOR_METRIC_LABELS[metric], + cmp: isCmp, + // OLake is the baseline for the comparison row, so it shows a dash + // rather than a multiplier against itself. + olake: isCmp ? '–' : row.olake, + comps: comps.map((key) => row[key] ?? '-') + } + }) + } + const comingSoon = !bench.hasData + const sourceName = connector.name const cols = [ { name: 'Metrics', @@ -102,8 +119,8 @@ export function useGoLogic(props = {}) { bg: GB, align: 'center' }, - ...comps.map((key) => ({ - name: TOOLS[key].name, + ...def.comps.map((name) => ({ + name, sub: '', hasSub: false, olake: false, @@ -118,24 +135,16 @@ export function useGoLogic(props = {}) { weight: type === 'olake' || type === 'cmp' ? 700 : 500, bg: type === 'olake' ? GB : 'transparent' }) - const table = BENCHMARK_METRICS.map((metric) => { - const row = bench[metric] - const isCmp = metric === 'comparison' - return { - label: CONNECTOR_METRIC_LABELS[metric], - sub: - metric === 'cost' - ? 'OLake is OSS and self-hosted — only pay for your infrastructure.' - : '', - hasSub: metric === 'cost', - // OLake is the baseline for the comparison row, so it shows a dash, not a multiplier. - cells: [ - cell(isCmp ? '–' : row.olake, 'olake'), - ...comps.map((key) => cell(row[key] ?? '-', isCmp ? 'cmp' : 'normal')) - ] - } - }) - return { cols, table, comingSoon: !bench.hasData, sourceName: connector.name } + const table = def.rows.map((r) => ({ + label: r.label, + sub: + r.label === 'Cost' + ? 'OLake is OSS and self-hosted — only pay for your infrastructure.' + : '', + hasSub: r.label === 'Cost', + cells: [cell(r.olake, 'olake'), ...r.comps.map((v) => cell(v, r.cmp ? 'cmp' : 'normal'))] + })) + return { cols, table, comingSoon, sourceName } } const selectBenchmarkMode = (mode) => { @@ -216,7 +225,7 @@ export function useGoLogic(props = {}) { icebergStyle, problemSentences: [ { - top: 27, + top: 22, left: 42, rot: -3, delay: 0, diff --git a/src/components/landing/pages/useHomeLogic.ts b/src/components/landing/pages/useHomeLogic.ts index c4ac68ccf..d97761336 100644 --- a/src/components/landing/pages/useHomeLogic.ts +++ b/src/components/landing/pages/useHomeLogic.ts @@ -1,5 +1,5 @@ // @ts-nocheck -import { useState, useRef, useEffect, useMemo } from 'react' +import { useState, useRef, useEffect } from 'react' export function useHomeLogic(props = {}) { const [state, setStateRaw] = useState({ @@ -7,6 +7,7 @@ export function useHomeLogic(props = {}) { contributorsOpen: false, productOpen: false, docsOpen: false, + mobileMenuOpen: false, advantage: 'go' }) const stateRef = useRef(state) @@ -50,6 +51,10 @@ export function useHomeLogic(props = {}) { setState({ contributorsOpen: false }) } + const toggleMobileMenu = () => { + setState((s) => ({ mobileMenuOpen: !s.mobileMenuOpen })) + } + const renderVals = () => { const isGo = stateRef.current.advantage === 'go' const activeTab = '#193AE6' @@ -94,15 +99,57 @@ export function useHomeLogic(props = {}) { ")), url('" + advImg + "')" - // w/h are the files' intrinsic sizes, set on the so the marquee reserves - // space before the logos load. + // w/h are intrinsic sizes, so the marquee row reserves space before decode. + // maxH/maxW are the design's per-tile boxes; Lending Kart's is larger. const logos = [ - { src: '/img/landing/v2/logo-bitespeed.webp', name: 'Bitespeed', w: 340, h: 65 }, - { src: '/img/landing/v2/logo-xeno.webp', name: 'Xeno', w: 176, h: 88 }, - { src: '/img/landing/v2/logo-cordial.webp', name: 'Cordial', w: 244, h: 88 }, - { src: '/img/landing/v2/logo-lendingkart.webp', name: 'Lending Kart', w: 168, h: 88 }, - { src: '/img/landing/v2/logo-astrotalk.webp', name: 'Astro Talk', w: 246, h: 88 }, - { src: '/img/landing/v2/logo-physicswallah.webp', name: 'Physics Wallah', w: 246, h: 88 } + { + src: '/img/landing/v2/logo-bitespeed.webp', + name: 'Bitespeed', + w: 340, + h: 65, + maxH: '44px', + maxW: '170px' + }, + { + src: '/img/landing/v2/logo-xeno.webp', + name: 'Xeno', + w: 176, + h: 88, + maxH: '44px', + maxW: '170px' + }, + { + src: '/img/landing/v2/logo-cordial.webp', + name: 'Cordial', + w: 244, + h: 88, + maxH: '44px', + maxW: '170px' + }, + { + src: '/img/landing/v2/logo-lendingkart.webp', + name: 'Lending Kart', + w: 168, + h: 88, + maxH: '62px', + maxW: '230px' + }, + { + src: '/img/landing/v2/logo-astrotalk.webp', + name: 'Astro Talk', + w: 246, + h: 88, + maxH: '44px', + maxW: '170px' + }, + { + src: '/img/landing/v2/logo-physicswallah.webp', + name: 'Physics Wallah', + w: 246, + h: 88, + maxH: '44px', + maxW: '170px' + } ] const ticker = [ 'Postgres', @@ -133,6 +180,8 @@ export function useHomeLogic(props = {}) { closeResources: () => closeResources(), openContributors: () => openContributors(), closeContributors: () => closeContributors(), + mobileMenuOpen: stateRef.current.mobileMenuOpen, + toggleMobileMenu: () => toggleMobileMenu(), terminalLines: [ { @@ -188,6 +237,23 @@ export function useHomeLogic(props = {}) { tickerLoop: [...ticker, ...ticker], + // Shared by the desktop canvas and the `.arch-mobile` stack below 860px. + archSources: ticker.slice(0, 8), + archGoChips: [{ label: 'Full Load' }, { label: 'CDC' }, { label: 'Incremental' }], + archFusionChips: [ + { label: 'Compaction' }, + { label: 'Cleanup', soon: true }, + { label: 'Logs & metrics' } + ], + archDestinations: [ + { + src: '/img/landing/v2/connector-iceberg.webp', + name: 'Iceberg', + sub: 'Tables & metadata' + }, + { src: '/img/landing/shared/parquet-icon.webp', name: 'Parquet on S3', sub: '' } + ], + engines: [ { tag: '// OLAKE GO', @@ -221,8 +287,7 @@ export function useHomeLogic(props = {}) { } ], - // Copies of the logo set; enough to keep the marquee covered on wide screens. - logoGroups: Array.from({ length: 4 }, () => logos), + logosLoop: [...logos, ...logos], selectGo: () => setState({ advantage: 'go' }), selectFusion: () => setState({ advantage: 'fusion' }), @@ -251,7 +316,7 @@ export function useHomeLogic(props = {}) { num: '02', kicker: 'OPEN', title: 'Built on open standards', - body: 'Write directly to Apache Iceberg or Parquet, with support for AWS Glue, Hive Metastore, and REST catalogs like Nessie, Polaris, and Unity. ' + body: 'Write directly to Apache Iceberg or Parquet, with support for AWS Glue, Hive Metastore, JDBC/SQL and REST catalogs like Nessie, Polaris, and Unity.' }, { stickyTop: 180, @@ -269,7 +334,7 @@ export function useHomeLogic(props = {}) { num: '04', kicker: 'MAINTAINED', title: 'Keep tables fast as data keeps growing', - body: 'Automated compaction and delete-file cleanup keep query performance and storage costs in check as you scale.' + body: 'Schedule and automate compaction and delete-file cleanup to keep query performance and storage costs in check as you scale.' } ], diff --git a/src/css/custom.css b/src/css/custom.css index ff1ace7ec..5d51c2cf6 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -733,34 +733,27 @@ html[data-theme='dark'] .benchmark-table-no-border thead th { margin-right: calc(-1 * var(--ifm-menu-link-padding-horizontal)); } -/* Translucent Navbar Styling */ +/* SiteNavbar (@theme/Navbar/Content) brings its own height, background and border. + This wrapper is kept only because NavbarLayout renders the mobile sidebar inside + it, so it must paint nothing behind SiteNavbar's translucent bar. */ .navbar { - /* Sticky positioning for scroll behavior + stacking context for backdrop-filter */ position: sticky !important; top: 0; z-index: 200; - isolation: isolate; - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - /* Backdrop blur effect */ - -webkit-backdrop-filter: blur(20px); - backdrop-filter: blur(20px); - border-bottom: 1px solid #e9e9e9; - background-color: rgba(255, 255, 255, 0.8) !important; - height: 72px; - display: flex; - align-items: center; + height: auto; + min-height: 0; + padding: 0; + display: block; + background: transparent !important; + backdrop-filter: none; + -webkit-backdrop-filter: none; + border-bottom: 0; + box-shadow: none; } html[data-theme='dark'] .navbar { - background-color: rgba(0, 0, 0, 0.8) !important; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); -} - -.navbar__inner { - display: flex; - align-items: center; - height: 100%; + background: transparent !important; + border-bottom: 0; } /* Override Infima's internal 996px breakpoint to extend mobile navbar up to xl (1280px) */ @@ -1211,20 +1204,10 @@ html[data-theme='dark'] .tabs-container > ul.tabs { /* ========================================================================= OLAKE DESIGN PAGES — the three landing routes are literal ports of the - supplied design bundles. Each renders the design's OWN navbar and footer - inline, so Docusaurus' chrome is hidden on them, and Infima's element - defaults are neutralised so the design's own rules/inline styles apply - exactly as authored. Everything here is scoped to `.olake-design-page`. + supplied design bundles: Infima's element defaults are neutralised so the + design's own rules/inline styles apply exactly as authored. Everything here + is scoped to `.olake-design-page`. ========================================================================= */ -/* The three landing pages render their own shared navbar inline - (src/components/landing/Navbar/SiteNavbar.tsx), so Docusaurus' navbar is - hidden on those routes only. Every other route — /docs, /blog, etc. — keeps - the standard navbar driven by docusaurus.config.js, untouched. */ -body:has(.olake-design-page) .navbar, -body:has(.olake-design-page) .navbar-sidebar, -body:has(.olake-design-page) .navbar-sidebar__backdrop { - display: none !important; -} /* Infima sets `html { font: /1.65 }`, so every element inherits line-height 1.65. The designs were authored against the browser default diff --git a/src/hooks/useGetReleases.ts b/src/hooks/useGetReleases.ts index d55adc96a..4f9f8c1cf 100644 --- a/src/hooks/useGetReleases.ts +++ b/src/hooks/useGetReleases.ts @@ -4,21 +4,24 @@ import { IGlobalData } from '@site/src/types/download' const STARS_API_URL = 'https://api.github.com/repos/datazip-inc/olake' const STARS_CACHE_KEY = 'olake:gh-stars' -const STARS_TTL_MS = 6 * 60 * 60 * 1000 +const STARS_TTL_MS = 24 * 60 * 60 * 1000 let starsRequest: Promise | null = null -const readCachedStars = (): number | null => { +const readStoredStars = (): { value: number; at: number } | null => { try { - const raw = window.sessionStorage.getItem(STARS_CACHE_KEY) - if (!raw) return null - const { value, at } = JSON.parse(raw) as { value: number; at: number } - return Date.now() - at < STARS_TTL_MS ? value : null + const raw = window.localStorage.getItem(STARS_CACHE_KEY) + return raw ? JSON.parse(raw) : null } catch { - return null + return null // private mode, storage disabled, or corrupt entry } } +const readCachedStars = (): number | null => { + const stored = readStoredStars() + return stored && Date.now() - stored.at < STARS_TTL_MS ? stored.value : null +} + const fetchStars = (): Promise => { if (starsRequest) return starsRequest starsRequest = fetch(STARS_API_URL) @@ -27,14 +30,14 @@ const fetchStars = (): Promise => { const value: number | null = data?.stargazers_count ?? null if (value) { try { - window.sessionStorage.setItem(STARS_CACHE_KEY, JSON.stringify({ value, at: Date.now() })) + window.localStorage.setItem(STARS_CACHE_KEY, JSON.stringify({ value, at: Date.now() })) } catch { /* private mode or storage disabled — just skip caching */ } } return value }) - .catch(() => null) // offline or rate-limited: callers keep their fallback + .catch(() => null) // offline or rate-limited: fall back to the stale value return starsRequest } @@ -58,6 +61,10 @@ const useGetReleases = () => { setStargazersCount(cached) return } + // Expired: show the stale count rather than a dash while refreshing. + const stale = readStoredStars() + if (stale?.value) setStargazersCount(stale.value) + fetchStars().then((value) => { if (alive && value) setStargazersCount(value) }) diff --git a/src/pages/ai-lake.tsx b/src/pages/ai-lake.tsx index cbcad1404..d24d4cf97 100644 --- a/src/pages/ai-lake.tsx +++ b/src/pages/ai-lake.tsx @@ -5,15 +5,7 @@ const GlaceLake: React.FC = () => { const history = useHistory() useEffect(() => { - // Redirect to home page with the form anchor - history.replace('/#olake-form-product') - // Scroll to the anchor after a brief delay to ensure page loads - setTimeout(() => { - const element = document.getElementById('olake-form-product') - if (element) { - element.scrollIntoView({ behavior: 'smooth' }) - } - }, 100) + history.replace('/contact') }, [history]) return null diff --git a/src/pages/contact.tsx b/src/pages/contact.tsx index 40e8b0b9a..eee5e9e9d 100644 --- a/src/pages/contact.tsx +++ b/src/pages/contact.tsx @@ -3,7 +3,9 @@ import Layout from '@theme/Layout' import Head from '@docusaurus/Head' import useDocusaurusContext from '@docusaurus/useDocusaurusContext' import { useLocation } from '@docusaurus/router' -import { FaEnvelope, FaMapMarkerAlt, FaSlack, FaLinkedin } from 'react-icons/fa' +import { FaEnvelope, FaPhone, FaMapMarkerAlt, FaSlack, FaLinkedin } from 'react-icons/fa' +import LazyComponent from '@site/src/components/LazyComponent' +import LightModeEnforcer from '@site/src/components/LightModeEnforcer' const stripTrailingSlash = (value?: string) => { if (!value) { @@ -30,40 +32,40 @@ const ContactPage = () => { const organizationSchema = { '@context': 'https://schema.org', '@type': 'Organization', - name: 'OLake', - alternateName: 'Datazip, Inc. (OLake project)', - url: 'https://olake.io/', - logo: 'https://olake.io/img/logo/olake-blue.svg', - sameAs: [ + 'name': 'OLake', + 'alternateName': 'Datazip, Inc. (OLake project)', + 'url': 'https://olake.io/', + 'logo': 'https://olake.io/img/logo/olake-blue.svg', + 'sameAs': [ 'https://github.com/datazip-inc/olake', 'https://x.com/_olake', 'https://www.linkedin.com/company/datazipio/', 'https://www.youtube.com/@olakeio' ], - address: { + 'address': { '@type': 'PostalAddress', - streetAddress: '16192 COASTAL HWY', - addressLocality: 'LEWES', - addressRegion: 'DE', - postalCode: '19958', - addressCountry: 'US' + 'streetAddress': '16192 COASTAL HWY', + 'addressLocality': 'LEWES', + 'addressRegion': 'DE', + 'postalCode': '19958', + 'addressCountry': 'US' } } const websiteSchema = { '@context': 'https://schema.org', '@type': 'WebSite', - url: 'https://olake.io/', - name: 'Fastest Open Source Data Replication Tool', - description: + 'url': 'https://olake.io/', + 'name': 'Fastest Open Source Data Replication Tool', + 'description': 'Fastest open-source tool for replicating Databases to Data Lake in Open Table Formats like Apache Iceberg. Efficient, quick and scalable data ingestion. Supporting Postgres, MongoDB, MySQL, Oracle and Kafka with 5-500x faster than alternatives.', - publisher: { + 'publisher': { '@type': 'Organization', - name: 'OLake' + 'name': 'OLake' }, - potentialAction: { + 'potentialAction': { '@type': 'SearchAction', - target: 'https://olake.io/search?q={search_term_string}', + 'target': 'https://olake.io/search?q={search_term_string}', 'query-input': 'required name=search_term_string' } } @@ -71,42 +73,42 @@ const ContactPage = () => { const contactPageSchema = { '@context': 'https://schema.org', '@type': 'ContactPage', - url: canonicalUrl, - name: 'Contact Us', - description: + 'url': canonicalUrl, + 'name': 'Contact Us', + 'description': 'Get in touch with OLake for product questions, community, or support. Email hello@olake.io. Join our Slack for community discussions.', - isPartOf: { + 'isPartOf': { '@type': 'WebSite', - url: 'https://olake.io/', - name: 'OLake' + 'url': 'https://olake.io/', + 'name': 'OLake' }, - publisher: { + 'publisher': { '@type': 'Organization', - name: 'OLake', - url: 'https://olake.io/', - logo: { + 'name': 'OLake', + 'url': 'https://olake.io/', + 'logo': { '@type': 'ImageObject', - url: 'https://olake.io/img/logo/olake-blue.svg', - width: 32, - height: 32 + 'url': 'https://olake.io/img/logo/olake-blue.svg', + 'width': 32, + 'height': 32 } }, - contactPoint: { + 'contactPoint': { '@type': 'ContactPoint', - contactType: 'customer support', - email: 'hello@olake.io', - availableLanguage: ['English'] + 'contactType': 'customer support', + 'email': 'hello@olake.io', + 'availableLanguage': ['English'] }, - mainEntity: [ + 'mainEntity': [ { '@type': 'ContactPoint', - contactType: 'general inquiries', - email: 'hello@olake.io' + 'contactType': 'general inquiries', + 'email': 'hello@olake.io' }, { '@type': 'WebSite', - name: 'Join Slack', - url: 'https://olake.io/slack/' + 'name': 'Join Slack', + 'url': 'https://olake.io/slack/' } ] } @@ -114,18 +116,18 @@ const ContactPage = () => { const breadcrumbSchema = { '@context': 'https://schema.org', '@type': 'BreadcrumbList', - itemListElement: [ + 'itemListElement': [ { '@type': 'ListItem', - position: 1, - name: 'Home', - item: 'https://olake.io/' + 'position': 1, + 'name': 'Home', + 'item': 'https://olake.io/' }, { '@type': 'ListItem', - position: 2, - name: 'Contact Us', - item: canonicalUrl + 'position': 2, + 'name': 'Contact Us', + 'item': canonicalUrl } ] } @@ -139,9 +141,11 @@ const ContactPage = () => { return ( + @@ -163,40 +167,42 @@ const ContactPage = () => { /> ))} -
-
-

Contact Us

-
- {/* Contact Info Section */} -
+
+ +
+
+
+

Contact Us

+
+
-

Get in Touch

-
-
- - +

Other ways to reach us

+
+ -
- +
+
-

Headquarters

+

Headquarters

Datazip, Inc. 16192 COASTAL HWY LEWES, DE 19958, USA

-

Working Address

+

Working Address

HustleHub H203, 522, 24th Main Rd, Parangi Palaya, Sector 2, HSR Layout, Bengaluru, Karnataka 560102

-
- {/* Team Links Section */} -
-

Connect with Our Team on LinkedIn

-
-
-
-
-
- OLake -
-

- Fastest Data Replication -

- -
- -
-
- By Datazip -
-
- OLake -
-
diff --git a/src/pages/olake-fusion.tsx b/src/pages/olake-fusion.tsx index b254ab45f..338de9f75 100644 --- a/src/pages/olake-fusion.tsx +++ b/src/pages/olake-fusion.tsx @@ -1,7 +1,6 @@ // @ts-nocheck import React from 'react' import Layout from '@theme/Layout' -import { PiLinkedinLogo, PiYoutubeLogo, PiSlackLogo, PiXLogo } from 'react-icons/pi' import LandingSeo from '@site/src/components/landing/seo/LandingSeo' import LightModeEnforcer from '@site/src/components/LightModeEnforcer' import { useFusionLogic } from '@site/src/components/landing/pages/useFusionLogic' @@ -40,7 +39,6 @@ export default function OLakeFusionPage() { title={FUSION_SEO.title} description={FUSION_SEO.description} wrapperClassName='landing-page' - noFooter >
{' '} -
-
-
-
-
- OLake -
-

- Optimized Iceberg Tables -

- -
- -
-
- By Datazip -
-
- OLake -
-
-
diff --git a/src/pages/olake-go.tsx b/src/pages/olake-go.tsx index dac4c337a..66dc2bbd2 100644 --- a/src/pages/olake-go.tsx +++ b/src/pages/olake-go.tsx @@ -1,7 +1,6 @@ // @ts-nocheck import React from 'react' import Layout from '@theme/Layout' -import { PiLinkedinLogo, PiYoutubeLogo, PiSlackLogo, PiXLogo } from 'react-icons/pi' import LandingSeo from '@site/src/components/landing/seo/LandingSeo' import LightModeEnforcer from '@site/src/components/LightModeEnforcer' import { useGoLogic } from '@site/src/components/landing/pages/useGoLogic' @@ -47,7 +46,6 @@ export default function OLakeGoPage() { title={GO_SEO.title} description={GO_SEO.description} wrapperClassName='landing-page' - noFooter > @@ -1977,7 +1975,7 @@ export default function OLakeGoPage() { style={{ display: 'grid', gridTemplateColumns: - 'minmax(0,1.3fr) minmax(0,1fr) minmax(0,1fr) minmax(0,1fr) minmax(0,1fr) minmax(0,1fr)', + 'minmax(0,1.15fr) minmax(0,1.35fr) minmax(0,1fr) minmax(0,1fr) minmax(0,1fr) minmax(0,1fr)', borderTop: '1px solid #EEF0F8' }} > @@ -2300,295 +2298,6 @@ export default function OLakeGoPage() {
-
-
-
-
-
- OLake -
-

- Fastest Data Replication -

- -
- -
-
- By Datazip -
-
- OLake -
-
-
) From 60c9055d3c06d1a0dd8a2c69f055600f53c0af75 Mon Sep 17 00:00:00 2001 From: deepanshupal09-datazip Date: Thu, 13 Aug 2026 18:33:57 +0530 Subject: [PATCH 3/7] fix: resolve comments --- src/components/landing/Navbar/SiteNavbar.css | 5 + src/components/landing/Navbar/SiteNavbar.tsx | 33 +- src/components/landing/Navbar/navData.ts | 4 +- src/components/landing/pages/olake-fusion.css | 2 +- src/components/landing/pages/olake-home.css | 2 +- src/components/landing/pages/useGoLogic.ts | 16 +- src/components/landing/pages/useHomeLogic.ts | 4 +- src/pages/index.tsx | 90 +- src/pages/olake-fusion.tsx | 974 +++++++------- src/pages/olake-go.tsx | 1168 +++++++++-------- src/theme/Footer/index.tsx | 4 +- 11 files changed, 1171 insertions(+), 1131 deletions(-) diff --git a/src/components/landing/Navbar/SiteNavbar.css b/src/components/landing/Navbar/SiteNavbar.css index 6bafd6dcc..43768d379 100644 --- a/src/components/landing/Navbar/SiteNavbar.css +++ b/src/components/landing/Navbar/SiteNavbar.css @@ -194,6 +194,11 @@ body:has(.olakehome-page) .olake-nav { text-decoration: none; } +.olake-nav .olake-nav-stars--icon-only { + border: none; + padding: 0; +} + .olake-nav-stars img { height: 29px; width: 28px; diff --git a/src/components/landing/Navbar/SiteNavbar.tsx b/src/components/landing/Navbar/SiteNavbar.tsx index d567f2270..188b70fdd 100644 --- a/src/components/landing/Navbar/SiteNavbar.tsx +++ b/src/components/landing/Navbar/SiteNavbar.tsx @@ -1,5 +1,6 @@ import React, { useState, type ReactNode } from 'react' import Link from '@docusaurus/Link' +import { useLocation } from '@docusaurus/router' import { cn } from '@site/src/lib/utils' import useGetReleases from '@site/src/hooks/useGetReleases' import { @@ -7,6 +8,7 @@ import { MOBILE_LINKS, PRICING_LINK, GITHUB_REPO_URL, + FUSION_GITHUB_REPO_URL, SLACK_URL, CTA, isFlyout, @@ -39,17 +41,28 @@ const StarMark = () => ( ) -/** Star count. In the bar on desktop; the design moves it into the drawer on mobile. */ -const StarPill = ({ stars }: { stars: string }) => ( +const StarPill = ({ + stars, + repoUrl, + showCount +}: { + stars: string + repoUrl: string + showCount: boolean +}) => ( - {stars} + {showCount && ( + <> + {stars} + + )} ) @@ -198,6 +211,8 @@ export default function SiteNavbar({ trailing, mobileSidebar }: SiteNavbarProps) const { stargazersCount } = useGetReleases() const stars = formatStars(stargazersCount) const [ownOpen, setOwnOpen] = useState(false) + const isFusion = useLocation().pathname.startsWith('/olake-fusion') + const repoUrl = isFusion ? FUSION_GITHUB_REPO_URL : GITHUB_REPO_URL const mobileOpen = mobileSidebar ? mobileSidebar.shown : ownOpen const toggleMobile = mobileSidebar ? mobileSidebar.toggle : () => setOwnOpen((o) => !o) @@ -227,11 +242,11 @@ export default function SiteNavbar({ trailing, mobileSidebar }: SiteNavbarProps)
- + {/* Below the breakpoint the design drops the count and shows the mark alone; the full pill moves into the drawer. */} - +
diff --git a/src/components/landing/Navbar/navData.ts b/src/components/landing/Navbar/navData.ts index 0d7832566..853fa8ebb 100644 --- a/src/components/landing/Navbar/navData.ts +++ b/src/components/landing/Navbar/navData.ts @@ -58,8 +58,7 @@ export const NAV_ENTRIES: NavEntry[] = [ items: [ { label: 'OLake Community', href: '/community' }, { label: 'Top Contributors', href: '/community/contributors' }, - { label: 'Contributor Program', href: '/community/contributor-program' }, - { label: 'GSoC', href: '/community/gsoc' } + { label: 'Contributor Program', href: '/community/contributor-program' } ] }, { @@ -99,5 +98,6 @@ export const MOBILE_LINKS: MobileNavItem[] = [ ] export const GITHUB_REPO_URL = 'https://github.com/datazip-inc/olake' +export const FUSION_GITHUB_REPO_URL = 'https://github.com/datazip-inc/olake-fusion' export const SLACK_URL = '/slack' export const CTA = { label: "Try, it's free!", href: '/docs/getting-started/quickstart/' } diff --git a/src/components/landing/pages/olake-fusion.css b/src/components/landing/pages/olake-fusion.css index 77c620fc5..a206c50b9 100644 --- a/src/components/landing/pages/olake-fusion.css +++ b/src/components/landing/pages/olake-fusion.css @@ -214,7 +214,7 @@ body:has(.olakefusion-page) { font-size: 26px !important; } .olakefusion-page .features-wrap { - padding: 48px 20px 20px !important; + padding: 48px 20px 100px !important; } .olakefusion-page .features-grid { grid-template-columns: 1fr !important; diff --git a/src/components/landing/pages/olake-home.css b/src/components/landing/pages/olake-home.css index ad4ba48ac..094adef81 100644 --- a/src/components/landing/pages/olake-home.css +++ b/src/components/landing/pages/olake-home.css @@ -45,7 +45,7 @@ body:has(.olakehome-page) { transform: translateX(0); } to { - transform: translateX(-50%); + transform: translateX(calc(-100% - 28px)); } } @keyframes glowPulse { diff --git a/src/components/landing/pages/useGoLogic.ts b/src/components/landing/pages/useGoLogic.ts index df3eb06a2..267755eeb 100644 --- a/src/components/landing/pages/useGoLogic.ts +++ b/src/components/landing/pages/useGoLogic.ts @@ -23,26 +23,26 @@ export function useGoLogic(props = {}) { faqs: [ { q: 'How to get started?', - a: 'Check the Quickstart Guide. With a single Docker command you can spin up OLake and access the UI.' + a: 'Check the Quickstart Guide. With a single Docker command you can spin up OLake Go and access the UI.' }, { - q: 'Is OLake really open source?', - a: 'Yes. OLake is fully open source under the Apache 2.0 license. You can explore the GitHub repository (already starred by 1K+ developers) and use it freely without hidden costs.' + q: 'Is OLake Go really open source?', + a: 'Yes. OLake Go is fully open source under the Apache 2.0 license. You can explore the GitHub repository (already starred by 1K+ developers) and use it freely without hidden costs.' }, { q: 'Is there any enterprise plan?', - a: "We're actively working on providing enterprise support, from professional assistance and pilot programs to helping teams scale OLake in production. You can reach out at hello@olake.io to learn more." + a: "We're actively working on providing enterprise support, from professional assistance and pilot programs to helping teams scale OLake Go in production. You can reach out at hello@olake.io to learn more." }, { q: 'How can I contribute?', a: 'Join our Slack community, review the Contribution Guide, and explore "Good First Issues" on GitHub. Contributors can get their pull requests merged and be part of building the fastest open-source Iceberg-native ingestion tool.' }, { - q: 'Why should I use OLake?', - a: 'OLake makes data replication into Apache Iceberg seamless, faster, and cost-efficient. It handles real-time CDC, schema and partition evolution, full and incremental syncs, and compaction, all without vendor lock-in, so your Iceberg tables stay open, scalable, and ready for analytics.' + q: 'Why should I use OLake Go?', + a: 'OLake Go makes data replication into Apache Iceberg seamless, faster, and cost-efficient. It handles real-time CDC, schema and partition evolution, full and incremental syncs, and compaction, all without vendor lock-in, so your Iceberg tables stay open, scalable, and ready for analytics.' }, { - q: 'What data platforms and tools does OLake integrate with?', + q: 'What data platforms and tools does OLake Go integrate with?', a: 'As of now, we integrate with Apache Iceberg and S3 as destinations. You can query it using popular query engines like Spark, AWS Athena, Snowflake, Databricks, and BigQuery.' } ], @@ -281,7 +281,7 @@ export function useGoLogic(props = {}) { }, { title: 'STATEFUL, RESUMABLE SYNCS', - body: 'Syncs checkpoint their progress and resume automatically after crashes, network failures, or pauses, never from scratch.', + body: 'Syncs checkpoint their progress and resume automatically after crashes or network failures; never from scratch.', tag: 'resume', stats: ['Checkpointed', 'Auto-resume', 'Fault-tolerant'] } diff --git a/src/components/landing/pages/useHomeLogic.ts b/src/components/landing/pages/useHomeLogic.ts index d97761336..18a9fe415 100644 --- a/src/components/landing/pages/useHomeLogic.ts +++ b/src/components/landing/pages/useHomeLogic.ts @@ -287,7 +287,7 @@ export function useHomeLogic(props = {}) { } ], - logosLoop: [...logos, ...logos], + logos, selectGo: () => setState({ advantage: 'go' }), selectFusion: () => setState({ advantage: 'fusion' }), @@ -307,7 +307,7 @@ export function useHomeLogic(props = {}) { num: '01', kicker: 'FAST', title: 'Replicate databases at scale', - body: 'Sync MySQL, Postgres, MongoDB, Kafka, and more to Apache Iceberg with parallelised chunking, incremental sync, and CDC.' + body: 'Sync MySQL, Postgres, MongoDB, Kafka, and more to Apache Iceberg and Parquet with parallelised chunking, incremental sync, and CDC.' }, { stickyTop: 138, diff --git a/src/pages/index.tsx b/src/pages/index.tsx index c4026de65..e92173b34 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -46,7 +46,7 @@ export default function HomePage() { terminalLines, tickerLoop, engines, - logosLoop, + logos, archSources, archGoChips, archFusionChips, @@ -767,53 +767,61 @@ export default function HomePage() { style={{ overflow: 'hidden', width: '100%', + display: 'flex', + gap: '28px', WebkitMaskImage: 'linear-gradient(90deg,transparent,#ffffff 12%,#ffffff 88%,transparent)', maskImage: 'linear-gradient(90deg,transparent,#ffffff 12%,#ffffff 88%,transparent)' }} > -
- {/* One copy per pass: the second is a duplicate that makes the scroll seamless. */} - {(logosLoop || []).map((logo, logoIdx) => ( -
= (logosLoop || []).length / 2 || undefined} - style={{ - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - height: '54px', - padding: '0 26px', - background: '#ffffff', - borderRadius: '14px', - flexShrink: '0' - }} - > - {logo.name} ( +
+ {/* 3x: group must outwidth any screen or the loop gap shows. */} + {[...(logos || []), ...(logos || []), ...(logos || [])].map((logo, logoIdx) => ( +
-
- ))} -
+ > + {logo.name} +
+ ))} +
+ ))}
-
+
@@ -790,102 +790,167 @@ export default function OLakeFusionPage() { ))}
{' '} -
+
{(features || []).map((feat, featIdx) => ( - {feat.active ? ( - <> +
+
-
- {feat.isTiered ? ( - <> + {feat.isTiered ? ( + <> +
-
{' '} -
{' '} -
-
- - ) : null}{' '} - {feat.isDecay ? ( - <> + />{' '}
{' '} +
+
+ + ) : null}{' '} + {feat.isDecay ? ( + <> +
+
+
+ + ) : null}{' '} + {feat.isConfig ? ( + <> +
+
+
+ + ) : null}{' '} + {feat.isHosted ? ( + <> +
+
-
- - ) : null}{' '} - {feat.isConfig ? ( - <> +
{' '}
- - ) : null}{' '} - {feat.isHosted ? ( - <> +
+ + ) : null} +
{' '} +

+ {feat.title} +

{' '} + {feat.isTiered ? ( + <> +
+
+ LITE +
{' '} +
-
-
{' '} + /> +
{' '} +
+ every 20 min +
+
{' '} +
+
+ MEDIUM +
{' '} +
-
-
+ /> +
{' '} +
+ every 40 min
- - ) : null} -
{' '} -

- {feat.title} -

{' '} - {feat.isTiered ? ( - <> +
{' '}
+ FULL +
{' '} +
- LITE -
{' '} + /> +
{' '} +
+ deep-clean +
+
+
+ + ) : null}{' '} + {feat.isDecay ? ( + <> +
+
+
-
-
{' '} + />
- every 20 min -
-
{' '} -
+ />
- MEDIUM -
{' '} + />{' '}
-
-
{' '} + />
- every 40 min -
-
{' '} -
+ />
- FULL -
{' '} + />{' '}
-
-
{' '} + />
- deep-clean -
+ /> +
{' '} +
+ fragmented files
-
- - ) : null}{' '} - {feat.isDecay ? ( - <> -
-
+
{' '} +
{' '} +
+
-
-
-
{' '} -
-
-
{' '} -
-
-
{' '} -
- fragmented files -
-
{' '} -
{' '} -
+ />
-
-
-
{' '} -
- compacted -
+ /> +
{' '} +
+ compacted
- - ) : null}{' '} - {feat.isConfig ? ( - <> +
+ + ) : null}{' '} + {feat.isConfig ? ( + <> +
-
- 1 -
{' '} -
- Fusion parameter -
+ 1
{' '}
-
- 10+ -
{' '} -
- Spark parameters -
+ Fusion parameter
-
- - ) : null}{' '} - {feat.isHosted ? ( - <> +
{' '}
- {' '} - - Docker - + 10+
{' '}
- {' '} - - Kubernetes - + Spark parameters
- - ) : null}{' '} -
- {feat.body} -
+
+ + ) : null}{' '} + {feat.isHosted ? ( + <> +
+
+ {' '} + + Docker + +
{' '} +
+ {' '} + + Kubernetes + +
+
+ + ) : null}{' '} +
+ {feat.body}
- - ) : null} +
+
))}
diff --git a/src/pages/olake-go.tsx b/src/pages/olake-go.tsx index 66dc2bbd2..6f1ce5af1 100644 --- a/src/pages/olake-go.tsx +++ b/src/pages/olake-go.tsx @@ -42,11 +42,7 @@ export default function OLakeGoPage() { } = useGoLogic({ icebergPosX: 54, icebergPosY: 53, icebergZoom: 100, icebergOpacity: 65 }) return ( - +
@@ -967,720 +963,728 @@ export default function OLakeGoPage() { ))}
{' '} -
+
{(features || []).map((feat, featIdx) => ( - {feat.active ? ( - <> +
+
-
- {feat.isTiered ? ( - <> + {feat.isTiered ? ( + <> +
+
{' '} +
{' '}
+
+ + ) : null}{' '} + {feat.isDecay ? ( + <> +
+
{' '} +
{' '} -
{' '} + />
- - ) : null}{' '} - {feat.isDecay ? ( - <> +
+ + ) : null}{' '} + {feat.isChunk ? ( + <> +
+
{' '} +
{' '} +
{' '}
+
+ + ) : null}{' '} + {feat.isResume ? ( + <> +
+
+
+ + ) : null} +
{' '} +

+ {feat.title} +

{' '} + {feat.isTiered ? ( + <> +
+
+
-
{' '} -
-
-
-
-
- - ) : null}{' '} - {feat.isChunk ? ( - <> + FULL +
{' '}
{' '} -
{' '} + />
{' '} + />
-
- - ) : null}{' '} - {feat.isResume ? ( - <> +
{' '}
-
+ one-time load
- - ) : null} -
{' '} -

- {feat.title} -

{' '} - {feat.isTiered ? ( - <> -
+
{' '} +
-
- FULL -
{' '} -
-
-
-
-
{' '} -
- one-time load -
+ INCREMENTAL
{' '}
- INCREMENTAL -
{' '} + />
-
-
-
-
{' '} + />
- on schedule -
+ />
{' '}
+ on schedule +
+
{' '} +
+
+ CDC +
{' '} +
- CDC -
{' '} -
-
-
-
{' '} + />
- real-time -
+ /> +
{' '} +
+ real-time
- - ) : null}{' '} - {feat.isDecay ? ( - <> +
+ + ) : null}{' '} + {feat.isDecay ? ( + <> +
+ SOURCE TABLE +
{' '} +
- SOURCE TABLE -
{' '} + />{' '}
-
{' '} -
{' '} -
-
-
{' '} + />{' '} +
+
+
{' '} +
+ → +
{' '} +
- → + ICEBERG TABLE
{' '}
- ICEBERG TABLE -
{' '} + />{' '} +
{' '}
{' '} -
{' '} -
+ -
- - + NEW - -
+ + NEW +
- - ) : null}{' '} - {feat.isChunk ? ( - <> -
+
+ + ) : null}{' '} + {feat.isChunk ? ( + <> +
+
{' '} +
{' '} + /> +
{' '} +
-
+ chunk 1
{' '} -
-
- chunk 1 -
{' '} -
- chunk 2 -
{' '} -
- chunk 3 -
{' '} -
- chunk 4 -
+
+ chunk 2
{' '}
+ chunk 3 +
{' '} +
- read in parallel + chunk 4
+
{' '} +
+ read in parallel
- - ) : null}{' '} - {feat.isResume ? ( - <> -
+
+ + ) : null}{' '} + {feat.isResume ? ( + <> +
+
-
{' '} -
{' '} -
- ✓ checkpoint -
-
{' '} + />{' '}
{' '} +
- interrupted - - resumes here → - + ✓ checkpoint
+
{' '} +
+ interrupted + + resumes here → +
- - ) : null}{' '} -
- {feat.body} -
+
+ + ) : null}{' '} +
+ {feat.body}
- - ) : null} +
+
))}
diff --git a/src/theme/Footer/index.tsx b/src/theme/Footer/index.tsx index 8e5c52b05..b03b27055 100644 --- a/src/theme/Footer/index.tsx +++ b/src/theme/Footer/index.tsx @@ -73,7 +73,7 @@ const SOCIALS = [ ] const Footer: React.FC = () => ( -
( > OLake
-
+ ) export default Footer From cd837d8fdbf3cb71a85cc7b4cfdc83b7e66f3bee Mon Sep 17 00:00:00 2001 From: deepanshupal09-datazip Date: Fri, 14 Aug 2026 10:46:59 +0530 Subject: [PATCH 4/7] fix: resolve comments --- src/components/landing/Navbar/navData.ts | 15 ++++++++++----- src/pages/olake-fusion.tsx | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/components/landing/Navbar/navData.ts b/src/components/landing/Navbar/navData.ts index 853fa8ebb..9b72bc697 100644 --- a/src/components/landing/Navbar/navData.ts +++ b/src/components/landing/Navbar/navData.ts @@ -89,11 +89,16 @@ export const MOBILE_LINKS: MobileNavItem[] = [ { label: 'OLake Fusion', href: '/docs/fusion/getting-started/overview' } ] }, - { label: 'Blog', href: '/blog' }, - { label: 'Customer Stories', href: '/customer-stories' }, - { label: 'Webinars & Events', href: '/webinar' }, - { label: 'Community', href: '/community' }, - { label: 'Iceberg', href: '/iceberg' }, + { + label: 'Resources', + items: [ + { label: 'Blog', href: '/blog' }, + { label: 'Customer Stories', href: '/customer-stories' }, + { label: 'Webinars & Events', href: '/webinar' }, + { label: 'Community', href: '/community' }, + { label: 'Iceberg', href: '/iceberg' } + ] + }, PRICING_LINK ] diff --git a/src/pages/olake-fusion.tsx b/src/pages/olake-fusion.tsx index 5bfa34d81..ba30a32d1 100644 --- a/src/pages/olake-fusion.tsx +++ b/src/pages/olake-fusion.tsx @@ -269,7 +269,7 @@ export default function OLakeFusionPage() { color: '#0D1230' }} > - Simplify your Iceberg table maintenance + Keep your Iceberg tables fast with less compute {' '}
Date: Fri, 14 Aug 2026 11:12:16 +0530 Subject: [PATCH 5/7] fix: mobile navbar --- src/components/landing/Navbar/SiteNavbar.css | 11 +++++ src/components/landing/Navbar/SiteNavbar.tsx | 42 +++++++++++++------ src/components/landing/Navbar/navData.ts | 17 +++++++- .../MobileSidebar/PrimaryMenu/index.tsx | 38 +++++++++++------ 4 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/components/landing/Navbar/SiteNavbar.css b/src/components/landing/Navbar/SiteNavbar.css index 43768d379..abfbe42ca 100644 --- a/src/components/landing/Navbar/SiteNavbar.css +++ b/src/components/landing/Navbar/SiteNavbar.css @@ -358,6 +358,17 @@ body:has(.landing-page) .olake-nav [class*='navbarSearchContainer'], text-decoration: none; } +.olake-nav .olake-nav-mobile-accordion-trigger--nested { + padding-left: 20px; + font-size: 15px; + font-weight: 600; + color: #5b6070; +} + +.olake-nav .olake-nav-mobile-sublink--nested { + padding-left: 34px; +} + /* The design collapses at 860px; we do it at 1279px to match the `navbar-breakpoint` plugin, below which Docusaurus renders the mobile sidebar that /docs relies on. */ diff --git a/src/components/landing/Navbar/SiteNavbar.tsx b/src/components/landing/Navbar/SiteNavbar.tsx index 188b70fdd..a8a10cffe 100644 --- a/src/components/landing/Navbar/SiteNavbar.tsx +++ b/src/components/landing/Navbar/SiteNavbar.tsx @@ -159,14 +159,26 @@ function Dropdown({ entry }: { entry: NavEntry }) { ) } -/** A drawer row that expands in place instead of navigating — the drawer's Docs entry. */ -function MobileAccordion({ entry, onNavigate }: { entry: NavEntry; onNavigate: () => void }) { +/** A drawer row that expands in place instead of navigating — the drawer's + * Docs entry, and any nested group inside it (e.g. Resources > Community). */ +function MobileAccordion({ + entry, + onNavigate, + nested +}: { + entry: NavEntry | NavFlyout + onNavigate: () => void + nested?: boolean +}) { const [open, setOpen] = useState(false) return (
{open && (
- {entry.items!.map((item) => ( - - {item.label} - - ))} + {entry.items!.map((item) => + isFlyout(item) ? ( + + ) : ( + + {item.label} + + ) + )}
)}
diff --git a/src/components/landing/Navbar/navData.ts b/src/components/landing/Navbar/navData.ts index 9b72bc697..ca7436d46 100644 --- a/src/components/landing/Navbar/navData.ts +++ b/src/components/landing/Navbar/navData.ts @@ -95,8 +95,21 @@ export const MOBILE_LINKS: MobileNavItem[] = [ { label: 'Blog', href: '/blog' }, { label: 'Customer Stories', href: '/customer-stories' }, { label: 'Webinars & Events', href: '/webinar' }, - { label: 'Community', href: '/community' }, - { label: 'Iceberg', href: '/iceberg' } + { + label: 'Community', + items: [ + { label: 'OLake Community', href: '/community' }, + { label: 'Top Contributors', href: '/community/contributors' }, + { label: 'Contributor Program', href: '/community/contributor-program' } + ] + }, + { + label: 'Iceberg', + items: [ + { label: 'Iceberg Blogs', href: '/iceberg' }, + { label: 'Query Engine', href: '/iceberg/query-engine' } + ] + } ] }, PRICING_LINK diff --git a/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx b/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx index 7f3bec9f4..f3a6a56df 100644 --- a/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx +++ b/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx @@ -5,13 +5,21 @@ import { cn } from '@site/src/lib/utils' import { MOBILE_LINKS, isMobileGroup, + isFlyout, type NavEntry, - type NavLink as NavLinkType + type NavFlyout } from '@site/src/components/landing/Navbar/navData' // A row that expands in place, mirroring the desktop Docs dropdown. Uses // Infima's own collapsible classes, so it picks up dark mode for free. -function MenuGroupItem({ entry, onNavigate }: { entry: NavEntry; onNavigate: () => void }) { +// Recurses for nested groups (e.g. Resources > Community). +function MenuGroupItem({ + entry, + onNavigate +}: { + entry: NavEntry | NavFlyout + onNavigate: () => void +}) { const [collapsed, setCollapsed] = useState(true) return (
  • @@ -30,17 +38,21 @@ function MenuGroupItem({ entry, onNavigate }: { entry: NavEntry; onNavigate: ()
    • - {entry.items!.map((item) => ( -
    • - - {item.label} - -
    • - ))} + {entry.items!.map((item) => + isFlyout(item) ? ( + + ) : ( +
    • + + {item.label} + +
    • + ) + )}
    ) From a465766fee0368e3ec38d166ff8130c6fc7c5fb2 Mon Sep 17 00:00:00 2001 From: deepanshupal09-datazip Date: Fri, 14 Aug 2026 14:33:46 +0530 Subject: [PATCH 6/7] fix: navbar and add posthog experiment --- package-lock.json | 102 +++++++++++++++++++++-- package.json | 1 + src/components/landing/Navbar/navData.ts | 9 +- src/lib/posthog/client.ts | 13 +++ src/lib/posthog/useFeatureFlagVariant.ts | 22 +++++ src/pages/olake-fusion.tsx | 10 ++- src/theme/Root/index.tsx | 6 ++ 7 files changed, 154 insertions(+), 9 deletions(-) create mode 100644 src/lib/posthog/client.ts create mode 100644 src/lib/posthog/useFeatureFlagVariant.ts create mode 100644 src/theme/Root/index.tsx diff --git a/package-lock.json b/package-lock.json index 70a412919..a92211bbf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "clsx": "^2.1.1", "lucide-react": "^0.475.0", "plugin-image-zoom": "^1.2.0", + "posthog-js": "^1.417.0", "prism-react-renderer": "^2.4.1", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -5213,6 +5214,31 @@ "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", "license": "MIT" }, + "node_modules/@posthog/browser-common": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@posthog/browser-common/-/browser-common-0.5.0.tgz", + "integrity": "sha512-8DaxVZS1bQPbA514RePurLNbYjei3P4jhnC206DwVv5XThmZM3QdlsXenI2ujE3pLbgQ79hYn9o1Kda8I3WK/Q==", + "license": "MIT", + "dependencies": { + "@posthog/core": "^1.47.0", + "@posthog/types": "^1.402.2" + } + }, + "node_modules/@posthog/core": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.48.0.tgz", + "integrity": "sha512-ezKjVLw9y3Q235PUY+2hRr5DN9t6j2jF1mFAvnvhCCu/Ha6/qBv3zmVJBaHu9PnqqSNtx2St3ggN8Z3TTu/12A==", + "license": "MIT", + "dependencies": { + "@posthog/types": "^1.403.1" + } + }, + "node_modules/@posthog/types": { + "version": "1.404.0", + "resolved": "https://registry.npmjs.org/@posthog/types/-/types-1.404.0.tgz", + "integrity": "sha512-/Y1zKv8SdwkK725SkmgT5QVYnXE7Fi23SPDCZ5Ybu27gTQub4yMTKWuUQekW+gkSKBZ0LyYCQK52mhyMMigMBw==", + "license": "MIT" + }, "node_modules/@radix-ui/react-avatar": { "version": "1.1.10", "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz", @@ -8926,11 +8952,14 @@ } }, "node_modules/core-js": { - "version": "3.45.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.45.1.tgz", - "integrity": "sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==", + "version": "3.50.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.50.0.tgz", + "integrity": "sha512-BRWgOLKkFeCgRudR6zrs8p9XJZcE14grzKMMssoYrk6krtuEZ7MTKPIY5RzOnqsEKIR9kst7wNzphttraT+Yqw==", "hasInstallScript": true, "license": "MIT", + "engines": { + "node": "*" + }, "funding": { "type": "opencollective", "url": "https://opencollective.com/core-js" @@ -10304,9 +10333,9 @@ } }, "node_modules/dompurify": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", - "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.13.tgz", + "integrity": "sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -11062,6 +11091,12 @@ "node": ">=0.4.0" } }, + "node_modules/fflate": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.9.tgz", + "integrity": "sha512-zdxgIEddhfsyCaWpJ2SdXEP8ZMrKJ6+5jl4OupODcywU0IhRk6gdXuVGcPICyfx2H97hVK7xmJtRLPjkxAX8Vw==", + "license": "MIT" + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -18618,6 +18653,42 @@ "postcss": "^8.4.31" } }, + "node_modules/posthog-js": { + "version": "1.417.0", + "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.417.0.tgz", + "integrity": "sha512-jokL2hiuBYO0+bSJ1l/ZLxFIc4+xwe5P8srIbivSU3MVSWsE4AP2U6IaVW8hQLdcz4k8ZWEa2jDPn9sTUcQ5yw==", + "license": "(Apache-2.0 AND MIT)", + "dependencies": { + "@posthog/browser-common": "^0.5.0", + "@posthog/core": "^1.48.0", + "@posthog/types": "^1.404.0", + "core-js": "^3.49.0", + "dompurify": "^3.4.13", + "fflate": "^0.4.8", + "preact": "^10.29.3", + "query-selector-shadow-dom": "^1.0.1", + "web-vitals": "^5.3.0", + "web-vitals-soft-navs": "npm:web-vitals@6.0.0" + } + }, + "node_modules/preact": { + "version": "10.29.8", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.8.tgz", + "integrity": "sha512-ej2aVZ+vZ8WO7tvlQWRM9N63A0KzF9q4mWJfDUHgYaIofWY9hu74QdnQrjoPMmZi2/nZ5gN0bJCQF49xQqx09Q==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "preact-render-to-string": ">=5" + }, + "peerDependenciesMeta": { + "preact-render-to-string": { + "optional": true + } + } + }, "node_modules/prebuild-install": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", @@ -18956,6 +19027,12 @@ ], "license": "MIT" }, + "node_modules/query-selector-shadow-dom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.1.tgz", + "integrity": "sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==", + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -22306,6 +22383,19 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/web-vitals": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-5.3.0.tgz", + "integrity": "sha512-q6LWsLatGYZp5VGBIOvbTj6JBV2nOmC8KvWztXBmwJcfFAzhwKwbOxhUH306XY3CcaZDUlSmSuNPBsCn0bFu+g==", + "license": "Apache-2.0" + }, + "node_modules/web-vitals-soft-navs": { + "name": "web-vitals", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-6.0.0.tgz", + "integrity": "sha512-Guaibvy/+uNtL6Bsu4jmMJGzuSl91oeRH5iO9pPRbYftnFUr3yqT1TUNX/OE4o9HexuEMU3Kb/Wg7iKhlffZUA==", + "license": "Apache-2.0" + }, "node_modules/webpack": { "version": "5.101.3", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.3.tgz", diff --git a/package.json b/package.json index e720759f9..ab9edda32 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "clsx": "^2.1.1", "lucide-react": "^0.475.0", "plugin-image-zoom": "^1.2.0", + "posthog-js": "^1.417.0", "prism-react-renderer": "^2.4.1", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/src/components/landing/Navbar/navData.ts b/src/components/landing/Navbar/navData.ts index ca7436d46..c918ea2c6 100644 --- a/src/components/landing/Navbar/navData.ts +++ b/src/components/landing/Navbar/navData.ts @@ -80,8 +80,13 @@ export const PRICING_LINK: NavLink = { label: 'Pricing', href: '/contact' } * expanding in place to mirror the desktop dropdown. */ export const MOBILE_LINKS: MobileNavItem[] = [ - { label: 'OLake Go', href: '/olake-go' }, - { label: 'OLake Fusion', href: '/olake-fusion' }, + { + label: 'Product', + items: [ + { label: 'OLake Go', href: '/olake-go' }, + { label: 'OLake Fusion', href: '/olake-fusion' } + ] + }, { label: 'Docs', items: [ diff --git a/src/lib/posthog/client.ts b/src/lib/posthog/client.ts new file mode 100644 index 000000000..ad5310dc9 --- /dev/null +++ b/src/lib/posthog/client.ts @@ -0,0 +1,13 @@ +import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment' +import posthog from 'posthog-js' + +// Side-effect import: initializes on load, client-side only. Root/index.tsx +// imports this so init runs before any page mounts. +if (ExecutionEnvironment.canUseDOM) { + posthog.init('phc_nT2syEvyPUz7FYFgbpadiAFyd7NHBu7W9ewdQ4ciVfac', { + api_host: 'https://us.i.posthog.com', + defaults: '2026-05-30' + }) +} + +export default posthog diff --git a/src/lib/posthog/useFeatureFlagVariant.ts b/src/lib/posthog/useFeatureFlagVariant.ts new file mode 100644 index 000000000..ef2791d68 --- /dev/null +++ b/src/lib/posthog/useFeatureFlagVariant.ts @@ -0,0 +1,22 @@ +import { useEffect, useState } from 'react' +import posthog from './client' + +/** Picks a variant from a PostHog multivariate flag. `variants` keys must + * match the flag's variant keys in the PostHog UI; unmatched/loading state + * falls back to `defaultVariant`. */ +export function useFeatureFlagVariant>( + flagKey: string, + variants: T, + defaultVariant: keyof T +): string { + const [variantKey, setVariantKey] = useState(defaultVariant) + useEffect( + () => + posthog.onFeatureFlags(() => { + const flag = posthog.getFeatureFlag(flagKey) + setVariantKey(typeof flag === 'string' && flag in variants ? flag : defaultVariant) + }), + [flagKey] + ) + return variants[variantKey] +} diff --git a/src/pages/olake-fusion.tsx b/src/pages/olake-fusion.tsx index ba30a32d1..2f1a7f8ef 100644 --- a/src/pages/olake-fusion.tsx +++ b/src/pages/olake-fusion.tsx @@ -6,10 +6,18 @@ import LightModeEnforcer from '@site/src/components/LightModeEnforcer' import { useFusionLogic } from '@site/src/components/landing/pages/useFusionLogic' import { cssToObj as __css } from '@site/src/components/landing/pages/cssToObj' import { FUSION_SEO } from '@site/src/data/landing/seo' +import { useFeatureFlagVariant } from '@site/src/lib/posthog/useFeatureFlagVariant' import '@site/src/components/landing/pages/olake-fusion.css' import '@site/src/components/landing/pages/overrides.css' +const HERO_HEADLINE_FLAG = 'fusion-hero-headline' +const HERO_HEADLINES = { + performance: 'Keep your Iceberg tables fast with less compute', + simplicity: 'Simplify your Iceberg table maintenance' +} + export default function OLakeFusionPage() { + const heroHeadline = useFeatureFlagVariant(HERO_HEADLINE_FLAG, HERO_HEADLINES, 'performance') const { icebergStyle, problemCards, @@ -269,7 +277,7 @@ export default function OLakeFusionPage() { color: '#0D1230' }} > - Keep your Iceberg tables fast with less compute + {heroHeadline} {' '}
    {children} +} From c70a983b15bca4355c02b58b072edbc74a932606 Mon Sep 17 00:00:00 2001 From: deepanshupal09-datazip Date: Fri, 14 Aug 2026 15:19:35 +0530 Subject: [PATCH 7/7] fix: fusion diagram --- src/components/landing/pages/olake-fusion.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/landing/pages/olake-fusion.css b/src/components/landing/pages/olake-fusion.css index a206c50b9..197f4cdf7 100644 --- a/src/components/landing/pages/olake-fusion.css +++ b/src/components/landing/pages/olake-fusion.css @@ -189,7 +189,7 @@ body:has(.olakefusion-page) { padding: 14px 20px !important; } .olakefusion-page .hero-wrap { - padding: 24px 20px 8px !important; + padding: 48px 20px 8px !important; } .olakefusion-page .hero-title { font-size: 32px !important; @@ -265,14 +265,14 @@ body:has(.olakefusion-page) { grid-template-columns: 1fr !important; } .olakefusion-page .arch-inner { - transform: scale(0.46); + transform: scale(0.78); transform-origin: top center; } .olakefusion-page .arch-wrap { - height: 118px !important; + height: 168px !important; overflow: hidden; padding: 6px 12px !important; - margin: 8px auto 8px !important; + margin: 84px auto 8px !important; } .olakefusion-page .bench-row { padding-left: 16px !important;