This is an automated email from the ASF dual-hosted git repository. Xuanwo pushed a commit to branch xuanwo/website-redesign in repository https://gitbox.apache.org/repos/asf/opendal.git
commit 0a9058bee3266d20883927a51e05cad7e398de77 Author: Xuanwo <[email protected]> AuthorDate: Sat May 30 00:26:30 2026 +0800 feat(website): add interactive capabilities explorer and used-by wall --- website/src/components/landing/data.js | 130 ++++++++++--- website/src/components/landing/sections.jsx | 125 ++++++++---- website/src/components/landing/styles.module.css | 238 +++++++++++++---------- website/static/img/users/cratedb.png | Bin 0 -> 711 bytes website/static/img/users/daft.png | Bin 0 -> 6745 bytes website/static/img/users/databend.png | Bin 13146 -> 3579 bytes website/static/img/users/datafusion-comet.png | Bin 0 -> 7018 bytes website/static/img/users/dify.png | Bin 7467 -> 2218 bytes website/static/img/users/filecodebox.png | Bin 53339 -> 0 bytes website/static/img/users/gravitino.png | Bin 0 -> 7018 bytes website/static/img/users/greptimedb.png | Bin 0 -> 6539 bytes website/static/img/users/hasura.png | Bin 0 -> 5428 bytes website/static/img/users/iceberg-rust.png | Bin 0 -> 7018 bytes website/static/img/users/kubeflow-trainer.png | Bin 0 -> 9460 bytes website/static/img/users/lance.png | Bin 0 -> 3328 bytes website/static/img/users/llamaindex.png | Bin 0 -> 6890 bytes website/static/img/users/lnx.png | Bin 0 -> 1895 bytes website/static/img/users/loco.png | Bin 0 -> 5092 bytes website/static/img/users/milvus.png | Bin 15620 -> 0 bytes website/static/img/users/octobase.png | Bin 0 -> 11292 bytes website/static/img/users/openraft.png | Bin 0 -> 3579 bytes website/static/img/users/pants.png | Bin 0 -> 2676 bytes website/static/img/users/pathway.png | Bin 0 -> 20187 bytes website/static/img/users/questdb.png | Bin 26479 -> 3767 bytes website/static/img/users/quickwit.png | Bin 0 -> 3667 bytes website/static/img/users/ragflow.png | Bin 0 -> 9257 bytes website/static/img/users/risingwave.png | Bin 6252 -> 5562 bytes website/static/img/users/robustmq.png | Bin 0 -> 1540 bytes website/static/img/users/rustic.png | Bin 0 -> 12204 bytes website/static/img/users/sccache.png | Bin 4701 -> 1356 bytes website/static/img/users/seatunnel.png | Bin 0 -> 7018 bytes website/static/img/users/slatedb.png | Bin 0 -> 4332 bytes website/static/img/users/spiceai.png | Bin 0 -> 4518 bytes website/static/img/users/vaultwarden.png | Bin 0 -> 18431 bytes website/static/img/users/vector.png | Bin 48196 -> 8211 bytes website/static/img/users/walrus.png | Bin 0 -> 7880 bytes website/static/img/users/wrenai.png | Bin 0 -> 2330 bytes website/static/img/users/zino.png | Bin 0 -> 4517 bytes 38 files changed, 320 insertions(+), 173 deletions(-) diff --git a/website/src/components/landing/data.js b/website/src/components/landing/data.js index ac5fa6418..83935b611 100644 --- a/website/src/components/landing/data.js +++ b/website/src/components/landing/data.js @@ -142,38 +142,80 @@ export const valueProps = [ }, ]; -// What OpenDAL can do, grouped for the capabilities section. Grounded in the -// core read/write/manage features (ranges, concurrency, multipart, listing …). -export const capabilityGroups = [ - { - title: "Read", - items: [ - "Whole-object or byte-range reads", - "Concurrent, chunked fetching", - "Auto-merge nearby ranges", - "Resume interrupted reads", - "Conditional & versioned reads", - ], +// What OpenDAL can do — grouped for the capabilities explorer. Each item pairs +// a minimal, real snippet with its docs.rs reference. Grounded in the core +// read / write / manage APIs (verified against types/operator + types/options). +const RS = "https://docs.rs/opendal/latest/opendal"; +const opDoc = (method) => `${RS}/struct.Operator.html#method.${method}`; + +export const capabilityThemes = [ + { + title: "Read in parallel", + blurb: "Fetch a byte range, or a whole object in concurrent chunks.", + doc: opDoc("read_with"), + code: `let op = Operator::new(S3::default().bucket("data"))?.finish(); + +// Read just the bytes you need. +let head = op.read_with("logs/today").range(0..64 * 1024).await?; + +// Or pull a large object in parallel chunks. +let full = op + .read_with("big.parquet") + .concurrent(8) + .chunk(8 * 1024 * 1024) + .await?;`, }, { - title: "Write", - items: [ - "Streaming writes of any size", - "Multipart upload", - "Concurrent part uploads", - "Append to existing objects", - "Atomic create & overwrite guards", - ], + title: "Upload in parts", + blurb: "Stream writes of any size as concurrent, multipart uploads.", + doc: opDoc("writer_with"), + code: `let op = Operator::new(S3::default().bucket("data"))?.finish(); + +// Open a multipart writer with 8 concurrent parts. +let mut w = op + .writer_with("big.bin") + .concurrent(8) + .chunk(8 * 1024 * 1024) + .await?; + +// Stream any number of buffers; close flushes the rest. +w.write(part_one).await?; +w.write(part_two).await?; +w.close().await?;`, }, { - title: "Manage", - items: [ - "Stat metadata without the body", - "Lazy, recursive, paginated listing", - "Batch & recursive delete", - "Server-side copy & rename", - "Presigned URLs for direct access", - ], + title: "Recover from failure", + blurb: "Resume on retry, write atomically, and pin a version.", + doc: `${RS}/layers/struct.RetryLayer.html`, + code: `// Retries automatically resume interrupted transfers. +let op = Operator::new(S3::default().bucket("data"))? + .layer(RetryLayer::new()) + .finish(); + +// Create only if absent. +op.write_with("once.json", data).if_not_exists(true).await?; +// Read only if unchanged. +let doc = op.read_with("doc").if_match(etag).await?; +// Pin an exact version. +let pinned = op.read_with("doc").version(version_id).await?;`, + }, + { + title: "Work with files", + blurb: "Inspect, list, move, and share — without moving bytes.", + doc: opDoc("list_with"), + code: `// Inspect a file without downloading it. +let meta = op.stat("report.csv").await?; +// List a prefix, recursing lazily through the tree. +let mut entries = op.lister_with("logs/").recursive(true).await?; +while let Some(entry) = entries.try_next().await? { + println!("{}", entry.path()); +} +// Copy on the server — no download. +op.copy("draft.md", "final.md").await?; +// Recursively delete a subtree. +op.delete_with("tmp/").recursive(true).await?; +// Presign a temporary, shareable URL. +let url = op.presign_read("report.csv", Duration::from_secs(3600)).await?;`, }, ]; @@ -181,15 +223,43 @@ export const capabilityGroups = [ // GitHub star count (highest first). Logos are the projects' GitHub org // avatars, self-hosted under static/img/users/. Refresh with scripts as the // ecosystem grows. The logo wall shows a responsive subset by viewport width. +// Public projects with 1,000+ GitHub stars that depend on OpenDAL, sorted by +// stars. Sourced via crates.io reverse deps + GitHub code search; logos are the +// owner avatars, mirrored locally under static/img/users to avoid runtime calls. export const usedBy = [ { name: "Dify", icon: "/img/users/dify.png", href: "https://github.com/langgenius/dify" }, - { name: "Milvus", icon: "/img/users/milvus.png", href: "https://github.com/milvus-io/milvus" }, + { name: "RAGFlow", icon: "/img/users/ragflow.png", href: "https://github.com/infiniflow/ragflow" }, + { name: "Pathway", icon: "/img/users/pathway.png", href: "https://github.com/pathwaycom/pathway" }, + { name: "Vaultwarden", icon: "/img/users/vaultwarden.png", href: "https://github.com/dani-garcia/vaultwarden" }, + { name: "LlamaIndex", icon: "/img/users/llamaindex.png", href: "https://github.com/run-llama/llama_index" }, + { name: "Hasura", icon: "/img/users/hasura.png", href: "https://github.com/hasura/graphql-engine" }, { name: "Vector", icon: "/img/users/vector.png", href: "https://github.com/vectordotdev/vector" }, { name: "QuestDB", icon: "/img/users/questdb.png", href: "https://github.com/questdb/questdb" }, + { name: "WrenAI", icon: "/img/users/wrenai.png", href: "https://github.com/Canner/WrenAI" }, + { name: "Quickwit", icon: "/img/users/quickwit.png", href: "https://github.com/quickwit-oss/quickwit" }, + { name: "SeaTunnel", icon: "/img/users/seatunnel.png", href: "https://github.com/apache/seatunnel" }, { name: "Databend", icon: "/img/users/databend.png", href: "https://github.com/databendlabs/databend" }, { name: "RisingWave", icon: "/img/users/risingwave.png", href: "https://github.com/risingwavelabs/risingwave" }, - { name: "FileCodeBox", icon: "/img/users/filecodebox.png", href: "https://github.com/vastsa/FileCodeBox" }, + { name: "Loco", icon: "/img/users/loco.png", href: "https://github.com/loco-rs/loco" }, { name: "sccache", icon: "/img/users/sccache.png", href: "https://github.com/mozilla/sccache" }, + { name: "Lance", icon: "/img/users/lance.png", href: "https://github.com/lance-format/lance" }, + { name: "GreptimeDB", icon: "/img/users/greptimedb.png", href: "https://github.com/GreptimeTeam/greptimedb" }, + { name: "Daft", icon: "/img/users/daft.png", href: "https://github.com/Eventual-Inc/Daft" }, + { name: "CrateDB", icon: "/img/users/cratedb.png", href: "https://github.com/crate/crate" }, + { name: "Pants", icon: "/img/users/pants.png", href: "https://github.com/pantsbuild/pants" }, + { name: "rustic", icon: "/img/users/rustic.png", href: "https://github.com/rustic-rs/rustic" }, + { name: "SlateDB", icon: "/img/users/slatedb.png", href: "https://github.com/slatedb/slatedb" }, + { name: "Gravitino", icon: "/img/users/gravitino.png", href: "https://github.com/apache/gravitino" }, + { name: "Spice.ai", icon: "/img/users/spiceai.png", href: "https://github.com/spiceai/spiceai" }, + { name: "Kubeflow Trainer", icon: "/img/users/kubeflow-trainer.png", href: "https://github.com/kubeflow/trainer" }, + { name: "OctoBase", icon: "/img/users/octobase.png", href: "https://github.com/toeverything/OctoBase" }, + { name: "Openraft", icon: "/img/users/openraft.png", href: "https://github.com/databendlabs/openraft" }, + { name: "Walrus", icon: "/img/users/walrus.png", href: "https://github.com/nubskr/walrus" }, + { name: "RobustMQ", icon: "/img/users/robustmq.png", href: "https://github.com/robustmq/robustmq" }, + { name: "lnx", icon: "/img/users/lnx.png", href: "https://github.com/lnx-search/lnx" }, + { name: "Iceberg Rust", icon: "/img/users/iceberg-rust.png", href: "https://github.com/apache/iceberg-rust" }, + { name: "DataFusion Comet", icon: "/img/users/datafusion-comet.png", href: "https://github.com/apache/datafusion-comet" }, + { name: "zino", icon: "/img/users/zino.png", href: "https://github.com/zino-rs/zino" }, ]; // Where people add their own project (PR to the users list). diff --git a/website/src/components/landing/sections.jsx b/website/src/components/landing/sections.jsx index cfb948b66..cfb1d7d16 100644 --- a/website/src/components/landing/sections.jsx +++ b/website/src/components/landing/sections.jsx @@ -17,9 +17,10 @@ * under the License. */ -import React from "react"; +import React, { useState } from "react"; import Link from "@docusaurus/Link"; import { useBaseUrlUtils } from "@docusaurus/useBaseUrl"; +import CodeBlock from "@theme/CodeBlock"; import CodeTabs from "./CodeTabs"; import styles from "./styles.module.css"; import { @@ -29,7 +30,7 @@ import { heroStats, codeSamples, valueProps, - capabilityGroups, + capabilityThemes, usedBy, USERS_LIST_URL, serviceGroups, @@ -93,34 +94,40 @@ export function Hero() { export function UsedBy() { const { withBaseUrl } = useBaseUrlUtils(); return ( - <section className={styles.usedBy}> + <section className={`${styles.section} ${styles.sectionSubtle}`}> <div className="odl-container"> - <div className={styles.usedByHead}> + <div className={styles.sectionHead}> <span className="odl-eyebrow">Used by</span> - <Link className={styles.addLogo} to={USERS_LIST_URL}> - + add your logo - </Link> + <h2 className={styles.sectionTitle}> + Powering AI, analytics, and real-time data + </h2> + <p className={styles.sectionLede}> + OpenDAL runs in production across the open-source ecosystem. These + are some of the projects that build on it. + </p> </div> - <div className={styles.logoWall}> + <ul className={styles.logoWall}> {usedBy.map((u) => ( - <Link - key={u.name} - className={styles.logoItem} - to={u.href} - title={u.name} - > - <img - className={styles.logoMark} - src={withBaseUrl(u.icon)} - alt="" - width="24" - height="24" - loading="lazy" - /> - <span className={styles.logoName}>{u.name}</span> - </Link> + <li key={u.name}> + <Link className={styles.logoItem} to={u.href} title={u.name}> + <img + className={styles.logoMark} + src={withBaseUrl(u.icon)} + alt="" + width="28" + height="28" + loading="lazy" + /> + <span className={styles.logoName}>{u.name}</span> + </Link> + </li> ))} - </div> + <li> + <Link className={styles.addLogo} to={USERS_LIST_URL}> + + add your logo + </Link> + </li> + </ul> </div> </section> ); @@ -155,6 +162,7 @@ export function ValueProps() { } export function Capabilities() { + const [active, setActive] = useState(capabilityThemes[0]); return ( <section className={`${styles.section} ${styles.sectionSubtle}`}> <div className="odl-container"> @@ -162,24 +170,61 @@ export function Capabilities() { <span className="odl-eyebrow">Capabilities</span> <h2 className={styles.sectionTitle}>Configure once. Access anything.</h2> <p className={styles.sectionLede}> - One Operator gives you a full toolkit for real-world data — - streaming, concurrency, multipart uploads, conditionals and - server-side moves — working the same way on every backend. + One Operator is a full toolkit for real-world data — read and write + at scale, recover from failures, and work with files — the same way + on every backend. </p> </div> - <div className={styles.capabilityGrid}> - {capabilityGroups.map((group) => ( - <div className={styles.capabilityGroup} key={group.title}> - <h3 className={styles.capabilityGroupTitle}>{group.title}</h3> - <ul className={styles.capabilityList}> - {group.items.map((item) => ( - <li className={styles.capabilityItem} key={item}> - {item} - </li> - ))} - </ul> + <div className={styles.capabilityExplorer}> + <ul className={styles.capabilityNav}> + {capabilityThemes.map((theme) => { + const selected = active.title === theme.title; + return ( + <li key={theme.title}> + <Link + className={`${styles.capabilityItem} ${ + selected ? styles.capabilityItemActive : "" + }`} + to={theme.doc} + target="_blank" + rel="noreferrer" + aria-current={selected ? "true" : undefined} + onMouseEnter={() => setActive(theme)} + onFocus={() => setActive(theme)} + > + <span className={styles.capabilityText}> + <span className={styles.capabilityItemTitle}> + {theme.title} + </span> + <span className={styles.capabilityItemBlurb}> + {theme.blurb} + </span> + </span> + <span className={styles.capabilityArrow} aria-hidden="true"> + ↗ + </span> + </Link> + </li> + ); + })} + </ul> + <div className={styles.capabilityPreview}> + <div className={styles.codeWindow}> + <div className={styles.windowBar}> + <div className={styles.windowDots} aria-hidden="true"> + <span /> + <span /> + <span /> + </div> + <span className={styles.windowTitle}>{active.title}</span> + </div> + <div className={`${styles.codeBody} ${styles.capabilityCodeBody}`}> + <div className={styles.capabilityCodeFade} key={active.title}> + <CodeBlock language="rust">{active.code}</CodeBlock> + </div> + </div> </div> - ))} + </div> </div> </div> </section> diff --git a/website/src/components/landing/styles.module.css b/website/src/components/landing/styles.module.css index 19e5f8a3e..b76032d14 100644 --- a/website/src/components/landing/styles.module.css +++ b/website/src/components/landing/styles.module.css @@ -273,61 +273,42 @@ } /* ===== Used-by wall ===================================================== */ -.usedBy { - padding-block: clamp(2.25rem, 1.5rem + 3vw, 3.25rem); - border-top: 1px solid var(--odl-border); -} -/* Top row: "Used by" eyebrow (left) + "+ add your logo" (right) over a rule */ -.usedByHead { - display: flex; - align-items: center; - justify-content: space-between; - gap: var(--odl-space-4); - padding-bottom: var(--odl-space-4); - border-bottom: 1px solid var(--odl-border); -} -.addLogo { - font-family: var(--odl-font-mono); - font-size: var(--odl-text-xs); - letter-spacing: 0.04em; - color: var(--odl-fg-subtle); - text-decoration: none; - white-space: nowrap; - transition: color var(--odl-dur) var(--odl-ease); -} -.addLogo:hover { - color: var(--odl-accent); - text-decoration: none; -} -/* Logo wall: grayscale adopter logos that color on hover. Logos are sorted by - GitHub stars; the count shown adapts to viewport width via the nth-child - rules below (4 → 6 → 8). */ .logoWall { + list-style: none; + margin: 0; + padding: 0; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(12.5rem, 1fr)); + gap: var(--odl-space-3); +} +.logoWall > li { display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: space-between; - gap: var(--odl-space-5) var(--odl-space-6); - margin-top: var(--odl-space-6); } .logoItem { - display: inline-flex; + flex: 1; + display: flex; align-items: center; gap: var(--odl-space-3); + padding: var(--odl-space-4); + background: var(--odl-surface); + border: 1px solid var(--odl-border); + border-radius: var(--odl-radius-md); text-decoration: none; filter: grayscale(1); - opacity: 0.62; + opacity: 0.72; transition: opacity var(--odl-dur) var(--odl-ease), - filter var(--odl-dur) var(--odl-ease); + filter var(--odl-dur) var(--odl-ease), + background-color var(--odl-dur) var(--odl-ease); } .logoItem:hover { + background: var(--odl-surface-2); filter: grayscale(0); opacity: 1; text-decoration: none; } .logoMark { - width: 26px; - height: 26px; + width: 28px; + height: 28px; object-fit: contain; border-radius: var(--odl-radius-sm); flex: none; @@ -338,24 +319,31 @@ font-weight: 500; color: var(--odl-fg-muted); white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } - -/* Responsive count: 4 on mobile, 6 on tablet, 8 on desktop. */ -.logoItem:nth-child(n + 5) { - display: none; -} -@media (min-width: 600px) { - .logoItem:nth-child(n + 5) { - display: inline-flex; - } - .logoItem:nth-child(n + 7) { - display: none; - } +/* "+ add your logo" rendered as the final, dashed tile in the wall. */ +.addLogo { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + padding: var(--odl-space-4); + border: 1px dashed var(--odl-border); + border-radius: var(--odl-radius-md); + font-family: var(--odl-font-mono); + font-size: var(--odl-text-xs); + letter-spacing: 0.04em; + color: var(--odl-fg-subtle); + text-decoration: none; + white-space: nowrap; + transition: color var(--odl-dur) var(--odl-ease), + border-color var(--odl-dur) var(--odl-ease); } -@media (min-width: 980px) { - .logoItem:nth-child(n + 7) { - display: inline-flex; - } +.addLogo:hover { + color: var(--odl-accent); + border-color: var(--odl-accent); + text-decoration: none; } /* ===== Value props ====================================================== */ @@ -400,63 +388,98 @@ margin: 0; } -/* ===== Capabilities ===================================================== */ -.capabilityGrid { +/* ===== Capabilities (explorer) ========================================== */ +.capabilityExplorer { display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 1px; - background: var(--odl-border); - border: 1px solid var(--odl-border); - border-radius: var(--odl-radius-lg); - overflow: hidden; -} -.capabilityGroup { - background: var(--odl-surface); - padding: clamp(1.25rem, 1rem + 1.5vw, 2rem); -} -.capabilityGroupTitle { - display: flex; - align-items: center; - gap: var(--odl-space-3); - font-family: var(--odl-font-mono); - font-size: var(--odl-text-xs); - font-weight: 500; - letter-spacing: var(--odl-tracking-label); - text-transform: uppercase; - color: var(--odl-fg-subtle); - margin: 0 0 var(--odl-space-2); -} -.capabilityGroupTitle::before { - content: ""; - width: 0.875rem; - height: 0.375rem; - background: var(--odl-accent); - flex: none; + grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr); + gap: clamp(2rem, 1rem + 3vw, 3.5rem); + align-items: start; } -.capabilityList { +.capabilityNav { list-style: none; margin: 0; padding: 0; + display: flex; + flex-direction: column; + gap: var(--odl-space-2); } .capabilityItem { display: flex; - align-items: baseline; + align-items: flex-start; + justify-content: space-between; gap: var(--odl-space-3); - padding: var(--odl-space-3) 0; - font-size: var(--odl-text-base); - color: var(--odl-fg); - border-top: 1px solid var(--odl-border); + padding: var(--odl-space-4); + border: 1px solid transparent; + border-radius: var(--odl-radius-md); + text-decoration: none; + transition: background-color var(--odl-dur) var(--odl-ease), + border-color var(--odl-dur) var(--odl-ease); } -.capabilityItem:first-child { - border-top: 0; +.capabilityItem:hover { + background: var(--odl-surface); + text-decoration: none; } -.capabilityItem::before { - content: ""; - width: 0.6rem; - height: 2px; - margin-top: 0.6em; - background: var(--odl-border-strong); - flex: none; +.capabilityItemActive { + background: var(--odl-surface); + border-color: var(--odl-border); + box-shadow: var(--odl-shadow-sm); +} +.capabilityText { + display: flex; + flex-direction: column; + gap: 3px; + min-width: 0; +} +.capabilityItemTitle { + font-size: var(--odl-text-md); + font-weight: 650; + letter-spacing: var(--odl-tracking-tight); + color: var(--odl-fg-strong); +} +.capabilityItemBlurb { + font-size: var(--odl-text-sm); + line-height: var(--odl-leading-snug); + color: var(--odl-fg-muted); +} +.capabilityArrow { + font-family: var(--odl-font-mono); + font-size: var(--odl-text-sm); + color: var(--odl-accent); + opacity: 0; + transition: opacity var(--odl-dur) var(--odl-ease); +} +.capabilityItem:hover .capabilityArrow, +.capabilityItemActive .capabilityArrow { + opacity: 1; +} + +/* Sticky code preview that tracks the active capability */ +.capabilityPreview { + position: sticky; + top: 5rem; +} +.capabilityCodeBody { + height: 18rem; + overflow: auto; + background: var(--odl-code-bg); +} +/* Fade only the code itself; the panel background stays put, so switching + snippets never flashes the window surface behind it. */ +.capabilityCodeFade { + animation: odlFade var(--odl-dur) var(--odl-ease); +} +@keyframes odlFade { + from { + opacity: 0; + } + to { + opacity: 1; + } +} +@media (prefers-reduced-motion: reduce) { + .capabilityCodeFade { + animation: none; + } } /* ===== Services ========================================================= */ @@ -729,9 +752,17 @@ @media (max-width: 996px) { .heroInner, .layersInner, - .capabilityGrid { + .capabilityExplorer { grid-template-columns: 1fr; } + .capabilityPreview { + display: none; + } + .capabilityNav { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: var(--odl-space-3); + } .serviceGroups { grid-template-columns: repeat(2, 1fr); } @@ -742,7 +773,8 @@ @media (max-width: 640px) { .valueGrid, - .serviceGroups { + .serviceGroups, + .capabilityNav { grid-template-columns: 1fr; } .heroStats { diff --git a/website/static/img/users/cratedb.png b/website/static/img/users/cratedb.png new file mode 100644 index 000000000..f65bfd245 Binary files /dev/null and b/website/static/img/users/cratedb.png differ diff --git a/website/static/img/users/daft.png b/website/static/img/users/daft.png new file mode 100644 index 000000000..cd845656c Binary files /dev/null and b/website/static/img/users/daft.png differ diff --git a/website/static/img/users/databend.png b/website/static/img/users/databend.png index 27fface5c..908975ca6 100644 Binary files a/website/static/img/users/databend.png and b/website/static/img/users/databend.png differ diff --git a/website/static/img/users/datafusion-comet.png b/website/static/img/users/datafusion-comet.png new file mode 100644 index 000000000..c8aaed47d Binary files /dev/null and b/website/static/img/users/datafusion-comet.png differ diff --git a/website/static/img/users/dify.png b/website/static/img/users/dify.png index d08be7198..d4c3195c1 100644 Binary files a/website/static/img/users/dify.png and b/website/static/img/users/dify.png differ diff --git a/website/static/img/users/filecodebox.png b/website/static/img/users/filecodebox.png deleted file mode 100644 index ba251b3d8..000000000 Binary files a/website/static/img/users/filecodebox.png and /dev/null differ diff --git a/website/static/img/users/gravitino.png b/website/static/img/users/gravitino.png new file mode 100644 index 000000000..c8aaed47d Binary files /dev/null and b/website/static/img/users/gravitino.png differ diff --git a/website/static/img/users/greptimedb.png b/website/static/img/users/greptimedb.png new file mode 100644 index 000000000..de5d5eb61 Binary files /dev/null and b/website/static/img/users/greptimedb.png differ diff --git a/website/static/img/users/hasura.png b/website/static/img/users/hasura.png new file mode 100644 index 000000000..bfd043810 Binary files /dev/null and b/website/static/img/users/hasura.png differ diff --git a/website/static/img/users/iceberg-rust.png b/website/static/img/users/iceberg-rust.png new file mode 100644 index 000000000..c8aaed47d Binary files /dev/null and b/website/static/img/users/iceberg-rust.png differ diff --git a/website/static/img/users/kubeflow-trainer.png b/website/static/img/users/kubeflow-trainer.png new file mode 100644 index 000000000..8cc9ba859 Binary files /dev/null and b/website/static/img/users/kubeflow-trainer.png differ diff --git a/website/static/img/users/lance.png b/website/static/img/users/lance.png new file mode 100644 index 000000000..ed288e5b1 Binary files /dev/null and b/website/static/img/users/lance.png differ diff --git a/website/static/img/users/llamaindex.png b/website/static/img/users/llamaindex.png new file mode 100644 index 000000000..731c902e4 Binary files /dev/null and b/website/static/img/users/llamaindex.png differ diff --git a/website/static/img/users/lnx.png b/website/static/img/users/lnx.png new file mode 100644 index 000000000..dfae753ef Binary files /dev/null and b/website/static/img/users/lnx.png differ diff --git a/website/static/img/users/loco.png b/website/static/img/users/loco.png new file mode 100644 index 000000000..e952fa04e Binary files /dev/null and b/website/static/img/users/loco.png differ diff --git a/website/static/img/users/milvus.png b/website/static/img/users/milvus.png deleted file mode 100644 index 8e3e38be8..000000000 Binary files a/website/static/img/users/milvus.png and /dev/null differ diff --git a/website/static/img/users/octobase.png b/website/static/img/users/octobase.png new file mode 100644 index 000000000..aaf33dfe3 Binary files /dev/null and b/website/static/img/users/octobase.png differ diff --git a/website/static/img/users/openraft.png b/website/static/img/users/openraft.png new file mode 100644 index 000000000..908975ca6 Binary files /dev/null and b/website/static/img/users/openraft.png differ diff --git a/website/static/img/users/pants.png b/website/static/img/users/pants.png new file mode 100644 index 000000000..b9ebd5fbf Binary files /dev/null and b/website/static/img/users/pants.png differ diff --git a/website/static/img/users/pathway.png b/website/static/img/users/pathway.png new file mode 100644 index 000000000..8939308f2 Binary files /dev/null and b/website/static/img/users/pathway.png differ diff --git a/website/static/img/users/questdb.png b/website/static/img/users/questdb.png index 1ae55a66a..663fb3c66 100644 Binary files a/website/static/img/users/questdb.png and b/website/static/img/users/questdb.png differ diff --git a/website/static/img/users/quickwit.png b/website/static/img/users/quickwit.png new file mode 100644 index 000000000..230241887 Binary files /dev/null and b/website/static/img/users/quickwit.png differ diff --git a/website/static/img/users/ragflow.png b/website/static/img/users/ragflow.png new file mode 100644 index 000000000..5bc5c186f Binary files /dev/null and b/website/static/img/users/ragflow.png differ diff --git a/website/static/img/users/risingwave.png b/website/static/img/users/risingwave.png index aed6574ee..ece3bd7d5 100644 Binary files a/website/static/img/users/risingwave.png and b/website/static/img/users/risingwave.png differ diff --git a/website/static/img/users/robustmq.png b/website/static/img/users/robustmq.png new file mode 100644 index 000000000..d13539b64 Binary files /dev/null and b/website/static/img/users/robustmq.png differ diff --git a/website/static/img/users/rustic.png b/website/static/img/users/rustic.png new file mode 100644 index 000000000..53e2a2773 Binary files /dev/null and b/website/static/img/users/rustic.png differ diff --git a/website/static/img/users/sccache.png b/website/static/img/users/sccache.png index 070e3df52..e5a7b2fc0 100644 Binary files a/website/static/img/users/sccache.png and b/website/static/img/users/sccache.png differ diff --git a/website/static/img/users/seatunnel.png b/website/static/img/users/seatunnel.png new file mode 100644 index 000000000..c8aaed47d Binary files /dev/null and b/website/static/img/users/seatunnel.png differ diff --git a/website/static/img/users/slatedb.png b/website/static/img/users/slatedb.png new file mode 100644 index 000000000..16b3d3e9c Binary files /dev/null and b/website/static/img/users/slatedb.png differ diff --git a/website/static/img/users/spiceai.png b/website/static/img/users/spiceai.png new file mode 100644 index 000000000..19e0eceef Binary files /dev/null and b/website/static/img/users/spiceai.png differ diff --git a/website/static/img/users/vaultwarden.png b/website/static/img/users/vaultwarden.png new file mode 100644 index 000000000..394dcae93 Binary files /dev/null and b/website/static/img/users/vaultwarden.png differ diff --git a/website/static/img/users/vector.png b/website/static/img/users/vector.png index 8420ae221..b8a7bf4d9 100644 Binary files a/website/static/img/users/vector.png and b/website/static/img/users/vector.png differ diff --git a/website/static/img/users/walrus.png b/website/static/img/users/walrus.png new file mode 100644 index 000000000..c87b21729 Binary files /dev/null and b/website/static/img/users/walrus.png differ diff --git a/website/static/img/users/wrenai.png b/website/static/img/users/wrenai.png new file mode 100644 index 000000000..5de193a81 Binary files /dev/null and b/website/static/img/users/wrenai.png differ diff --git a/website/static/img/users/zino.png b/website/static/img/users/zino.png new file mode 100644 index 000000000..df460333e Binary files /dev/null and b/website/static/img/users/zino.png differ
