You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fluss.apache.org by ja...@apache.org on 2026/09/23 16:09:57 UTC

(fluss) branch main updated: [docs] Add user logo banner and dedicated user stories (#4469)

This is an automated email from the ASF dual-hosted git repository.

wuchong pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fluss.git


The following commit(s) were added to refs/heads/main by this push:
     new 2a95d96a5 [docs] Add user logo banner and dedicated user stories (#4469)
2a95d96a5 is described below

commit 2a95d96a5c3c73a8c27b38e30736606ed36ae1c8
Author: Jark Wu <ja...@apache.org>
AuthorDate: Thu Sep 24 00:09:52 2026 +0800

    [docs] Add user logo banner and dedicated user stories (#4469)
    
    Show end-user logos on the homepage and link each organization to a
    maintainable story page with a company introduction and public references.
    
    
    AI-Model: gpt-6-astra
    AI-Contributed/Feature: 1589/1589
    AI-Contributed/UT: 0/0
    
    Co-authored-by: Codex <no...@openai.com>
---
 website/docusaurus.config.ts                       |   7 +-
 website/src/components/UserLogoBand/index.tsx      |  58 +++
 .../src/components/UserLogoBand/styles.module.css  | 111 +++++
 website/src/components/UserStory/BrandLogo.tsx     |  49 +++
 website/src/components/UserStory/index.tsx         | 103 +++++
 website/src/components/UserStory/styles.module.css | 358 ++++++++++++++++
 website/src/css/custom.css                         |  28 ++
 website/src/data/userStories.ts                    | 453 +++++++++++++++++++++
 website/src/pages/index.module.css                 |   8 +-
 website/src/pages/index.tsx                        |   2 +
 website/src/pages/user-stories/alibaba-cloud.tsx   |  23 ++
 website/src/pages/user-stories/alibaba.tsx         |  23 ++
 website/src/pages/user-stories/ant-group.tsx       |  23 ++
 website/src/pages/user-stories/cisco.tsx           |  23 ++
 website/src/pages/user-stories/doris.tsx           |  23 ++
 website/src/pages/user-stories/fresha.tsx          |  23 ++
 website/src/pages/user-stories/index.tsx           | 124 ++++++
 website/src/pages/user-stories/iqiyi.tsx           |  23 ++
 website/src/pages/user-stories/jd.tsx              |  23 ++
 website/src/pages/user-stories/rednote.tsx         |  23 ++
 website/src/pages/user-stories/ververica.tsx       |  23 ++
 website/static/img/users/README.md                 |  54 +++
 website/static/img/users/alibaba-cloud.png         | Bin 0 -> 26432 bytes
 website/static/img/users/alibaba.png               | Bin 0 -> 14179 bytes
 website/static/img/users/ant-group-english.png     | Bin 0 -> 32077 bytes
 website/static/img/users/cisco.png                 | Bin 0 -> 75170 bytes
 website/static/img/users/doris.png                 | Bin 0 -> 43867 bytes
 website/static/img/users/fresha.png                | Bin 0 -> 35853 bytes
 website/static/img/users/iqiyi.svg                 |   1 +
 website/static/img/users/jd-english.jpg            | Bin 0 -> 167664 bytes
 website/static/img/users/rednote.png               | Bin 0 -> 5940 bytes
 website/static/img/users/ververica.png             | Bin 0 -> 24263 bytes
 website/static/img/users/white/alibaba.png         | Bin 0 -> 5955 bytes
 website/static/img/users/white/ant-group.png       | Bin 0 -> 6079 bytes
 website/static/img/users/white/cisco.svg           |   1 +
 website/static/img/users/white/fresha.svg          |   1 +
 website/static/img/users/white/iqiyi.svg           |   1 +
 website/static/img/users/white/jd.png              | Bin 0 -> 4554 bytes
 website/static/img/users/white/rednote.png         | Bin 0 -> 4463 bytes
 39 files changed, 1582 insertions(+), 7 deletions(-)

diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts
index 61dd0cfa7..ebda9f848 100644
--- a/website/docusaurus.config.ts
+++ b/website/docusaurus.config.ts
@@ -296,6 +296,10 @@ const config: Config = {
           position: 'left',
           type: 'dropdown',
           items: [
+            {
+              label: 'User Stories',
+              to: '/user-stories',
+            },
             {
               label: 'Talks',
               to: '/learn/talks',
@@ -348,6 +352,7 @@ const config: Config = {
         {
           title: 'Community',
           items: [
+            {label: 'User Stories', to: '/user-stories'},
             {label: 'GitHub', href: 'https://github.com/apache/fluss'},
             {label: 'Slack', href: 'https://join.slack.com/t/apache-fluss/shared_invite/zt-473vgmvjr-cmIma~_iAA4cN02o5u2pDQ'},
             {label: 'Welcome', to: '/community/welcome'},
@@ -393,4 +398,4 @@ const config: Config = {
   } satisfies Preset.ThemeConfig,
 };
 
-export default config;
\ No newline at end of file
+export default config;
diff --git a/website/src/components/UserLogoBand/index.tsx b/website/src/components/UserLogoBand/index.tsx
new file mode 100644
index 000000000..12081636e
--- /dev/null
+++ b/website/src/components/UserLogoBand/index.tsx
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import clsx from 'clsx';
+import Link from '@docusaurus/Link';
+import BrandLogo from '@site/src/components/UserStory/BrandLogo';
+import {endUsers} from '@site/src/data/userStories';
+import styles from './styles.module.css';
+
+/** A quiet, continuous strip of end-user stories below the homepage hero. */
+export default function UserLogoBand(): JSX.Element {
+    return (
+        <section
+            className={styles.band}
+            aria-label="Organizations using Apache Fluss"
+        >
+            <div className={styles.viewport}>
+                <div className={styles.track}>
+                    {[false, true].map((duplicate) => (
+                        <div
+                            key={String(duplicate)}
+                            className={clsx(styles.group, duplicate && styles.duplicate)}
+                            aria-hidden={duplicate || undefined}
+                        >
+                            {endUsers.map((story) => (
+                                <Link
+                                    key={story.organizationId}
+                                    to={story.href}
+                                    className={styles.logoLink}
+                                    tabIndex={duplicate ? -1 : undefined}
+                                    aria-label={`Read ${story.name}'s story`}
+                                    title={`${story.name}: ${story.title}`}
+                                >
+                                    <BrandLogo story={story} white className={styles.logo} />
+                                </Link>
+                            ))}
+                        </div>
+                    ))}
+                </div>
+            </div>
+        </section>
+    );
+}
diff --git a/website/src/components/UserLogoBand/styles.module.css b/website/src/components/UserLogoBand/styles.module.css
new file mode 100644
index 000000000..9a0631cba
--- /dev/null
+++ b/website/src/components/UserLogoBand/styles.module.css
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.band {
+    position: relative;
+    margin: 72px auto -32px;
+    max-width: 1240px;
+}
+
+.viewport {
+    overflow: hidden;
+    mask-image: linear-gradient(to right, transparent, #000 5%, #000 95%, transparent);
+    -webkit-mask-image: linear-gradient(to right, transparent, #000 5%, #000 95%, transparent);
+}
+
+.track {
+    display: flex;
+    width: max-content;
+    animation: travel 52s linear infinite;
+}
+
+.group {
+    display: flex;
+    flex: none;
+    align-items: center;
+    gap: 48px;
+    padding-right: 48px;
+}
+
+.logoLink {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex: none;
+    width: 144px;
+    height: 48px;
+    border-radius: 4px;
+    opacity: 0.84;
+    transition: opacity 160ms ease;
+}
+
+.logoLink:hover,
+.logoLink:focus-visible {
+    opacity: 1;
+}
+.logoLink:focus-visible {
+    outline: 2px solid #fff;
+    outline-offset: -4px;
+}
+.logo {
+    display: block;
+    width: 144px;
+    height: 32px;
+}
+
+.band:hover .track,
+.viewport:focus-within .track {
+    animation-play-state: paused;
+}
+
+/* Keyboard users get a stable, scrollable list with one focus stop per user. */
+.viewport:has(a:focus-visible) {
+    overflow-x: auto;
+}
+.viewport:has(a:focus-visible) .track {
+    animation: none;
+}
+.viewport:has(a:focus-visible) .duplicate {
+    display: none;
+}
+
+@keyframes travel {
+    to {
+        transform: translateX(-50%);
+    }
+}
+
+@media (max-width: 600px), (hover: none), (prefers-reduced-motion: reduce) {
+    .band {
+        margin-top: 40px;
+    }
+    .viewport {
+        overflow-x: auto;
+        scrollbar-width: thin;
+        scrollbar-color: #7aafcb transparent;
+    }
+    .track {
+        animation: none;
+    }
+    .group {
+        gap: 32px;
+        padding: 0 24px;
+    }
+    .duplicate {
+        display: none;
+    }
+}
diff --git a/website/src/components/UserStory/BrandLogo.tsx b/website/src/components/UserStory/BrandLogo.tsx
new file mode 100644
index 000000000..04cc892f9
--- /dev/null
+++ b/website/src/components/UserStory/BrandLogo.tsx
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import useBaseUrl from '@docusaurus/useBaseUrl';
+import {logoArtwork, whiteLogoArtwork, type UserStory} from '@site/src/data/userStories';
+
+/** Render the selected original artwork with consistent clear space. */
+export default function BrandLogo({
+    story,
+    white = false,
+    className,
+}: {
+    story: UserStory;
+    white?: boolean;
+    className?: string;
+}): JSX.Element {
+    const artwork = white ? whiteLogoArtwork[story.organizationId] : logoArtwork[story.organizationId];
+    const filename = white
+        ? `white/${artwork.file}`
+        : artwork.file ?? `${story.organizationId}.png`;
+    const src = useBaseUrl(`/img/users/${filename}`);
+
+    return (
+        <svg
+            className={className}
+            viewBox={artwork.viewBox}
+            role="img"
+            aria-label={story.name}
+            preserveAspectRatio="xMidYMid meet"
+        >
+            <image href={src} width={artwork.width} height={artwork.height} />
+        </svg>
+    );
+}
diff --git a/website/src/components/UserStory/index.tsx b/website/src/components/UserStory/index.tsx
new file mode 100644
index 000000000..a70dc9ecf
--- /dev/null
+++ b/website/src/components/UserStory/index.tsx
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import Layout from '@theme/Layout';
+import Link from '@docusaurus/Link';
+import BrandLogo from './BrandLogo';
+import {userStories, whiteLogoArtwork} from '@site/src/data/userStories';
+import styles from './styles.module.css';
+
+/** A short case study based on the organization's public community submission. */
+export default function UserStory({id}: {id: string}): JSX.Element {
+    const story = userStories.find((entry) => entry.id === id);
+    if (!story) {
+        throw new Error(`No local user story for ${id}`);
+    }
+    const hasWhiteLogo = Boolean(whiteLogoArtwork[story.organizationId]);
+
+    return (
+        <Layout title={`${story.name}: ${story.title}`} description={story.summary}>
+            <main className={styles.page}>
+                <header className={styles.detailHero}>
+                    <div className={styles.readingWidth}>
+                        <Link to="/user-stories/" className={styles.backLink}>
+                            ← User Stories
+                        </Link>
+                        <div className={hasWhiteLogo ? undefined : styles.detailLogoPanel}>
+                            <BrandLogo
+                                story={story}
+                                white={hasWhiteLogo}
+                                className={styles.detailLogo}
+                            />
+                        </div>
+                        <div className={styles.detailMeta}>
+                            {story.name} · {story.region}
+                        </div>
+                        <h1>{story.title}</h1>
+                        <p>{story.summary}</p>
+                    </div>
+                </header>
+                <article className={styles.readingWidth}>
+                    <div className={styles.articleBody}>
+                        <section>
+                            <h2>
+                                About <Link to={story.website}>{story.name}</Link>
+                            </h2>
+                            <p>{story.about}</p>
+                        </section>
+                        {story.sections.map((section) => (
+                            <section key={section.heading}>
+                                <h2>{section.heading}</h2>
+                                <p>{section.text}</p>
+                            </section>
+                        ))}
+                        {story.references && story.references.length > 0 && (
+                            <section>
+                                <h2>Further reading</h2>
+                                <ul className={styles.references}>
+                                    {story.references.map((reference) => (
+                                        <li key={reference.href}>
+                                            <Link to={reference.href}>
+                                                <span>{reference.title}</span>
+                                                <span aria-hidden="true">↗</span>
+                                            </Link>
+                                        </li>
+                                    ))}
+                                </ul>
+                            </section>
+                        )}
+                        <aside className={styles.source}>
+                            <strong>Shared by {story.name}</strong>
+                            <p>
+                                This overview draws on the team’s public community submission and
+                                linked resources. Deployment details and results reflect the
+                                workloads described in those sources.
+                            </p>
+                            <Link to={story.submission}>
+                                Read the original submission <span aria-hidden="true">↗</span>
+                            </Link>
+                        </aside>
+                        <Link to="/user-stories/" className={styles.readLink}>
+                            Explore more user stories →
+                        </Link>
+                    </div>
+                </article>
+            </main>
+        </Layout>
+    );
+}
diff --git a/website/src/components/UserStory/styles.module.css b/website/src/components/UserStory/styles.module.css
new file mode 100644
index 000000000..0b7eac2c7
--- /dev/null
+++ b/website/src/components/UserStory/styles.module.css
@@ -0,0 +1,358 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.page {
+    --story-ink: #102856;
+    --story-muted: #536778;
+    --story-line: #dce5eb;
+    --story-surface: #fff;
+    background: #f5f8fa;
+    color: var(--story-ink);
+}
+
+:global([data-theme='dark']) .page {
+    --story-ink: #e6ecfa;
+    --story-muted: #a8b9cd;
+    --story-line: #293f5d;
+    --story-surface: #142744;
+    background: #0c1b31;
+}
+
+.container {
+    max-width: 1240px;
+    margin: 0 auto;
+    padding: 0 32px;
+}
+.hero,
+.detailHero {
+    background: #102856;
+    color: white;
+}
+.hero {
+    padding: 88px 0 80px;
+}
+.eyebrow {
+    color: #a6cada;
+    font-size: 12px;
+    letter-spacing: 0.14em;
+    text-transform: uppercase;
+}
+.hero h1 {
+    color: #fff;
+    font-size: clamp(3rem, 6vw, 5rem);
+    letter-spacing: -0.045em;
+    margin: 16px 0 24px;
+    line-height: 1.08;
+}
+.hero p {
+    color: #c3d5e3;
+    font-size: 20px;
+    line-height: 1.65;
+    margin: 0;
+}
+.storyGroup {
+    padding-top: 72px;
+}
+.groupHeading {
+    margin-bottom: 28px;
+}
+.groupHeading h2 {
+    color: var(--story-ink);
+    font-size: 30px;
+    letter-spacing: -0.025em;
+    margin: 0 0 8px;
+}
+.groupHeading p {
+    color: var(--story-muted);
+    margin: 0;
+}
+.grid {
+    display: grid;
+    grid-template-columns: repeat(3, minmax(0, 1fr));
+    gap: 24px;
+}
+.card {
+    background: var(--story-surface);
+    border: 1px solid var(--story-line);
+    border-radius: 12px;
+    overflow: hidden;
+    transition:
+        border-color 160ms ease,
+        box-shadow 160ms ease;
+}
+.card:hover {
+    border-color: #7aafcb;
+    box-shadow: 0 8px 24px rgba(16, 40, 86, 0.07);
+}
+.cardLink {
+    display: flex;
+    height: 100%;
+    flex-direction: column;
+    color: inherit;
+    text-decoration: none;
+}
+.cardLink:hover {
+    color: inherit;
+    text-decoration: none;
+}
+.cardLink:focus-visible {
+    outline: 3px solid #7aafcb;
+    outline-offset: -3px;
+}
+.logoPanel {
+    display: flex;
+    height: 140px;
+    padding: 32px;
+    align-items: center;
+    justify-content: flex-start;
+    background: #fff;
+    border-bottom: 1px solid var(--story-line);
+}
+.cardLogo {
+    width: 184px;
+    height: 60px;
+}
+.cardBody {
+    display: flex;
+    flex: 1;
+    flex-direction: column;
+    padding: 28px;
+}
+.organization {
+    display: flex;
+    align-items: center;
+    flex-wrap: wrap;
+    gap: 8px 12px;
+    font-size: 12px;
+    color: var(--story-muted);
+    margin-bottom: 14px;
+}
+.card h3 {
+    color: var(--story-ink);
+    font-size: 21px;
+    line-height: 1.4;
+    letter-spacing: -0.02em;
+    margin: 0 0 14px;
+}
+.card p {
+    color: var(--story-muted);
+    font-size: 14px;
+    line-height: 1.75;
+    margin: 0 0 24px;
+}
+.tags {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 6px;
+    margin-top: auto;
+    margin-bottom: 24px;
+}
+.tags span {
+    border: 1px solid var(--story-line);
+    padding: 3px 8px;
+    border-radius: 4px;
+    font-size: 11px;
+    color: var(--story-muted);
+}
+.readLink {
+    display: inline-flex;
+    gap: 8px;
+    align-items: center;
+    font-weight: 600;
+    font-size: 14px;
+    color: var(--story-ink);
+}
+.readLink span {
+    margin-left: auto;
+}
+.contribute {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    gap: 32px;
+    padding: 40px 0 64px;
+    margin-top: 64px;
+    border-top: 1px solid var(--story-line);
+}
+.contribute h2 {
+    color: var(--story-ink);
+    font-size: 26px;
+    letter-spacing: -0.02em;
+    margin: 0 0 12px;
+}
+.contribute p {
+    margin: 0;
+    color: var(--story-muted);
+}
+.contribute > a {
+    flex-shrink: 0;
+    color: var(--story-ink);
+    font-weight: 600;
+    border-bottom: 1px solid #7aafcb;
+    padding-bottom: 6px;
+}
+.readingWidth {
+    max-width: 820px;
+    margin: 0 auto;
+    padding: 0 32px;
+}
+.detailHero {
+    padding: 48px 0 64px;
+}
+.backLink {
+    display: inline-block;
+    color: #c3d5e3;
+    font-size: 14px;
+    margin-bottom: 48px;
+}
+.backLink:hover {
+    color: #fff;
+}
+.detailLogo {
+    display: block;
+    width: 180px;
+    height: 60px;
+    margin-bottom: 32px;
+}
+.detailLogoPanel {
+    width: fit-content;
+    padding: 16px 24px;
+    margin-bottom: 32px;
+    border-radius: 8px;
+    background: #fff;
+}
+.detailLogoPanel .detailLogo {
+    margin-bottom: 0;
+}
+.detailMeta {
+    color: #a6cada;
+    font-size: 13px;
+    margin-bottom: 16px;
+}
+.detailHero h1 {
+    color: #fff;
+    font-size: clamp(2rem, 4vw, 3rem);
+    line-height: 1.2;
+    letter-spacing: -0.035em;
+    margin: 0 0 24px;
+}
+.detailHero p {
+    color: #c3d5e3;
+    font-size: 18px;
+    line-height: 1.75;
+    margin: 0;
+}
+.articleBody {
+    padding: 48px 0 72px;
+}
+.articleBody section {
+    margin-bottom: 40px;
+}
+.articleBody h2 {
+    color: var(--story-ink);
+    font-size: 25px;
+    line-height: 1.4;
+    letter-spacing: -0.025em;
+}
+.articleBody p {
+    color: var(--story-muted);
+    font-size: 17px;
+    line-height: 1.85;
+}
+.references {
+    list-style: none;
+    padding: 0;
+    margin: 24px 0 0;
+    border-top: 1px solid var(--story-line);
+}
+.references li {
+    border-bottom: 1px solid var(--story-line);
+}
+.references a {
+    display: flex;
+    justify-content: space-between;
+    align-items: baseline;
+    gap: 24px;
+    padding: 18px 0;
+    color: var(--story-ink);
+    font-size: 16px;
+    line-height: 1.6;
+    font-weight: 600;
+}
+.references a:focus-visible {
+    outline: 2px solid #7aafcb;
+    outline-offset: 4px;
+}
+.source {
+    padding: 24px;
+    border: 1px solid var(--story-line);
+    border-left: 3px solid #7aafcb;
+    background: var(--story-surface);
+    margin: 48px 0 32px;
+}
+.source p {
+    font-size: 14px;
+    margin: 10px 0;
+}
+.source a {
+    font-size: 14px;
+}
+
+@media (max-width: 996px) {
+    .grid {
+        grid-template-columns: repeat(2, minmax(0, 1fr));
+    }
+}
+@media (max-width: 600px) {
+    .container,
+    .readingWidth {
+        padding: 0 24px;
+    }
+    .hero {
+        padding: 56px 0;
+    }
+    .hero p {
+        font-size: 17px;
+    }
+    .storyGroup {
+        padding-top: 48px;
+    }
+    .grid {
+        grid-template-columns: minmax(0, 1fr);
+        gap: 20px;
+    }
+    .logoPanel {
+        height: 120px;
+        padding: 28px;
+    }
+    .cardBody {
+        padding: 24px;
+    }
+    .contribute {
+        align-items: flex-start;
+        flex-direction: column;
+        margin-top: 48px;
+    }
+    .detailHero {
+        padding: 32px 0 48px;
+    }
+}
+@media (prefers-reduced-motion: reduce) {
+    .card {
+        transition: none;
+    }
+}
diff --git a/website/src/css/custom.css b/website/src/css/custom.css
index be97b89f6..a8625eecd 100644
--- a/website/src/css/custom.css
+++ b/website/src/css/custom.css
@@ -756,6 +756,34 @@ h1, h2, h3, h4, h5, h6 {
   padding: 0 4px;
 }
 
+/* Keep navigation readable between the mobile and full desktop layouts. */
+@media (min-width: 997px) and (max-width: 1199px) {
+  .navbar__inner {
+    padding: 0 8px;
+  }
+
+  .navbar__brand {
+    flex-shrink: 0;
+  }
+
+  .navbar__link {
+    padding: 0 8px;
+    white-space: nowrap;
+  }
+
+  .navbar .DocSearch-Button {
+    width: 40px;
+    min-width: 40px;
+    padding: 0;
+    justify-content: center;
+  }
+
+  .navbar .DocSearch-Button-Placeholder,
+  .navbar .DocSearch-Button-Keys {
+    display: none;
+  }
+}
+
 /* Version dropdown badge */
 .navbar .navbar__item--version,
 .navbar .badge {
diff --git a/website/src/data/userStories.ts b/website/src/data/userStories.ts
new file mode 100644
index 000000000..a38abc384
--- /dev/null
+++ b/website/src/data/userStories.ts
@@ -0,0 +1,453 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export type StoryCategory = 'End user' | 'Service provider' | 'Ecosystem integration';
+
+export interface UserStory {
+    id: string;
+    organizationId: string;
+    name: string;
+    category: StoryCategory;
+    region: string;
+    about: string;
+    website: string;
+    title: string;
+    summary: string;
+    tags: string[];
+    href: string;
+    submission: string;
+    sections: {heading: string; text: string}[];
+    references?: {title: string; href: string}[];
+}
+
+export const userDiscussion = 'https://github.com/apache/fluss/discussions/4033';
+
+// Keep one card per organization, linking to its dedicated overview.
+// Organization overviews can collect multiple published stories as references.
+export const userStories: UserStory[] = [
+    {
+        id: 'alibaba',
+        organizationId: 'alibaba',
+        name: 'Alibaba Group',
+        category: 'End user',
+        region: 'China',
+        about: 'Alibaba Group is a technology company whose core businesses are e-commerce and cloud computing.',
+        website: 'https://www.alibabagroup.com/en-US/faqs-business-operations',
+        title: 'Unified real-time analytics across Alibaba Group',
+        summary:
+            'Alibaba uses Fluss as a shared ingestion and serving layer for behavioral analytics across Taobao, Tmall, Ele.me, Amap, and Alibaba Pictures.',
+        tags: ['User-behavior analytics', 'Streaming Lakehouse'],
+        href: '/user-stories/alibaba/',
+        submission: `${userDiscussion}#discussioncomment-18067474`,
+        sections: [
+            {
+                heading: 'Behavioral data collection at group scale',
+                text: 'The A+ platform collects events from web, mobile apps, mini-programs, and server SDKs. Alibaba reports processing 4 PB daily during Double 11 2025, with peaks of 100 million TPS and 100 GiB/s, and over 40% lower pipeline costs.',
+            },
+            {
+                heading: 'Real-time experiments at Taotian',
+                text: 'Across more than 100 experimentation scenarios, Fluss feeds search, recommendations, content, and growth analytics. The team reports 59% lower Flink CPU usage, 73% lower memory usage, and near elimination of over 100 TB of operator state.',
+            },
+            {
+                heading: 'Streaming into the Lakehouse',
+                text: 'Fluss tiers data into Paimon/Alake, replacing separate Lambda pipelines. Streaming consumers receive updates within seconds; the lake becomes available within minutes. Partial-column updates also lower the cost of batch backfills.',
+            },
+        ],
+        references: [
+            {
+                title: 'Taobao: Search and recommendations',
+                href: '/blog/taobao-practice/',
+            },
+            {
+                title: 'Taobao Instant Commerce: Real-time decisions',
+                href: '/blog/taobao-instant-commerce-real-time-decision/',
+            },
+            {
+                title: 'Alibaba Double 11: Trillion-scale production (Chinese)',
+                href: 'https://zhuanlan.zhihu.com/p/2000632412443535295',
+            },
+        ],
+    },
+    {
+        id: 'iqiyi',
+        organizationId: 'iqiyi',
+        name: 'iQIYI',
+        category: 'End user',
+        region: 'China',
+        about: 'iQIYI is an online entertainment platform in China that produces and distributes video content through subscriptions, advertising, and content licensing.',
+        website: 'https://ir.iqiyi.com/',
+        title: 'Fast lookups and feature backfills at massive scale',
+        summary:
+            'iQIYI combines primary-key lookups, streaming feature backfills, and lake tiering to serve its machine-learning data pipelines.',
+        tags: ['ML features', 'Primary-key lookups'],
+        href: '/user-stories/iqiyi/',
+        submission: `${userDiscussion}#discussioncomment-18074056`,
+        sections: [
+            {
+                heading: 'Moving state out of Flink jobs',
+                text: 'Large Flink state can slow recovery and make data difficult to inspect. iQIYI uses Fluss primary-key tables as a schema-enforced state store. In its reported production workload, primary-key lookups achieve P99 latency below one millisecond at 100,000 queries per second.',
+            },
+            {
+                heading: 'Replaying historical features',
+                text: 'Fluss log tables provide the streaming source for long-term ML feature backfills. Longer retention and column pruning let jobs replay the fields they need. Combined with the disaggregated state architecture, iQIYI reports that a ten-tablet-server cluster handles up to one million queries per second for backfill workloads and can backfill one day of data in about thirty minutes.',
+            },
+            {
+                heading: 'Serving hot and cold feature data',
+                text: 'For real-time feature enrichment, iQIYI combines Fluss primary-key tables with Paimon lake tiering and fallback lookups for cold data. The team reports ingestion of up to 20 GB/s and approximately 50% lower cost than its previous HBase-based solution.',
+            },
+        ],
+    },
+    {
+        id: 'fresha',
+        organizationId: 'fresha',
+        name: 'Fresha',
+        category: 'End user',
+        region: 'United Kingdom',
+        about: 'Fresha provides booking, payments, and business-management software for beauty and wellness businesses, alongside a consumer marketplace for appointments.',
+        website: 'https://www.fresha.com/for-business',
+        title: 'Bringing transactional data into a real-time serving layer',
+        summary:
+            'Fresha runs Fluss on Amazon EKS, uses Delta Join to denormalize commerce data, and contributes Kubernetes and multi-language client support.',
+        tags: ['Delta Join', 'Kubernetes'],
+        href: '/user-stories/fresha/',
+        submission: `${userDiscussion}#discussioncomment-18081546`,
+        sections: [
+            {
+                heading: 'Enriching transactional streams',
+                text: 'Fresha uses Fluss as the real-time serving layer between its operational databases and analytical stack. Flink ingests database changes into primary-key tables, then uses lookup joins to enrich appointment events with dimensional data stored in Fluss.',
+            },
+            {
+                heading: 'Denormalizing commerce data with Delta Join',
+                text: 'Sales, sale items, and related records form a deep transactional hierarchy. By storing each level in Fluss, eligible Flink joins can use Delta Join to look up matching records instead of retaining both inputs in operator state. Fresha reports that this brings pipeline state close to zero and reduces recovery from tens of minutes to seconds.',
+            },
+            {
+                heading: 'Running on Kubernetes and connecting applications',
+                text: 'Fresha runs Fluss on Amazon EKS with S3 remote storage and the community Helm chart. Its engineers contribute Kubernetes deployment support, the Rust core client, and Elixir bindings so application services can access Fluss directly.',
+            },
+        ],
+        references: [
+            {
+                title: 'Processing Patterns with Apache Fluss',
+                href: 'https://medium.com/fresha-data-engineering/processing-patterns-with-apache-fluss-302449793c43',
+            },
+        ],
+    },
+    {
+        id: 'rednote',
+        organizationId: 'rednote',
+        name: 'rednote',
+        category: 'End user',
+        region: 'China',
+        about: 'rednote (Xiaohongshu) is a lifestyle community platform where people discover and share interests, experiences, and recommendations.',
+        website: 'https://www.rednote.com/',
+        title: 'Migrating a core real-time indexing pipeline from Kafka',
+        summary:
+            'rednote uses column pruning and tiered storage to reduce read amplification and isolate historical index builds from online workloads.',
+        tags: ['Real-time indexing', 'Streaming lakehouse'],
+        href: '/user-stories/rednote/',
+        submission: `${userDiscussion}#discussioncomment-18089790`,
+        sections: [
+            {
+                heading: 'Reading fewer columns for real-time indexes',
+                text: 'Search, recommendation, and advertising services consume different fields from the same wide tables. rednote moved its core indexing pipeline toward Fluss so each consumer can request only the columns it needs. The team reports 30% to 90% lower bandwidth usage across online workloads and approximately three times the peak throughput.',
+            },
+            {
+                heading: 'Separating historical builds from online traffic',
+                text: 'Index builders read historical Fluss log files directly from object storage. This keeps large scans from competing with real-time consumers for broker bandwidth and cache. rednote reports that batch and incremental index construction became 50% to 80% faster.',
+            },
+            {
+                heading: 'Connecting the pipeline to Paimon',
+                text: 'Fluss also tiers the data into Apache Paimon for exploration, migration validation, and historical analytics. Load tests, extended dual runs, and a phased rollout helped the team validate correctness and stability before moving core production traffic.',
+            },
+        ],
+        references: [
+            {
+                title: 'From Kafka to Fluss: How Rednote Migrated a Core Real-Time Indexing Pipeline',
+                href: '/blog/rednote-kafka-to-fluss-real-time-indexing/',
+            },
+        ],
+    },
+    {
+        id: 'ant-group',
+        organizationId: 'ant-group',
+        name: 'Ant Group',
+        category: 'End user',
+        region: 'China',
+        about: 'Ant Group is a digital technology company and the operator of Alipay, which connects consumers with payments and everyday services.',
+        website: 'https://www.antgroup.com/en',
+        title: 'Unifying real-time marketing data at Alipay',
+        summary:
+            'Alipay uses partial updates and columnar streaming to bring marketing events together and serve fresh data across its marketing platform.',
+        tags: ['Partial updates', 'Real-time marketing'],
+        href: '/user-stories/ant-group/',
+        submission: `${userDiscussion}#discussioncomment-18123921`,
+        sections: [
+            {
+                heading: 'One attribution table, many event streams',
+                text: 'Alipay’s marketing platform supports coupons, red packets, payment marketing, merchant offers, and personalized recommendations. Fluss primary-key tables merge events such as coupon issuance, redemption, rewards, and task participation through partial updates. Each upstream job writes the columns it owns, while the storage layer combines them into a shared attribution table.',
+            },
+            {
+                heading: 'Fresh data with less processing state',
+                text: 'Moving column-level merging into Fluss reduces chained streaming joins and the state held in Flink. The team describes an improvement from multi-minute pipeline latency to second-level data availability. Column pruning lets downstream jobs consume only the fields required for their real-time analytics and feature pipelines.',
+            },
+            {
+                heading: 'Connecting streaming and lakehouse analytics',
+                text: 'Alipay is building a unified streaming storage layer that tiers data into the lakehouse. Real-time applications read fresh data from Fluss, while batch analytics and next-day validation use the lakehouse representation. This simplifies the previous architecture of separate streaming and lakehouse storage, dual writes, and additional data-copy jobs.',
+            },
+        ],
+    },
+    {
+        id: 'jd',
+        organizationId: 'jd',
+        name: 'JD',
+        category: 'End user',
+        region: 'China',
+        about: 'JD is a supply-chain technology and services company with businesses in retail, logistics, and related services.',
+        website: 'https://corporate.jd.com/',
+        title: 'Connecting online and offline samples for model training',
+        summary:
+            'JD combines Fluss and Apache Hudi to produce recommendation-ranking samples for online serving and near-real-time and offline model training.',
+        tags: ['Model training', 'Streaming lakehouse'],
+        href: '/user-stories/jd/',
+        submission: `${userDiscussion}#discussioncomment-18149379`,
+        sections: [
+            {
+                heading: 'A shared foundation for training samples',
+                text: 'JD builds its recommendation-ranking sample pipeline on Apache Fluss and Apache Hudi. The architecture connects streaming and batch sample generation with model training, supporting online sample serving alongside near-real-time and offline training data.',
+            },
+            {
+                heading: 'Tiering samples into the lake',
+                text: 'The pipeline uses the tiering service to synchronize data to Hudi lake storage in near real time. JD reports contributing the Fluss–Hudi integration back to the open-source community.',
+            },
+            {
+                heading: 'Reading only what a training job needs',
+                text: 'During online training, jobs use Fluss column pruning to read only the fields needed by the model. This improves reading efficiency and reduces bandwidth consumption. JD also collaborates with the community on message-queue capabilities such as offset management.',
+            },
+        ],
+    },
+    {
+        id: 'cisco',
+        organizationId: 'cisco',
+        name: 'Cisco Webex',
+        category: 'End user',
+        region: 'Global',
+        about: 'Webex is Cisco’s collaboration and customer-experience platform, offering meetings, calling, messaging, and contact-center services.',
+        website: 'https://www.webex.com/',
+        title: 'Streaming Lakehouse for high-throughput events',
+        summary:
+            'Cisco Webex’s streaming Lakehouse architecture combines Fluss, Flink, and Iceberg for event ingestion, primary-key lookups, and simpler data lifecycle management.',
+        tags: ['Event ingestion', 'Primary-key lookups'],
+        href: '/user-stories/cisco/',
+        submission: `${userDiscussion}#discussioncomment-18173301`,
+        sections: [
+            {
+                heading: 'A real-time layer for event data',
+                text: 'Cisco Webex’s streaming Lakehouse architecture brings together Apache Fluss for high-throughput event ingestion, Apache Flink for processing, and Apache Iceberg for historical analytics.',
+            },
+            {
+                heading: 'Reducing the state in Flink',
+                text: 'The team uses low-latency primary-key lookups in Fluss to reduce the state maintained inside Flink jobs. Cisco Webex reports that this reduces job memory usage to approximately one-third of the previous level.',
+            },
+            {
+                heading: 'Contributing enterprise integration',
+                text: 'Cisco Webex contributes implicit time partitioning, SASL/OAUTHBEARER authentication, and group-based ACL authorization to the Fluss community. These capabilities support data lifecycle management and integration with enterprise identity and access-control infrastructure.',
+            },
+        ],
+    },
+    {
+        id: 'alibaba-cloud',
+        organizationId: 'alibaba-cloud',
+        name: 'Alibaba Cloud',
+        category: 'Service provider',
+        region: 'China',
+        about: 'Alibaba Cloud provides cloud infrastructure and services for computing, storage, databases, and data analytics.',
+        website: 'https://www.alibabacloud.com/en/product',
+        title: 'Fully-managed streaming storage for Apache Fluss',
+        summary:
+            'Alibaba Cloud provides managed Fluss instances with visual table management, access controls, monitoring, and hot and cold data tiering.',
+        tags: ['Managed service', 'Flink integration'],
+        href: '/user-stories/alibaba-cloud/',
+        submission: `${userDiscussion}#discussioncomment-18064873`,
+        sections: [
+            {
+                heading: 'Managed streaming storage',
+                text: 'Alibaba Cloud offers a fully managed service built on Apache Fluss. Customers create isolated, highly available instances while the service handles deployment and operation of the underlying Fluss servers and ZooKeeper nodes.',
+            },
+            {
+                heading: 'Operating through a shared console',
+                text: 'The service includes visual database and table management, fine-grained access controls, monitoring and alerts, and hot and cold data tiering. These capabilities bring streaming storage administration into the cloud platform.',
+            },
+            {
+                heading: 'Building with Flink and the Lakehouse',
+                text: 'Integration with Alibaba Cloud Realtime Compute for Apache Flink supports real-time warehouses and Streaming Lakehouse workloads. Teams can use Fluss capabilities such as column pruning, partial updates, and Delta Join within their data pipelines.',
+            },
+        ],
+        references: [
+            {
+                title: 'Streaming Storage for Apache Fluss — Alibaba Cloud',
+                href: 'https://www.aliyun.com/product/flink/fluss',
+            },
+        ],
+    },
+    {
+        id: 'ververica',
+        organizationId: 'ververica',
+        name: 'Ververica',
+        category: 'Service provider',
+        region: 'Europe',
+        about: 'Ververica develops an enterprise streaming data platform built on Apache Flink for deploying and operating real-time data applications.',
+        website: 'https://www.ververica.com/product',
+        title: 'Self-managed streaming storage for Apache Fluss',
+        summary:
+            'Ververica integrates Fluss into its platform with cluster management, database and table operations, scaling, and lake tiering.',
+        tags: ['Self-managed service', 'Flink integration'],
+        href: '/user-stories/ververica/',
+        submission: `${userDiscussion}#discussioncomment-18077747`,
+        sections: [
+            {
+                heading: 'Streaming storage in the customer environment',
+                text: 'Ververica integrates Apache Fluss into its self-managed platform, letting organizations run streaming storage in their own infrastructure alongside Flink processing.',
+            },
+            {
+                heading: 'Managing clusters and data',
+                text: 'The platform provides visual and programmatic management for Fluss clusters, databases, and tables. Teams can manage lake tiering, rebalance data, and scale clusters through the platform’s operational tooling.',
+            },
+            {
+                heading: 'A shared layer for streaming and historical data',
+                text: 'Fluss adds low-latency reads and writes, columnar streaming, and table updates to Ververica’s data platform. Flink integration and lake tiering connect real-time pipelines with historical data for warehouse and Streaming Lakehouse applications.',
+            },
+        ],
+        references: [
+            {
+                title: 'Ververica Platform for Apache Fluss — Documentation',
+                href: 'https://docs.ververica.com/docs/byoc/fluss',
+            },
+        ],
+    },
+    {
+        id: 'doris',
+        organizationId: 'doris',
+        name: 'Apache Doris',
+        category: 'Ecosystem integration',
+        region: 'Global',
+        about: 'Apache Doris is an open-source analytical database for real-time reporting, interactive SQL analytics, and data warehousing.',
+        website: 'https://doris.apache.org/docs/dev/getting-started/what-is-apache-doris/',
+        title: 'Querying Fluss tables directly with SQL',
+        summary:
+            'The Fluss Catalog in Doris 5.0 connects SQL analytics to Fluss log and primary-key tables, including union reads over Fluss and Paimon.',
+        tags: ['SQL analytics', 'Lake and log union reads'],
+        href: '/user-stories/doris/',
+        submission: `${userDiscussion}#discussioncomment-18269669`,
+        sections: [
+            {
+                heading: 'SQL access to streaming tables',
+                text: 'The Fluss Catalog in Doris 5.0 exposes Fluss log and primary-key tables to SQL clients and BI tools without an intermediate ETL job. For primary-key tables, Doris combines snapshots with subsequent changes to return the latest state of each key.',
+            },
+            {
+                heading: 'Combining lake history with fresh updates',
+                text: 'For tables tiered into Paimon, a union read combines historical lake data with the newer records still in Fluss. Doris scans lake files through its native readers and reads the remaining log tail through the Fluss client, preserving a unified view of the table.',
+            },
+            {
+                heading: 'Bringing Fluss into federated analytics',
+                text: 'Queries can join Fluss tables with Doris internal tables or other catalogs, including Hive, Iceberg, Paimon, and JDBC sources. Column and partition pruning reduce unnecessary reads, while query profiles expose which read paths were used.',
+            },
+        ],
+        references: [
+            {
+                title: 'Fluss Catalog — Apache Doris Documentation',
+                href: 'https://doris.apache.org/docs/dev/lakehouse/catalogs/fluss-catalog',
+            },
+        ],
+    },
+];
+
+// Homepage logos link to the same destinations as the organization cards.
+export const endUsers = userStories.filter((story) => story.category === 'End user');
+
+// Visible artwork bounds, in source-image pixels. Source files are unmodified.
+export const logoArtwork: Record<string, {file?: string; width: number; height: number; viewBox: string}> = {
+    'alibaba-cloud': {
+        width: 960,
+        height: 121,
+        viewBox: '0 0 960 121',
+    },
+    alibaba: {
+        width: 1000,
+        height: 378,
+        viewBox: '0 0 1000 378',
+    },
+    iqiyi: {
+        file: 'iqiyi.svg',
+        width: 1577,
+        height: 492,
+        viewBox: '0 0 1577 492',
+    },
+    ververica: {
+        width: 2000,
+        height: 357,
+        viewBox: '0 0 2000 357',
+    },
+    fresha: {
+        width: 1400,
+        height: 438,
+        viewBox: '26 20 1348 398',
+    },
+    rednote: {
+        width: 468,
+        height: 72,
+        viewBox: '0 0 468 72',
+    },
+    'ant-group': {
+        file: 'ant-group-english.png',
+        width: 483,
+        height: 207,
+        viewBox: '0 0 483 207',
+    },
+    jd: {
+        file: 'jd-english.jpg',
+        width: 8000,
+        height: 4500,
+        viewBox: '1712 1936 4585 633',
+    },
+    cisco: {
+        width: 738,
+        height: 210,
+        viewBox: '87 22 587 166',
+    },
+    doris: {
+        width: 2400,
+        height: 480,
+        viewBox: '158 88 2084 305',
+    },
+};
+
+// White artwork is separate from the original submission images.
+// Bounds normalize transparent padding without modifying or recoloring the assets.
+export const whiteLogoArtwork: Record<string, {
+    file: string;
+    width: number;
+    height: number;
+    viewBox: string;
+}> = {
+    alibaba: {file: 'alibaba.png', width: 435, height: 56, viewBox: '0 0 435 56'},
+    iqiyi: {file: 'iqiyi.svg', width: 1577, height: 492, viewBox: '0 0 1577 492'},
+    fresha: {file: 'fresha.svg', width: 819.5, height: 240.5, viewBox: '0 0 819.5 240.5'},
+    rednote: {file: 'rednote.png', width: 468, height: 72, viewBox: '0 0 468 72'},
+    'ant-group': {file: 'ant-group.png', width: 256, height: 80, viewBox: '0 2 179 76'},
+    jd: {file: 'jd.png', width: 200, height: 39, viewBox: '1 3 199 27'},
+    cisco: {file: 'cisco.svg', width: 24, height: 24, viewBox: '0 4.3 24 15.4'},
+};
diff --git a/website/src/pages/index.module.css b/website/src/pages/index.module.css
index 18151655c..b36997d9c 100644
--- a/website/src/pages/index.module.css
+++ b/website/src/pages/index.module.css
@@ -44,15 +44,11 @@
     overflow: hidden;
     margin-top: -60px;
     padding: calc(var(--fluss-space-32) + 60px) 0 var(--fluss-space-24);
-    /* Hero gradient pinned to the dark-mode rendering for BOTH themes.
-     * The bottom stop is the dark-mode --fluss-blue-800 override value
-     * (#D6E4ED, light blue) so the gradient fades from deep blue to light
-     * blue identically in light and dark — composited with the cyan +
-     * brand-blue radial overlays above for the layered hero look. */
+    /* Keep the hero dark in both themes so the white user logos remain legible. */
     background:
         radial-gradient(1200px 600px at 80% 0%, rgba(38, 109, 149, 0.18), transparent 60%),
         radial-gradient(900px 500px at 10% 100%, rgba(38, 109, 149, 0.25), transparent 60%),
-        linear-gradient(180deg, #0A1745 0%, #102856 60%, #D6E4ED 100%);
+        linear-gradient(180deg, #0A1745 0%, #102856 100%);
     color: #FFFFFF;
 }
 
diff --git a/website/src/pages/index.tsx b/website/src/pages/index.tsx
index 60149a0aa..58870458c 100644
--- a/website/src/pages/index.tsx
+++ b/website/src/pages/index.tsx
@@ -20,6 +20,7 @@ import Link from '@docusaurus/Link';
 import Layout from '@theme/Layout';
 import {useColorMode} from '@docusaurus/theme-common';
 import HomepageFeatures from '@site/src/components/HomepageFeatures';
+import UserLogoBand from '@site/src/components/UserLogoBand';
 import {useEffect, useRef, useState} from 'react';
 import {Highlight} from 'prism-react-renderer';
 import flussPrismDark from '@site/src/utils/prismDark';
@@ -538,6 +539,7 @@ function HomepageHeader({heroRef}: {heroRef: React.RefObject<HTMLElement>}) {
                         <HeroCodePanel />
                     </div>
                 </div>
+                <UserLogoBand />
             </div>
         </header>
     );
diff --git a/website/src/pages/user-stories/alibaba-cloud.tsx b/website/src/pages/user-stories/alibaba-cloud.tsx
new file mode 100644
index 000000000..6961e644d
--- /dev/null
+++ b/website/src/pages/user-stories/alibaba-cloud.tsx
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import UserStory from '@site/src/components/UserStory';
+
+export default function Story(): JSX.Element {
+    return <UserStory id="alibaba-cloud" />;
+}
diff --git a/website/src/pages/user-stories/alibaba.tsx b/website/src/pages/user-stories/alibaba.tsx
new file mode 100644
index 000000000..2b1da7580
--- /dev/null
+++ b/website/src/pages/user-stories/alibaba.tsx
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import UserStory from '@site/src/components/UserStory';
+
+export default function Story(): JSX.Element {
+    return <UserStory id="alibaba" />;
+}
diff --git a/website/src/pages/user-stories/ant-group.tsx b/website/src/pages/user-stories/ant-group.tsx
new file mode 100644
index 000000000..e615c0735
--- /dev/null
+++ b/website/src/pages/user-stories/ant-group.tsx
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import UserStory from '@site/src/components/UserStory';
+
+export default function Story(): JSX.Element {
+    return <UserStory id="ant-group" />;
+}
diff --git a/website/src/pages/user-stories/cisco.tsx b/website/src/pages/user-stories/cisco.tsx
new file mode 100644
index 000000000..ccb817ff2
--- /dev/null
+++ b/website/src/pages/user-stories/cisco.tsx
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import UserStory from '@site/src/components/UserStory';
+
+export default function Story(): JSX.Element {
+    return <UserStory id="cisco" />;
+}
diff --git a/website/src/pages/user-stories/doris.tsx b/website/src/pages/user-stories/doris.tsx
new file mode 100644
index 000000000..c144d92a3
--- /dev/null
+++ b/website/src/pages/user-stories/doris.tsx
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import UserStory from '@site/src/components/UserStory';
+
+export default function Story(): JSX.Element {
+    return <UserStory id="doris" />;
+}
diff --git a/website/src/pages/user-stories/fresha.tsx b/website/src/pages/user-stories/fresha.tsx
new file mode 100644
index 000000000..80101010f
--- /dev/null
+++ b/website/src/pages/user-stories/fresha.tsx
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import UserStory from '@site/src/components/UserStory';
+
+export default function Story(): JSX.Element {
+    return <UserStory id="fresha" />;
+}
diff --git a/website/src/pages/user-stories/index.tsx b/website/src/pages/user-stories/index.tsx
new file mode 100644
index 000000000..edd681d55
--- /dev/null
+++ b/website/src/pages/user-stories/index.tsx
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import Layout from '@theme/Layout';
+import Link from '@docusaurus/Link';
+import BrandLogo from '@site/src/components/UserStory/BrandLogo';
+import {userDiscussion, userStories, type StoryCategory} from '@site/src/data/userStories';
+import styles from '@site/src/components/UserStory/styles.module.css';
+
+const groups: {category: StoryCategory; title: string; description: string}[] = [
+    {
+        category: 'End user',
+        title: 'Built with Fluss',
+        description: 'Real-world applications, shared by the teams building them.',
+    },
+    {
+        category: 'Service provider',
+        title: 'Services built on Fluss',
+        description: 'Platforms that help organizations deploy and operate Apache Fluss.',
+    },
+    {
+        category: 'Ecosystem integration',
+        title: 'Connected to Fluss',
+        description: 'Projects bringing Fluss data into the wider data ecosystem.',
+    },
+];
+
+export default function UserStories(): JSX.Element {
+    return (
+        <Layout
+            title="User Stories"
+            description="Explore how organizations use Apache Fluss for real-time analytics, AI applications, and streaming Lakehouses."
+        >
+            <main className={styles.page}>
+                <header className={styles.hero}>
+                    <div className={styles.container}>
+                        <span className={styles.eyebrow}>The Fluss community</span>
+                        <h1>User Stories</h1>
+                        <p>
+                            From real-time analytics to AI-powered applications.
+                            <br />
+                            Discover what teams are building with Apache Fluss.
+                        </p>
+                    </div>
+                </header>
+                <div className={styles.container}>
+                    {groups.map((group) => (
+                        <section
+                            key={group.category}
+                            className={styles.storyGroup}
+                            aria-label={group.title}
+                        >
+                            <div className={styles.groupHeading}>
+                                <h2>{group.title}</h2>
+                                <p>{group.description}</p>
+                            </div>
+                            <div className={styles.grid}>
+                                {userStories
+                                    .filter((story) => story.category === group.category)
+                                    .map((story) => (
+                                        <article key={story.id} className={styles.card}>
+                                            <Link
+                                                to={story.href}
+                                                className={styles.cardLink}
+                                                aria-label={`${story.name}: ${story.title}`}
+                                            >
+                                                <div className={styles.logoPanel}>
+                                                    <BrandLogo
+                                                        story={story}
+                                                        className={styles.cardLogo}
+                                                    />
+                                                </div>
+                                                <div className={styles.cardBody}>
+                                                    <div className={styles.organization}>
+                                                        <span>{story.name}</span>
+                                                    </div>
+                                                    <h3>{story.title}</h3>
+                                                    <p>{story.summary}</p>
+                                                    <div className={styles.tags}>
+                                                        {story.tags.map((tag) => (
+                                                            <span key={tag}>{tag}</span>
+                                                        ))}
+                                                    </div>
+                                                    <span className={styles.readLink}>
+                                                        Read story <span aria-hidden="true">→</span>
+                                                    </span>
+                                                </div>
+                                            </Link>
+                                        </article>
+                                    ))}
+                            </div>
+                        </section>
+                    ))}
+                    <aside className={styles.contribute}>
+                        <div>
+                            <h2>What are you building?</h2>
+                            <p>
+                                Share your experience with Fluss and help the next team get started.
+                            </p>
+                        </div>
+                        <Link to={userDiscussion}>
+                            Share your story <span aria-hidden="true">↗</span>
+                        </Link>
+                    </aside>
+                </div>
+            </main>
+        </Layout>
+    );
+}
diff --git a/website/src/pages/user-stories/iqiyi.tsx b/website/src/pages/user-stories/iqiyi.tsx
new file mode 100644
index 000000000..2d5dcbaf4
--- /dev/null
+++ b/website/src/pages/user-stories/iqiyi.tsx
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import UserStory from '@site/src/components/UserStory';
+
+export default function Story(): JSX.Element {
+    return <UserStory id="iqiyi" />;
+}
diff --git a/website/src/pages/user-stories/jd.tsx b/website/src/pages/user-stories/jd.tsx
new file mode 100644
index 000000000..00d8da2da
--- /dev/null
+++ b/website/src/pages/user-stories/jd.tsx
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import UserStory from '@site/src/components/UserStory';
+
+export default function Story(): JSX.Element {
+    return <UserStory id="jd" />;
+}
diff --git a/website/src/pages/user-stories/rednote.tsx b/website/src/pages/user-stories/rednote.tsx
new file mode 100644
index 000000000..33f8286ec
--- /dev/null
+++ b/website/src/pages/user-stories/rednote.tsx
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import UserStory from '@site/src/components/UserStory';
+
+export default function Story(): JSX.Element {
+    return <UserStory id="rednote" />;
+}
diff --git a/website/src/pages/user-stories/ververica.tsx b/website/src/pages/user-stories/ververica.tsx
new file mode 100644
index 000000000..a7c2455cc
--- /dev/null
+++ b/website/src/pages/user-stories/ververica.tsx
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import UserStory from '@site/src/components/UserStory';
+
+export default function Story(): JSX.Element {
+    return <UserStory id="ververica" />;
+}
diff --git a/website/static/img/users/README.md b/website/static/img/users/README.md
new file mode 100644
index 000000000..8a27772b2
--- /dev/null
+++ b/website/static/img/users/README.md
@@ -0,0 +1,54 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+# User logos
+
+Original images supplied by organizations in [Who is using Apache Fluss?](https://github.com/apache/fluss/discussions/4033). Brand marks remain the property of their respective owners.
+
+The original submission images are used on the User Stories cards, with replacement assets and their sources noted below. Cisco supplied the Webex by Cisco lockup.
+
+The homepage and story headers use separate white-on-transparent assets, downloaded or converted from user-supplied originals as noted below. No color filters, masks, or blend modes recolor the logos at runtime. The SVG viewport only normalizes blank or transparent padding, preserving the artwork and its aspect ratio. Logo files are stored locally so page loads do not depend on external asset hosts.
+
+| Asset | Original image | Submission |
+| --- | --- | --- |
+| `alibaba-cloud.png` | [Image](https://github.com/user-attachments/assets/fd597d0a-3372-47ae-b743-030fa7141173) | [Submission](https://github.com/apache/fluss/discussions/4033#discussioncomment-18064873) |
+| `alibaba.png` | [Image](https://github.com/user-attachments/assets/9984abd5-7a0e-4fc8-b7c6-853ac09ea70c) | [Submission](https://github.com/apache/fluss/discussions/4033#discussioncomment-18067474) |
+| `iqiyi.svg` | User-supplied `IQ.svg`, 2026-09-22; original green SVG preserved unchanged. | [Submission](https://github.com/apache/fluss/discussions/4033#discussioncomment-18074056) |
+| `ververica.png` | [Image](https://github.com/user-attachments/assets/77cab608-5766-4ffd-9276-f2a41774d3c6) | [Submission](https://github.com/apache/fluss/discussions/4033#discussioncomment-18077747) |
+| `fresha.png` | [Image](https://github.com/user-attachments/assets/2f8d0aae-85bb-4100-b682-8b3ee155019b) | [Submission](https://github.com/apache/fluss/discussions/4033#discussioncomment-18081546) |
+| `rednote.png` | User-supplied 468 × 72 rednote lockup, 2026-09-22. | [Submission](https://github.com/apache/fluss/discussions/4033#discussioncomment-18089790) |
+| `ant-group-english.png` | Original English color wordmark from the maintained PowerPoint brand-logo catalog, asset `color-wordmark-ed91f0fc52`; copied unchanged, 2026-09-22. | [Submission](https://github.com/apache/fluss/discussions/4033#discussioncomment-18123921) |
+| `jd-english.jpg` | Source: [JD corporate website](https://corporate.jd.com/). [Original English JINGDONG header JPG](https://storage.360buyimg.com/jdw-asserts/galaxy/jdei/fin-inv-joygen-app-1778478020444/f445411d-aa20-4616-bcd4-7ee010bdb506/dist/assets/main-logo-new-ad105c5c.jpg), 8000 × 4500; downloaded unchanged, 2026-09-22. The viewport excludes surrounding white space. | [Submission](https://github.com/apache/fluss/discussions/4033#discussioncomment-18149379) |
+| `cisco.png` | [Image](https://github.com/user-attachments/assets/c74d321d-53fb-4f7b-b5cc-0e80966ad56e) | [Submission](https://github.com/apache/fluss/discussions/4033#discussioncomment-18173301) |
+| `doris.png` | [Image](https://github.com/user-attachments/assets/f5ba6dd1-cb83-4675-8e1c-b98aa630753f) | [Submission](https://github.com/apache/fluss/discussions/4033#discussioncomment-18269669) |
+
+## White assets
+
+Retrieved 2026-09-22. Downloaded files retain the bytes from their source (or the image within its archive / embedded data URL). The iQIYI SVG changes only the fill color of the user-supplied artwork to white. The rednote PNG is a white, transparent conversion of the user-supplied lockup, preserving its original pixel dimensions and contours. The homepage uses the Cisco company mark for the Cisco Webex story; its submitted Webex lockup remains on the User Stories cards.
+
+| Asset | Source | Download / original asset |
+| --- | --- | --- |
+| `white/alibaba.png` | [Alibaba Group website](https://home.alibabagroup.com/en-US/resource-logos) | White header PNG embedded in [official CSS](https://assets.alibabagroup.com/assets/0.1.126/css/index.css), `.nav-header-left-img`. Source: www.alibabagroup.com. |
+| `white/iqiyi.svg` | User-supplied `IQ.svg`, 2026-09-22 | Fill changed from `#00dc5a` to `#ffffff`; original path, dimensions, and transparent background preserved. |
+| `white/fresha.svg` | [Fresha brand download centre](https://fresha.hypedev.23x.me/download-centre/) | `RGB/SVG/Fresha_Wordmark_White_RGB.svg` from the [RGB archive](https://fresha.hypedev.23x.me/wp-content/uploads/2022/07/RGB.zip). |
+| `white/rednote.png` | User-supplied rednote logo, 2026-09-22 | Original 468 × 72 PNG converted to white ink: Chinese lettering is knocked out of the capsule, and the English wordmark retains its original alpha channel. |
+| `white/ant-group.png` | [Ant Group website](https://www.antgroup.com/en) | [White header PNG](https://gw.alipayobjects.com/mdn/rms_27e257/afts/img/A*70AsSL23VKYAAAAAAAAAAAAAARQnAQ). |
+| `white/jd.png` | [JD corporate blog](https://jdcorporateblog.com/media-resources/) | [White footer PNG](https://jdcorporateblog.com/wp-content/uploads/2024/01/42741705567864_%E7%99%BD.png). |
+| `white/cisco.svg` | [Simple Icons](https://simpleicons.org/) | [White Cisco SVG](https://cdn.simpleicons.org/cisco/FFFFFF). |
+
+Simple Icons assets use CC0; company names and trademarks remain the property of their respective owners. The asset sources above do not imply endorsement by the organizations.
diff --git a/website/static/img/users/alibaba-cloud.png b/website/static/img/users/alibaba-cloud.png
new file mode 100644
index 000000000..32e3ada7a
Binary files /dev/null and b/website/static/img/users/alibaba-cloud.png differ
diff --git a/website/static/img/users/alibaba.png b/website/static/img/users/alibaba.png
new file mode 100644
index 000000000..c7d906eba
Binary files /dev/null and b/website/static/img/users/alibaba.png differ
diff --git a/website/static/img/users/ant-group-english.png b/website/static/img/users/ant-group-english.png
new file mode 100644
index 000000000..515e8af38
Binary files /dev/null and b/website/static/img/users/ant-group-english.png differ
diff --git a/website/static/img/users/cisco.png b/website/static/img/users/cisco.png
new file mode 100644
index 000000000..e6ca7f533
Binary files /dev/null and b/website/static/img/users/cisco.png differ
diff --git a/website/static/img/users/doris.png b/website/static/img/users/doris.png
new file mode 100644
index 000000000..56325f7b5
Binary files /dev/null and b/website/static/img/users/doris.png differ
diff --git a/website/static/img/users/fresha.png b/website/static/img/users/fresha.png
new file mode 100644
index 000000000..cee846716
Binary files /dev/null and b/website/static/img/users/fresha.png differ
diff --git a/website/static/img/users/iqiyi.svg b/website/static/img/users/iqiyi.svg
new file mode 100644
index 000000000..e7aaa34f6
--- /dev/null
+++ b/website/static/img/users/iqiyi.svg
@@ -0,0 +1 @@
+<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1577 492" width="1577" height="492"><style>.a{fill:#00dc5a}</style><path fill-rule="evenodd" class="a" d="m783.8 13.7c0-2.2 2-4 4.4-4h105.2c2.4 0 4.4 1.8 4.4 4v473.7c0 2.3-2 4.1-4.4 4.1h-105.2c-2.4 0-4.4-1.8-4.4-4.1zm-773 175.5c0-2.3 2-4.1 4.4-4.1h105.1c2.5 0 4.5 1.8 4.5 4.1v298.2c0 2.2-2 4.1-4.5 4.1h-105.1c-2.4 0-4.4-1.9-4.4-4.1zm704.2 227.2l-58.8 73.7c-1.6 1.9-4.4 2.3-6.3 0.7l-55.8-45c-2-1.6-4.8-1.7-7-0.2-28.6 20.7-62.2 [...]
\ No newline at end of file
diff --git a/website/static/img/users/jd-english.jpg b/website/static/img/users/jd-english.jpg
new file mode 100644
index 000000000..2a7288f86
Binary files /dev/null and b/website/static/img/users/jd-english.jpg differ
diff --git a/website/static/img/users/rednote.png b/website/static/img/users/rednote.png
new file mode 100644
index 000000000..78a10c96a
Binary files /dev/null and b/website/static/img/users/rednote.png differ
diff --git a/website/static/img/users/ververica.png b/website/static/img/users/ververica.png
new file mode 100644
index 000000000..925cdb299
Binary files /dev/null and b/website/static/img/users/ververica.png differ
diff --git a/website/static/img/users/white/alibaba.png b/website/static/img/users/white/alibaba.png
new file mode 100644
index 000000000..6b5dfbfe7
Binary files /dev/null and b/website/static/img/users/white/alibaba.png differ
diff --git a/website/static/img/users/white/ant-group.png b/website/static/img/users/white/ant-group.png
new file mode 100644
index 000000000..a7274910f
Binary files /dev/null and b/website/static/img/users/white/ant-group.png differ
diff --git a/website/static/img/users/white/cisco.svg b/website/static/img/users/white/cisco.svg
new file mode 100644
index 000000000..d546ac006
--- /dev/null
+++ b/website/static/img/users/white/cisco.svg
@@ -0,0 +1 @@
+<svg fill="#FFFFFF" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Cisco</title><path d="M16.331 18.171V17.06l-.022.01c-.25.121-.522.19-.801.203a1.186 1.186 0 01-.806-.237 1.038 1.038 0 01-.352-.498 1.21 1.21 0 01-.023-.667c.052-.225.178-.426.357-.569.16-.134.355-.218.562-.242a1.85 1.85 0 011.061.198l.024.013v-1.117l-.051-.014a2.862 2.862 0 00-1.011-.132 2.34 2.34 0 00-.903.206c-.287.132-.54.327-.739.571a2.221 2.221 0 00-.04 2.705c.295.378.709.645 1.175.756.491. [...]
\ No newline at end of file
diff --git a/website/static/img/users/white/fresha.svg b/website/static/img/users/white/fresha.svg
new file mode 100644
index 000000000..5090e6e27
--- /dev/null
+++ b/website/static/img/users/white/fresha.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 819.5 240.5"><defs><style>.c{fill:#fff;}</style></defs><g id="a"/><g id="b"><g><path class="c" d="M516.06,21.4l39.36-.13V102.5c13.06-18.8,40.37-24.76,62.46-15.63,22.35,8.84,29.4,24.63,30.42,26.77,2.31,4.85,3.73,10.03,4.58,15.31,5.73,35.75-6.03,72.39,4.53,107.61h-38.21c-9.97-24.8-4.23-52.88-4.17-79.61,.01-7.5-.5-15.24-3.78-21.98-4.62-9.5-14.84-16.01-25.41-16.17-10.57-.16-20.99,6.02-25.9,15.38-4.27,8 [...]
\ No newline at end of file
diff --git a/website/static/img/users/white/iqiyi.svg b/website/static/img/users/white/iqiyi.svg
new file mode 100644
index 000000000..53c4055f7
--- /dev/null
+++ b/website/static/img/users/white/iqiyi.svg
@@ -0,0 +1 @@
+<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1577 492" width="1577" height="492"><style>.a{fill:#ffffff}</style><path fill-rule="evenodd" class="a" d="m783.8 13.7c0-2.2 2-4 4.4-4h105.2c2.4 0 4.4 1.8 4.4 4v473.7c0 2.3-2 4.1-4.4 4.1h-105.2c-2.4 0-4.4-1.8-4.4-4.1zm-773 175.5c0-2.3 2-4.1 4.4-4.1h105.1c2.5 0 4.5 1.8 4.5 4.1v298.2c0 2.2-2 4.1-4.5 4.1h-105.1c-2.4 0-4.4-1.9-4.4-4.1zm704.2 227.2l-58.8 73.7c-1.6 1.9-4.4 2.3-6.3 0.7l-55.8-45c-2-1.6-4.8-1.7-7-0.2-28.6 20.7-62.2 [...]
\ No newline at end of file
diff --git a/website/static/img/users/white/jd.png b/website/static/img/users/white/jd.png
new file mode 100644
index 000000000..045c83ac1
Binary files /dev/null and b/website/static/img/users/white/jd.png differ
diff --git a/website/static/img/users/white/rednote.png b/website/static/img/users/white/rednote.png
new file mode 100644
index 000000000..7fd5c060d
Binary files /dev/null and b/website/static/img/users/white/rednote.png differ