This is an automated email from the ASF dual-hosted git repository.
RongtongJin pushed a commit to branch new-official-website
in repository https://gitbox.apache.org/repos/asf/rocketmq-site.git
The following commit(s) were added to refs/heads/new-official-website by this
push:
new 166fd8df13 update index page (#774)
166fd8df13 is described below
commit 166fd8df13729ac604077d0a65a35b0206bb7e58
Author: WentingYang <[email protected]>
AuthorDate: Fri May 15 09:56:12 2026 +0800
update index page (#774)
* add LiteTopic Documents
* add documents
* add documents
* update index page
---------
Co-authored-by: wenting <[email protected]>
---
docs/09-streams/01RocketMQStreamsOverview.md | 38 ++
docs/09-streams/02RocketMQStreamsConcept.md | 65 ++++
docs/09-streams/03RocketMQStreamsQuickStart.md | 162 ++++++++
src/pages/components/AISolutions.js | 283 ++++++++++++++
src/pages/components/AISolutions.module.css | 419 +++++++++++++++++++++
src/pages/components/Hero.js | 61 ++-
src/pages/components/Hero.module.css | 157 +++++---
src/pages/index.js | 23 +-
static/picture/v5/litetopic_batch_practice.svg | 4 +
.../picture/v5/litetopic_multiagent_practice.svg | 1 +
static/picture/v5/litetopic_ratelimit_practice.svg | 4 +
static/picture/v5/litetopic_session_practice.svg | 1 +
12 files changed, 1115 insertions(+), 103 deletions(-)
diff --git a/docs/09-streams/01RocketMQStreamsOverview.md
b/docs/09-streams/01RocketMQStreamsOverview.md
new file mode 100644
index 0000000000..617516c82a
--- /dev/null
+++ b/docs/09-streams/01RocketMQStreamsOverview.md
@@ -0,0 +1,38 @@
+# RocketMQ Streams 概览
+RocketMQ Streams是基于RocketMQ的轻量级流计算引擎。能以SDK方式被应用依赖,无须部署复杂的流计算服务端即可获得流计算能力。
+因此具有资源消耗少、扩展性好、支持流计算算子丰富的特点。
+
+## 整体架构
+
+
+数据从RocketMQ中被RocketMQ-streams消费,经过处理最终被写回到RocketMQ。
+
+
+
+数据被RocketMQ
Consumer消费,进入处理拓扑被算子处理,如果流处理任务中含有算子keyBy,则需要将数据按照Key进行分组,将分组数据写入shuffle
topic。后续算子从
+shuffle topic消费。如果还涉及count之类有状态算子,那么计算时需要读写state topic,计算结束后,将结果写回到RocketMQ中。
+
+
+## 消费模型
+
+
+
+计算实例实质上是依赖了Rocket-streams SDK的client,因此,计算实例消费的MQ依赖RocketMQ rebalance分配,
+计算实例总个数也不能大于消费总MQ个数,否则将有部分计算实例处于等待状态,消费不到数据。
+
+一个计算实例可以消费多个MQ,一个实例内也只有一张计算拓扑图。
+
+## 状态
+
+
+对于有状态算子,比如count,需要先对count算子进行分组,然后才能求和。分组算子keyBy会将数据按照分组的key重新写回RocketMQ,并且使相同key写入同一分区(这一过程称作shuffle),
+保证这个含有相同key的数据被同一个消费者消费。 状态本地依赖RocksDB加速读取,远程依赖RocketMQ做持久化。
+
+
+## 扩缩容
+
+
+
+当计算实例从3个缩容到2个,借助于RocketMQ集群消费模式下的rebalance功能,被消费的分片MQ会在计算实例之间重新分配。Instance1上消费的MQ2和MQ3被分配到Instance2和Instance3上,
+这两个MQ的状态数据也需要迁移到Instance2和Instance3上,这也暗示,状态数据是根据源数据分片MQ保存的;扩容则是刚好相反的过程。
+
diff --git a/docs/09-streams/02RocketMQStreamsConcept.md
b/docs/09-streams/02RocketMQStreamsConcept.md
new file mode 100644
index 0000000000..26e8afdd7d
--- /dev/null
+++ b/docs/09-streams/02RocketMQStreamsConcept.md
@@ -0,0 +1,65 @@
+# RocketMQ Streams 核心概念
+
+## 领域模型
+
+### StreamBuilder
+
+
+* 一个StreamBuilder实例,有1到N个pipeline,pipeline表示一个数据处理路径;
+* 一个pipeline可以含有1到N个处理节点GroupNode;
+* 一个StreamBuilder实例,有一个TopologyBuilder,TopologyBuilder可构建出数据处理器processor;
+* 一个JobId对应一个StreamBuilder实例。
+
+### RocketMQStream
+
+
+* 一个RocketMQStream实例,有一个拓扑构建器TopologyBuilder;
+* 一个RocketMQStream实例,可实例化1到N个worker线程;
+* 每个线程WorkerThread实例,包含一个engine;
+* 一个engine包含执行数据处理的所有逻辑,包含一个consumer实例、一个producer实例、一个StateStore实例;
+
+### 流处理实例
+流处理实例表示一个运行RocketMQ Streams的进程;
+
+* 一个流处理实例包含一个StreamBuilder,一个RocketMQStream,一个拓扑图,一到多个pipeline;
+
+
+## StreamBuilder
++ ```StreamBuilder(jobId)``` 构建实例;
++ ```<OUT> RStream<OUT> source(topicName, deserializer) ``` 定义source topic
和反序列化方式;
+
+
+## RStream
++ ```<K> GroupedStream<K, T> keyBy(selectAction)``` 按照特定字段分组;
++ ```<O> RStream<O> map(mapperAction)``` 对数据进行一对一转化;
++ ```RStream<T> filter(predictor)``` 对数据进行过滤
++ ```<VR> RStream<T> flatMap(mapper)```对数据进行一对多转化;
++ ```<T2> JoinedStream<T, T2> join(rightStream)``` 双流Join;
++ ```sink(topicName, serializer)``` 将结果输出到特定topic;
+
+
+## GroupedStream
+对含有相同Key的数据进行操作
++ ```<OUT> GroupedStream<K, Integer> count(selectAction)``` 统计含有某个字段数据的个数;
++ ```GroupedStream<K, V> min(selectAction)``` 对某个字段统计最小值;
++ ```GroupedStream<K, V> max(selectAction)``` 对某个字段统计最大值;
++ ```GroupedStream<K, ? extends Number> sum(selectAction)``` 对某个字段统计和;
++ ```GroupedStream<K, V> filter(predictor)``` 对某个字段进行过滤;
++ ```<OUT> GroupedStream<K, OUT> map(valueMapperAction)``` 对数据进行一对一转化;
++ ```<OUT> GroupedStream<K, OUT> aggregate(accumulator)```
对数据进行聚合操作,且聚合支持二阶聚合,例如在窗口未触发时添加数据,在窗口触发时计算结果这类算子;
++ ```WindowStream<K, V> window(windowInfo)``` 对窗口划定window;
++ ```GroupedStream<K, V> addGraphNode(name, supplier)``` 底层接口,向流处理拓扑中增加自定义算子;
++ ```RStream<V> toRStream()``` 转化为RStream,只是在接口形式上转化,对数据无任何操作;
++ ```sink(topicName, serializer)``` 按照自定义序列化形式将结果写出到topic;
+
+
+## WindowStream
+对被划分window的数据进行操作
++ ```WindowStream<K, Integer> count()``` 统计窗口内数据个数;
++ ```WindowStream<K, V> filter(predictor)``` 过滤窗口内数据;
++ ```<OUT> WindowStream<K, OUT> map(mapperAction)``` 对窗口内数据一对一转化;
++ ```<OUT> WindowStream<K, OUT> aggregate(aggregateAction)``` 对窗口内数据多对一转化;
++ ```<OUT> WindowStream<K, OUT> aggregate(accumulator)```
对数据进行聚合操作,且聚合支持二阶聚合,例如在窗口未触发时添加数据,在窗口触发时计算结果这类算子;
++ ```void sink(topicName, serializer)``` 按照自定义序列化形式将结果写出到topic;
+
+
diff --git a/docs/09-streams/03RocketMQStreamsQuickStart.md
b/docs/09-streams/03RocketMQStreamsQuickStart.md
new file mode 100644
index 0000000000..d258e35966
--- /dev/null
+++ b/docs/09-streams/03RocketMQStreamsQuickStart.md
@@ -0,0 +1,162 @@
+# RocketMQ Streams 快速开始
+
+## RocketMQ Streams工程中运行
+参考RocketMQ Streams工程rocketmq-streams-examples模块下程序可以直接运行;运行example步骤:
+* 本地启动RocketMQ 5.0及以上版本;
+* 使用mqAdmin创建example中数据源topic;
+* 启动example中例子;
+* 向RocketMQ的源topic中写入合适数据(依据示例而定);
+
+## RocketMQ Streams以SDK方式被应用依赖
+### 环境准备
+- 64bit JDK 1.8及以上
+- Maven 3.2及以上
+- 本地启动RocketMQ,[启动文档](https://rocketmq.apache.org/docs/quick-start/)
+
+### 构建RocketMQ Streams
+
+
+### 添加pom依赖
+
+```xml
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.rocketmq</groupId>
+ <artifactId>rocketmq-streams</artifactId>
+ <!-- 根据需要修改 -->
+ <version>1.1.0</version>
+ </dependency>
+</dependencies>
+```
+
+### 编写流计算程序
+```java
+public class WordCount {
+ public static void main(String[] args) {
+ StreamBuilder builder = new StreamBuilder("wordCount");
+
+ builder.source("sourceTopic", total -> {
+ String value = new String(total, StandardCharsets.UTF_8);
+ return new Pair<>(null, value);
+ })
+ .flatMap((ValueMapperAction<String, List<String>>) value -> {
+ String[] splits = value.toLowerCase().split("\\W+");
+ return Arrays.asList(splits);
+ })
+ .keyBy(value -> value)
+ .count()
+ .toRStream()
+ .print();
+
+ TopologyBuilder topologyBuilder = builder.build();
+
+ Properties properties = new Properties();
+ properties.put(MixAll.NAMESRV_ADDR_PROPERTY, "127.0.0.1:9876");
+
+ RocketMQStream rocketMQStream = new RocketMQStream(topologyBuilder,
properties);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+
+ Runtime.getRuntime().addShutdownHook(new
Thread("wordcount-shutdown-hook") {
+ @Override
+ public void run() {
+ rocketMQStream.stop();
+ latch.countDown();
+ }
+ });
+
+ try {
+ rocketMQStream.start();
+ latch.await();
+ } catch (final Throwable e) {
+ System.exit(1);
+ }
+ System.exit(0);
+ }
+}
+```
+
+### 向RocketMQ sourceTopic中写入数据并观察结果
+如果向sourceTopic中写入的数据如下:每行数据作为一个消息发送;
+```xml
+"To be, or not to be,--that is the question:--",
+"Whether 'tis nobler in the mind to suffer",
+"The slings and arrows of outrageous fortune",
+"Or to take arms against a sea of troubles,",
+"And by opposing end them?--To die,--to sleep,--",
+"No more; and by a sleep to say we end",
+"The heartache, and the thousand natural shocks",
+"That flesh is heir to,--'tis a consummation",
+```
+统计单词出现频率,计算结果如下:
+```xml
+(key=to, value=1)
+(key=be, value=1)
+(key=or, value=1)
+(key=not, value=1)
+(key=to, value=2)
+(key=be, value=2)
+(key=that, value=1)
+(key=is, value=1)
+(key=the, value=1)
+(key=whether, value=1)
+(key=tis, value=1)
+(key=nobler, value=1)
+(key=mind, value=1)
+(key=against, value=1)
+(key=troubles, value=1)
+(key=slings, value=1)
+(key=die, value=1)
+(key=natural, value=1)
+(key=flesh, value=1)
+(key=sea, value=1)
+(key=fortune, value=1)
+(key=shocks, value=1)
+(key=consummation, value=1)
+(key=to, value=3)
+(key=to, value=4)
+(key=to, value=5)
+(key=say, value=1)
+(key=end, value=1)
+(key=end, value=2)
+(key=to, value=6)
+(key=to, value=7)
+(key=to, value=8)
+(key=or, value=2)
+(key=them, value=1)
+(key=take, value=1)
+(key=arms, value=1)
+(key=of, value=1)
+(key=and, value=1)
+(key=of, value=2)
+(key=and, value=2)
+(key=by, value=1)
+(key=sleep, value=1)
+(key=and, value=3)
+(key=by, value=2)
+(key=sleep, value=2)
+(key=and, value=4)
+(key=that, value=2)
+(key=arrows, value=1)
+(key=heir, value=1)
+(key=question, value=1)
+(key=is, value=2)
+(key=the, value=2)
+(key=suffer, value=1)
+(key=a, value=1)
+(key=the, value=3)
+(key=no, value=1)
+(key=a, value=2)
+(key=opposing, value=1)
+(key=the, value=4)
+(key=the, value=5)
+(key=a, value=3)
+(key=in, value=1)
+(key=more, value=1)
+(key=heartache, value=1)
+(key=outrageous, value=1)
+(key=we, value=1)
+(key=thousand, value=1)
+(key=tis, value=2)
+```
+
diff --git a/src/pages/components/AISolutions.js
b/src/pages/components/AISolutions.js
new file mode 100644
index 0000000000..68b9633442
--- /dev/null
+++ b/src/pages/components/AISolutions.js
@@ -0,0 +1,283 @@
+import React, { useState } from 'react';
+import styles from './AISolutions.module.css';
+
+const TABS = [
+ { key: 'session', label: 'MCP & Session Management' },
+ { key: 'ratelimit', label: 'Isolation & Rate Limiting' },
+ { key: 'batch', label: 'Batch Consumption' },
+ { key: 'multiagent', label: 'Multi-Agent Communication' },
+];
+
+function Lightbox({ src, alt, onClose }) {
+ return (
+ <div className={styles.lightboxOverlay} onClick={onClose}>
+ <button className={styles.lightboxClose} onClick={onClose}>✕</button>
+ <img
+ src={src}
+ alt={alt}
+ className={styles.lightboxImg}
+ onClick={(e) => e.stopPropagation()}
+ />
+ </div>
+ );
+}
+
+function SolutionImage({ src, alt }) {
+ const [open, setOpen] = useState(false);
+ return (
+ <>
+ <div className={styles.solutionVisual} onClick={() => setOpen(true)}
style={{ cursor: 'zoom-in' }}>
+ <img src={src} alt={alt} className={styles.solutionImg} />
+ </div>
+ {open && <Lightbox src={src} alt={alt} onClose={() => setOpen(false)} />}
+ </>
+ );
+}
+
+function SessionPanel() {
+ return (
+ <div className={styles.solutionCard}>
+ <div className={styles.solutionContent}>
+ <h3>MCP & Long-Session State Continuity</h3>
+ <div className={styles.solutionPain}>
+ AI tasks are long-running and GPU-expensive. Unstable SSE/WebSocket
connections cause session interruption, context loss, and wasted compute.
+ </div>
+ <ul className={styles.solutionList}>
+ <li>Each session maps to a LiteTopic
(<code>chat/{sessionID}</code>), keeping app servers completely
stateless</li>
+ <li>On reconnection to any node, subscribe to the same LiteTopic and
resume from breakpoint</li>
+ <li>Backend LLM tasks continue running — results persist regardless
of frontend disconnection</li>
+ </ul>
+ <div className={styles.solutionValues}>
+ <span className={styles.valueTag}>Session Continuity</span>
+ <span className={styles.valueTag}>Zero Compute Waste</span>
+ <span className={styles.valueTag}>Stateless Scaling</span>
+ </div>
+ </div>
+ <SolutionImage
+ src="/picture/v5/litetopic_session_practice.svg"
+ alt="MCP & Long-Session State Continuity Architecture"
+ />
+ </div>
+ );
+}
+
+function RateLimitPanel() {
+ return (
+ <div className={styles.solutionCard}>
+ <div className={styles.solutionContent}>
+ <h3>Fine-Grained Isolation & Rate Limiting</h3>
+ <div className={styles.solutionPain}>
+ Limited GPU capacity shared by massive users. A single user's burst
traffic starves others. Traditional Topic/Partition schemes can't support
million-level isolation.
+ </div>
+ <ul className={styles.solutionList}>
+ <li>Route requests to isolated LiteTopics by user ID / model ID /
task type — physical isolation, zero cross-tenant interference</li>
+ <li>Consumer-side Suspend precisely pauses a single LiteTopic with
ms-level rate limiting</li>
+ <li>Cluster-level governance: identify top-traffic queues, suspend
and gradually recover with elastic scaling</li>
+ </ul>
+ <div className={styles.solutionValues}>
+ <span className={styles.valueTag}>Per-User Flow Control</span>
+ <span className={styles.valueTag}>Physical Isolation</span>
+ <span className={styles.valueTag}>Peak Shaving</span>
+ </div>
+ </div>
+ <SolutionImage
+ src="/picture/v5/litetopic_ratelimit_practice.svg"
+ alt="Fine-Grained Isolation & Rate Limiting Architecture"
+ />
+ </div>
+ );
+}
+
+function BatchPanel() {
+ return (
+ <div className={styles.solutionCard}>
+ <div className={styles.solutionContent}>
+ <h3>Batch Consumption — Unleash GPU Parallelism</h3>
+ <div className={styles.solutionPain}>
+ LLM Batch API inference costs only 50% of real-time inference.
Per-message consumption wastes GPU parallel capacity.
+ </div>
+ <ul className={styles.solutionList}>
+ <li>Native batch consumption: dual-trigger by count (maxNumMessages)
+ time (batchTimeout)</li>
+ <li>PushConsumer BatchMessageListener for timely batching;
SimpleConsumer batchReceive for active pacing</li>
+ <li>Directly adapts to OpenAI-style Batch APIs, cutting inference
costs by 50%</li>
+ </ul>
+ <div className={styles.solutionValues}>
+ <span className={styles.valueTag}>GPU Utilization Maximized</span>
+ <span className={styles.valueTag}>50% Cost Reduction</span>
+ <span className={styles.valueTag}>Flexible Batching</span>
+ </div>
+ </div>
+ <SolutionImage
+ src="/picture/v5/litetopic_batch_practice.svg"
+ alt="Batch Consumption Architecture"
+ />
+ </div>
+ );
+}
+
+function MultiAgentPanel() {
+ return (
+ <div className={styles.solutionCard}>
+ <div className={styles.solutionContent}>
+ <h3>Multi-Agent Async Communication</h3>
+ <div className={styles.solutionPain}>
+ Long-running AI tasks in multi-agent systems cause thread blocking,
cascade failures, and poor scalability with synchronous calls.
+ </div>
+ <ul className={styles.solutionList}>
+ <li>Supervisor dispatches subtasks to worker Agents' Request Topics
— fully async and decoupled</li>
+ <li>Workers return results via Response LiteTopics (named by
TaskID); Supervisor subscribes to receive</li>
+ <li>LiteTopics auto-create/destroy; ordered messages guarantee
streaming token consistency</li>
+ <li>Compatible with MCP & A2A; adapters for LangChain, CrewAI,
AutoGen, AgentScope, Dify, Coze</li>
+ </ul>
+ <div className={styles.solutionValues}>
+ <span className={styles.valueTag}>Non-Blocking</span>
+ <span className={styles.valueTag}>Task Isolation</span>
+ <span className={styles.valueTag}>Framework Agnostic</span>
+ </div>
+ </div>
+ <SolutionImage
+ src="/picture/v5/litetopic_multiagent_practice.svg"
+ alt="Multi-Agent Async Communication Architecture"
+ />
+ </div>
+ );
+}
+
+const PANELS = {
+ session: SessionPanel,
+ ratelimit: RateLimitPanel,
+ batch: BatchPanel,
+ multiagent: MultiAgentPanel,
+};
+
+export default function AISolutions() {
+ const [activeTab, setActiveTab] = useState('session');
+ const ActivePanel = PANELS[activeTab];
+
+ return (
+ <>
+ {/* Solutions Section */}
+ <section className={styles.solutions} id="solutions">
+ <div className={styles.sectionHeader}>
+ <div className={styles.sectionLabel}>AI Solutions</div>
+ <p className={styles.sectionDesc}>Classic scenario solutions for
agentic AI systems</p>
+ </div>
+
+ <div className={styles.tabNav}>
+ {TABS.map(tab => (
+ <button
+ key={tab.key}
+ className={`${styles.tabBtn} ${activeTab === tab.key ?
styles.tabBtnActive : ''}`}
+ onClick={() => setActiveTab(tab.key)}
+ >
+ {tab.label}
+ </button>
+ ))}
+ </div>
+
+ <div className={styles.tabPanel}>
+ <ActivePanel />
+ </div>
+ </section>
+
+ {/* Features Section */}
+ <section className={styles.featuresSection} id="features">
+ <div className={styles.sectionHeader}>
+ <div className={styles.sectionLabel}>Core Features</div>
+ <p className={styles.sectionDesc}>The underlying capabilities that
make enterprise AI communication reliable, fast, and effortless.</p>
+ </div>
+
+ <div className={styles.featuresGrid}>
+ <div className={styles.featureCard}>
+ <div className={styles.featureIcon}>⚡</div>
+ <h4>LiteTopic — Million-Scale</h4>
+ <ul>
+ <li>Million-level LiteTopics per cluster, auto-created on
demand</li>
+ <li>TTL-based auto-expiration, zero manual maintenance</li>
+ <li>Per-consumer selective subscription within same group</li>
+ <li>Strict ordering within each LiteTopic</li>
+ </ul>
+ </div>
+
+ <div className={styles.featureCard}>
+ <div className={styles.featureIcon}>📦</div>
+ <h4>Batch Consumption</h4>
+ <ul>
+ <li>Dual-trigger: message count + time window</li>
+ <li>PushConsumer & SimpleConsumer dual-mode</li>
+ <li>Native fit for LLM Batch API paradigms</li>
+ <li>Adaptive pacing for varying throughput</li>
+ </ul>
+ </div>
+
+ <div className={styles.featureCard}>
+ <div className={styles.featureIcon}>🎛️</div>
+ <h4>Fine-Grained Flow Control</h4>
+ <ul>
+ <li>Per-LiteTopic Suspend/Resume at consumer level</li>
+ <li>Millisecond-level rate limiting, isolated impact</li>
+ <li>Smooth traffic curves with elastic scaling</li>
+ <li>Cluster-wide top-N queue governance</li>
+ </ul>
+ </div>
+
+ <div className={styles.featureCard}>
+ <div className={styles.featureIcon}>🛡️</div>
+ <h4>High Reliability & HA</h4>
+ <ul>
+ <li>Durable persistence + offset management</li>
+ <li>Multi-replica sync replication, cross-region DR</li>
+ <li>Auto failover, financial-grade transactions</li>
+ <li>Breakpoint recovery for AI workflows</li>
+ </ul>
+ </div>
+
+ <div className={styles.featureCard}>
+ <div className={styles.featureIcon}>☁️</div>
+ <h4>Cloud-Native Architecture</h4>
+ <ul>
+ <li>Compute-storage separation, stateless Proxy</li>
+ <li>Kubernetes-native, infinite elastic scaling</li>
+ <li>gRPC SDK: Java / Go / Python / C++ / Rust</li>
+ <li>Trillion-level throughput, 10M+ TPS proven</li>
+ </ul>
+ </div>
+
+ <div className={styles.featureCard}>
+ <div className={styles.featureIcon}>🔗</div>
+ <h4>Protocol & Ecosystem</h4>
+ <ul>
+ <li>MCP (Model Context Protocol) native support</li>
+ <li>A2A (Agent-to-Agent) protocol compatible</li>
+ <li>LangChain, CrewAI, AutoGen, AgentScope</li>
+ <li>Framework-agnostic: Dify, Coze, and more</li>
+ </ul>
+ </div>
+ </div>
+
+ {/* Also Included */}
+ <div className={styles.alsoIncluded}>
+ <div className={styles.alsoIncludedTitle}>Also Included — Classic
Integration Capabilities</div>
+ <div className={styles.alsoIncludedGrid}>
+ <div className={styles.alsoIncludedItem}>
+ <h5>EventBridge</h5>
+ <p>CloudEvents-compatible event bus for cross-platform routing
and Serverless integration.</p>
+ </div>
+ <div className={styles.alsoIncludedItem}>
+ <h5>MQTT</h5>
+ <p>Native IoT protocol support for massive device connectivity
and cloud-edge collaboration.</p>
+ </div>
+ <div className={styles.alsoIncludedItem}>
+ <h5>RocketMQ Connect</h5>
+ <p>Low-code data integration connecting 50+ sources for
streaming ETL pipelines.</p>
+ </div>
+ <div className={styles.alsoIncludedItem}>
+ <h5>RocketMQ Streams</h5>
+ <p>Lightweight stream processing engine with Flink SQL
compatibility.</p>
+ </div>
+ </div>
+ </div>
+ </section>
+ </>
+ );
+}
diff --git a/src/pages/components/AISolutions.module.css
b/src/pages/components/AISolutions.module.css
new file mode 100644
index 0000000000..44f7a6d41e
--- /dev/null
+++ b/src/pages/components/AISolutions.module.css
@@ -0,0 +1,419 @@
+/* ===== Solutions Section ===== */
+.solutions {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 5rem 2rem 2rem;
+}
+
+.sectionHeader {
+ margin-bottom: 3rem;
+ text-align: center;
+}
+
+.sectionLabel {
+ font-size: clamp(1.75rem, 3.5vw, 2.5rem);
+ font-weight: 800;
+ color: #1a1a2e;
+ letter-spacing: -0.02em;
+ margin-bottom: 0.75rem;
+}
+
+.sectionDesc {
+ font-size: 1rem;
+ color: #5a5a72;
+ max-width: 700px;
+ margin: 0 auto;
+ line-height: 1.7;
+ white-space: nowrap;
+}
+
+/* Tab Navigation */
+.tabNav {
+ display: flex;
+ gap: 0.25rem;
+ margin-bottom: 0;
+ background: #f5f7fb;
+ border-radius: 12px;
+ padding: 0.375rem;
+ border: 1px solid rgba(0, 0, 0, 0.06);
+}
+
+.tabBtn {
+ flex: 1;
+ padding: 0.875rem 1.25rem;
+ border: none;
+ background: transparent;
+ color: #5a5a72;
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
+ font-size: 0.875rem;
+ font-weight: 500;
+ border-radius: 9px;
+ cursor: pointer;
+ transition: all 0.25s;
+ white-space: nowrap;
+}
+
+.tabBtn:hover {
+ color: #1a1a2e;
+}
+
+.tabBtnActive {
+ background: #ffffff;
+ color: #1a1a2e;
+ font-weight: 600;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
+}
+
+.tabPanel {
+ animation: tabFade 0.35s ease;
+}
+
+@keyframes tabFade {
+ from { opacity: 0; transform: translateY(6px); }
+ to { opacity: 1; transform: translateY(0); }
+}
+
+.solutionCard {
+ background: #ffffff;
+ border: 1px solid rgba(0, 0, 0, 0.06);
+ border-radius: 20px;
+ padding: 3rem;
+ display: grid;
+ grid-template-columns: 2fr 3fr;
+ gap: 3rem;
+ align-items: center;
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
+ min-height: 520px;
+}
+
+.solutionContent h3 {
+ font-size: 1.5rem;
+ font-weight: 700;
+ margin-bottom: 1.25rem;
+ letter-spacing: -0.01em;
+}
+
+.solutionPain {
+ background: #f5f3ff;
+ border-left: 3px solid #7c5cfc;
+ padding: 1rem 1.25rem;
+ border-radius: 0 8px 8px 0;
+ margin-bottom: 1.5rem;
+ font-size: 0.875rem;
+ color: #5a5a72;
+ line-height: 1.7;
+}
+
+.solutionList {
+ list-style: none;
+ margin-bottom: 1.5rem;
+ padding: 0;
+}
+
+.solutionList li {
+ padding: 0.5rem 0;
+ padding-left: 1.25rem;
+ position: relative;
+ font-size: 0.875rem;
+ color: #5a5a72;
+ line-height: 1.7;
+}
+
+.solutionList li::before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0.8rem;
+ width: 6px;
+ height: 6px;
+ border-radius: 50%;
+ background: #4e6ef2;
+}
+
+.solutionValues {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.5rem;
+}
+
+.valueTag {
+ padding: 0.375rem 0.875rem;
+ background: rgba(78, 110, 242, 0.06);
+ border: 1px solid rgba(78, 110, 242, 0.12);
+ border-radius: 100px;
+ font-size: 0.75rem;
+ font-weight: 500;
+ color: #4e6ef2;
+}
+
+.solutionVisual {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-height: 460px;
+ background: linear-gradient(135deg, #f8faff, #f5f0ff);
+ border-radius: 14px;
+ border: 1px solid rgba(0, 0, 0, 0.06);
+ position: relative;
+ overflow: hidden;
+ padding: 1.5rem;
+}
+
+.solutionImg {
+ max-width: 100%;
+ max-height: 420px;
+ width: auto;
+ height: auto;
+ border-radius: 8px;
+ object-fit: contain;
+}
+
+.archDiagram {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ padding: 1.5rem;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 1rem;
+}
+
+.archNode {
+ padding: 0.5rem 1rem;
+ background: #fff;
+ border: 1px solid rgba(0, 0, 0, 0.08);
+ border-radius: 6px;
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 0.65rem;
+ color: #5a5a72;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
+}
+
+.archNode.highlight {
+ border-color: rgba(78, 110, 242, 0.2);
+ background: #f5f3ff;
+ color: #7c5cfc;
+ font-weight: 500;
+}
+
+.highlight {
+ border-color: rgba(78, 110, 242, 0.2) !important;
+ background: #f5f3ff !important;
+ color: #7c5cfc !important;
+ font-weight: 500;
+}
+
+.archFlow {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.archArrow {
+ color: #8e8ea0;
+ font-size: 0.75rem;
+ font-family: 'JetBrains Mono', monospace;
+}
+
+.archArrowRed {
+ color: #e74c3c;
+ font-size: 0.75rem;
+ font-family: 'JetBrains Mono', monospace;
+}
+
+.archCaption {
+ font-size: 0.65rem;
+ color: #8e8ea0;
+ margin-top: 0.5rem;
+}
+
+/* ===== Features Section ===== */
+.featuresSection {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 3rem 2rem 4rem;
+}
+
+.featuresGrid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 1.25rem;
+}
+
+.featureCard {
+ background: #ffffff;
+ border: 1px solid rgba(0, 0, 0, 0.06);
+ border-radius: 12px;
+ padding: 1.75rem;
+ transition: all 0.25s;
+}
+
+.featureCard:hover {
+ border-color: rgba(78, 110, 242, 0.2);
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
+ transform: translateY(-2px);
+}
+
+.featureIcon {
+ width: 36px;
+ height: 36px;
+ background: rgba(78, 110, 242, 0.06);
+ border-radius: 8px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 1rem;
+ font-size: 1rem;
+}
+
+.featureCard h4 {
+ font-size: 0.9375rem;
+ font-weight: 700;
+ margin-bottom: 0.625rem;
+ letter-spacing: -0.01em;
+}
+
+.featureCard ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.featureCard li {
+ font-size: 0.75rem;
+ color: #5a5a72;
+ padding: 0.2rem 0;
+ padding-left: 0.875rem;
+ position: relative;
+ line-height: 1.6;
+}
+
+.featureCard li::before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0.55rem;
+ width: 4px;
+ height: 4px;
+ border-radius: 50%;
+ background: #8e8ea0;
+}
+
+/* ===== Also Included ===== */
+.alsoIncluded {
+ margin-top: 3rem;
+ padding-top: 2.5rem;
+ border-top: 1px solid rgba(0, 0, 0, 0.06);
+}
+
+.alsoIncludedTitle {
+ font-size: 0.6875rem;
+ font-weight: 500;
+ color: #8e8ea0;
+ text-transform: uppercase;
+ letter-spacing: 0.06em;
+ margin-bottom: 1rem;
+}
+
+.alsoIncludedGrid {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 1rem;
+}
+
+.alsoIncludedItem {
+ padding: 1rem;
+ border: 1px solid rgba(0, 0, 0, 0.06);
+ border-radius: 8px;
+ transition: border-color 0.2s;
+}
+
+.alsoIncludedItem:hover {
+ border-color: rgba(0, 0, 0, 0.08);
+}
+
+.alsoIncludedItem h5 {
+ font-size: 0.75rem;
+ font-weight: 600;
+ color: #5a5a72;
+ margin-bottom: 0.375rem;
+}
+
+.alsoIncludedItem p {
+ font-size: 0.6875rem;
+ color: #8e8ea0;
+ line-height: 1.5;
+ margin: 0;
+}
+
+/* ===== Responsive ===== */
+@media (max-width: 1024px) {
+ .solutionCard { grid-template-columns: 1fr; }
+ .featuresGrid { grid-template-columns: repeat(2, 1fr); }
+ .alsoIncludedGrid { grid-template-columns: repeat(2, 1fr); }
+}
+
+@media (max-width: 768px) {
+ .tabNav { flex-direction: column; }
+ .featuresGrid { grid-template-columns: 1fr; }
+ .alsoIncludedGrid { grid-template-columns: 1fr; }
+}
+
+/* ===== Lightbox ===== */
+.lightboxOverlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 9999;
+ background: rgba(0, 0, 0, 0.75);
+ backdrop-filter: blur(6px);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ cursor: zoom-out;
+ animation: lightboxFadeIn 0.2s ease;
+}
+
+@keyframes lightboxFadeIn {
+ from { opacity: 0; }
+ to { opacity: 1; }
+}
+
+.lightboxClose {
+ position: absolute;
+ top: 1.5rem;
+ right: 1.5rem;
+ width: 40px;
+ height: 40px;
+ border: none;
+ background: rgba(255, 255, 255, 0.15);
+ color: #fff;
+ font-size: 1.25rem;
+ border-radius: 50%;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: background 0.2s;
+}
+
+.lightboxClose:hover {
+ background: rgba(255, 255, 255, 0.3);
+}
+
+.lightboxImg {
+ max-width: 90vw;
+ max-height: 85vh;
+ object-fit: contain;
+ border-radius: 12px;
+ background: #ffffff;
+ padding: 2rem;
+ box-shadow: 0 8px 40px rgba(0, 0, 0, 0.3);
+ cursor: default;
+}
diff --git a/src/pages/components/Hero.js b/src/pages/components/Hero.js
index f5534dc621..86d3ea35d6 100644
--- a/src/pages/components/Hero.js
+++ b/src/pages/components/Hero.js
@@ -3,44 +3,33 @@ import Link from "@docusaurus/Link";
import clsx from "clsx";
import styles from "./Hero.module.css";
import Translate, {translate} from '@docusaurus/Translate';
+
export default function Hero(){
return(
-
- <header className={clsx("hero hero--primary", styles.heroBanner)}>
- <div className="container">
- <h1 className={clsx("gradient-text",styles.herotitle)}>Apache
RocketMQ</h1>
- <p className={clsx("hero__subtitle",styles.herosubtitle)}>
- <Translate id="rmq_intro">RocketMQ
5.0:云原生“消息、事件、流”实时数据处理平台,覆盖云边端一体化数据处理场景</Translate>
- </p>
- <div className={clsx('container',styles.github)}>
- <a class="github-button" href="https://github.com/apache/rocketmq"
- data-color-scheme="no-preference: light; light: light; dark:
light;"
- data-icon="octicon-star" data-size="large"
- data-show-count="true" aria-label="Star apache/rocketmq on
GitHub">Star</a>
-
- <a class="github-button"
href="https://github.com/apache/rocketmq/fork"
- data-color-scheme="no-preference: light; light: light; dark:
light;"
- data-icon="octicon-repo-forked" data-size="large"
data-show-count="true"
- aria-label="Fork apache/rocketmq on GitHub">Fork</a>
- </div>
-
- <div className={styles.buttons}>
- <Link
- className={clsx(
- "button button--outline button--secondary
button--lg",styles.button
- )}
- to={"/docs/quickStart/01quickstart"}
- >
- <Translate id="快速开始">快速开始</Translate>
- </Link>
- <Link
- to="/version"
- className={clsx(
- "button button--outline button--secondary
button--lg",styles.button2
- )}
- >
- <Translate id="RocketMQ 5.0 速览">RocketMQ 5.0 速览</Translate>
- </Link>
+ <header className={styles.heroBanner}>
+ <div className={styles.heroInner}>
+ <div className={styles.heroContent}>
+ <div className={styles.heroTag}>Apache Top-Level Project · Open
Source</div>
+ <h1 className={styles.heroTitle}>
+ <span className={styles.gradient}>AI-Native</span>
Asynchronous<br/>Communication Engine
+ </h1>
+ <p className={styles.heroDesc}>
+ <Translate id="hero_desc">Purpose-built for multi-agent
collaboration, AI inference scheduling, and MCP/session state management —
battle-tested at trillion-message scale.</Translate>
+ </p>
+ <div className={styles.heroActions}>
+ <Link
+ className={styles.btnSolid}
+ to={"/docs/quickStart/01quickstart"}
+ >
+ <Translate id="快速开始">Get Started</Translate>
+ </Link>
+ <Link
+ className={styles.btnOutline}
+ to={"/download"}
+ >
+ <Translate id="下载">Download</Translate>
+ </Link>
+ </div>
</div>
</div>
</header>
diff --git a/src/pages/components/Hero.module.css
b/src/pages/components/Hero.module.css
index 12889c7c3d..8efb17af6c 100644
--- a/src/pages/components/Hero.module.css
+++ b/src/pages/components/Hero.module.css
@@ -1,72 +1,135 @@
.heroBanner {
- padding: 4rem 1rem 5rem;
- text-align: center;
+ padding: 56px 2rem 0;
+ background: linear-gradient(160deg, #eef2ff 0%, #f5f0ff 40%, #eef6ff 100%);
position: relative;
overflow: hidden;
- min-height: 100vh;
- background-image: url('/img/rmq-home-page.png');
- background-size: cover;
- background-position: center;
}
-.herotitle {
- font-size: 6.5rem;
- line-height: 1.1;
- word-break: normal;
+.heroBanner::before {
+ content: '';
+ position: absolute;
+ top: -200px;
+ right: -100px;
+ width: 600px;
+ height: 600px;
+ background: radial-gradient(circle, rgba(78, 110, 242, 0.08) 0%, transparent
70%);
+ border-radius: 50%;
}
-.herosubtitle {
- font-size: 1.5rem;
- max-width: 760px;
- margin: 1.5rem auto 0;
+.heroBanner::after {
+ content: '';
+ position: absolute;
+ bottom: -150px;
+ left: -50px;
+ width: 400px;
+ height: 400px;
+ background: radial-gradient(circle, rgba(124, 92, 252, 0.06) 0%, transparent
70%);
+ border-radius: 50%;
}
-@media (max-width: 966px) {
- .herotitle {
- font-size: 6rem;
- }
+.heroInner {
+ max-width: 1200px;
+ margin: 0 auto;
+ position: relative;
+ z-index: 1;
+ padding-top: 4rem;
+ padding-bottom: 4rem;
+}
- .herosubtitle {
- font-size: 1.3rem;
- }
+.heroContent {
+ max-width: 820px;
+ text-align: center;
+ margin: 0 auto;
}
-.buttons {
- display: flex;
- flex-wrap: wrap;
- justify-content: center;
- margin-top: 2.5rem;
+.heroTag {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.25rem 0.875rem;
+ background: rgba(78, 110, 242, 0.08);
+ border: 1px solid rgba(78, 110, 242, 0.2);
+ border-radius: 100px;
+ font-size: 0.6875rem;
+ font-weight: 600;
+ color: #4e6ef2;
+ margin-bottom: 1.25rem;
+ letter-spacing: 0.01em;
+}
+
+.heroTitle {
+ font-size: clamp(2.75rem, 5.5vw, 4.5rem);
+ font-weight: 800;
+ line-height: 1.1;
+ letter-spacing: -0.03em;
+ margin-bottom: 1.25rem;
+ color: #1a1a2e;
}
-.buttons > a {
- margin: 0 6px;
+.gradient {
+ background: linear-gradient(135deg, #4e6ef2, #7c5cfc);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
}
-@media (max-width: 650px) {
- .herotitle{
- font-size: 4rem;
- }
+.heroDesc {
+ font-size: 1.125rem;
+ color: #5a5a72;
+ line-height: 1.7;
+ margin-bottom: 2rem;
+ max-width: 600px;
+ margin-left: auto;
+ margin-right: auto;
+}
- .herosubtitle {
- font-size: 1rem;
- }
+.heroActions {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.875rem;
+}
- .button {
- width: 200px !important;
- }
+.btnSolid {
+ padding: 0.625rem 1.75rem;
+ background: linear-gradient(135deg, #4e6ef2, #6366f1);
+ border: none;
+ border-radius: 8px;
+ color: #fff;
+ text-decoration: none;
+ font-size: 0.875rem;
+ font-weight: 600;
+ transition: all 0.2s;
+ box-shadow: 0 2px 8px rgba(78, 110, 242, 0.25);
+}
- .button2 {
- display: none !important;
- }
+.btnSolid:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 4px 16px rgba(78, 110, 242, 0.35);
+ color: #fff;
+ text-decoration: none;
}
-@media (max-width: 400px) {
- .herotitle{
- font-size: 3.2rem;
- }
+.btnOutline {
+ padding: 0.625rem 1.75rem;
+ border: 1px solid rgba(0, 0, 0, 0.08);
+ border-radius: 8px;
+ color: #5a5a72;
+ text-decoration: none;
+ font-size: 0.875rem;
+ font-weight: 500;
+ transition: all 0.2s;
}
-.github{
- margin-top: 2rem;
+.btnOutline:hover {
+ border-color: #4e6ef2;
+ color: #4e6ef2;
+ text-decoration: none;
}
+@media (max-width: 768px) {
+ .heroActions {
+ flex-direction: column;
+ align-items: center;
+ }
+}
diff --git a/src/pages/index.js b/src/pages/index.js
index 047caba1ce..47619a3ea8 100644
--- a/src/pages/index.js
+++ b/src/pages/index.js
@@ -1,18 +1,9 @@
import React from "react";
-import clsx from "clsx";
import Layout from "@theme/Layout";
-import Head from '@docusaurus/Head';
-import CodeBlock from "@theme/CodeBlock";
-
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
-import LogoCarousel from "./components/LogoCarousel";
-// import Feature from "./components/Feature";
-import Highlight from "./components/Highlight";
-
-import Community from "./components/Community";
-import Section from "./components/Section";
import Hero from "./components/Hero";
-import { logos } from "../constants";
+import AISolutions from "./components/AISolutions";
+import Community from "./components/Community";
function Home() {
@@ -23,18 +14,10 @@ function Home() {
title={`${siteConfig.title} · ${siteConfig.tagline}`}
description={`${siteConfig.tagline}`}
>
- <Head>
- <script async defer
src="https://buttons.github.io/buttons.js"></script>
- </Head>
<Hero/>
<main>
- <Section isDark>
- <Highlight/>
-
- </Section>
-
+ <AISolutions />
<Community />
-
</main>
</Layout>
);
diff --git a/static/picture/v5/litetopic_batch_practice.svg
b/static/picture/v5/litetopic_batch_practice.svg
new file mode 100644
index 0000000000..bddaa05e71
--- /dev/null
+++ b/static/picture/v5/litetopic_batch_practice.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Do not edit this file with editors other than draw.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" style="background: transparent;
background-color: transparent; color-scheme: light dark;"
xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="811px"
height="267px" viewBox="-0.5 -0.5 811 267" content="<mxfile
host="Electron" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X
10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/27.0.9
Chrome/134.0.6998.205 Electron/35.4.0 Safari/537.36"
version="27.0.9"> [...]
\ No newline at end of file
diff --git a/static/picture/v5/litetopic_multiagent_practice.svg
b/static/picture/v5/litetopic_multiagent_practice.svg
new file mode 100644
index 0000000000..f482a31af7
--- /dev/null
+++ b/static/picture/v5/litetopic_multiagent_practice.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" data-width="963"
data-height="583" class="icms-hetu-svg" width="963px" height="583px"><defs /><g
transform="translate(0.5,0.5)"><rect x="1" y="201" width="120" height="160"
fill="#ffffff" stroke="#d9d9d9" pointer-events="none" /><rect x="161" y="1"
width="800" height="580" fill="#f0f0f0" stroke="none" pointer-events="none"
/><g><switch><foreignObject style="overflow: visible; text-align: left;"
pointer-events="none" width="100%" heigh [...]
\ No newline at end of file
diff --git a/static/picture/v5/litetopic_ratelimit_practice.svg
b/static/picture/v5/litetopic_ratelimit_practice.svg
new file mode 100644
index 0000000000..3906437afd
--- /dev/null
+++ b/static/picture/v5/litetopic_ratelimit_practice.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Do not edit this file with editors other than draw.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" style="background: transparent;
background-color: transparent; color-scheme: light dark;"
xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1353px"
height="451px" viewBox="-0.5 -0.5 1353 451" content="<mxfile
host="Electron" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X
10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/27.0.9
Chrome/134.0.6998.205 Electron/35.4.0 Safari/537.36"
version="27.0.9"&g [...]
\ No newline at end of file
diff --git a/static/picture/v5/litetopic_session_practice.svg
b/static/picture/v5/litetopic_session_practice.svg
new file mode 100644
index 0000000000..c50997897b
--- /dev/null
+++ b/static/picture/v5/litetopic_session_practice.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" data-width="1067"
data-height="403" class="icms-hetu-svg" width="1067px" height="403px"><defs
/><g transform="translate(0.5,0.5)"><rect x="578" y="1" width="150"
height="400" fill="#ffffff" stroke="#d9d9d9" pointer-events="none"
/><g><switch><foreignObject style="overflow: visible; text-align: left;"
pointer-events="none" width="100%" height="100%"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div
xmlns="http:// [...]
\ No newline at end of file