@lovrabet/rabetbase-cli 2.0.2-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/LICENSE +45 -0
  2. package/README.md +605 -0
  3. package/lib/ai-setup/config.js +1 -0
  4. package/lib/api/api-doc-ui.js +1 -0
  5. package/lib/api/api-doc.js +1 -0
  6. package/lib/api/api-pull-ui.js +1 -0
  7. package/lib/api/fetch-model-list.js +1 -0
  8. package/lib/api/generate-api-file.js +1 -0
  9. package/lib/api/main.js +1 -0
  10. package/lib/api/pull-silent.js +1 -0
  11. package/lib/app-menu/app-menu-sync-ui.js +1 -0
  12. package/lib/app-menu/create-menu.js +1 -0
  13. package/lib/app-menu/get-local-pages.js +1 -0
  14. package/lib/app-menu/get-online-menu-list.js +1 -0
  15. package/lib/app-menu/types.js +1 -0
  16. package/lib/app-menu/use-get-online-menu-list.js +1 -0
  17. package/lib/app-menu/utils.js +1 -0
  18. package/lib/app-menu/valid-url.js +1 -0
  19. package/lib/app-menu-update-cdn/current-content.js +1 -0
  20. package/lib/app-menu-update-cdn/input-cdn-asset.js +1 -0
  21. package/lib/app-menu-update-cdn/main.js +1 -0
  22. package/lib/app-menu-update-cdn/types.js +1 -0
  23. package/lib/app-menu-update-cdn/update-menu-cdn-url.js +1 -0
  24. package/lib/auth/auth-server-ui.js +1 -0
  25. package/lib/auth/auth-server.js +1 -0
  26. package/lib/auth/constant.js +1 -0
  27. package/lib/auth/get-cookie.js +1 -0
  28. package/lib/auth/is-session-valid.js +1 -0
  29. package/lib/auth/logout.js +1 -0
  30. package/lib/cli-flags.js +1 -0
  31. package/lib/cli.js +2 -0
  32. package/lib/commands/api.js +1 -0
  33. package/lib/commands/app.js +1 -0
  34. package/lib/commands/auth.js +1 -0
  35. package/lib/commands/bff/delete.js +1 -0
  36. package/lib/commands/bff/detail.js +1 -0
  37. package/lib/commands/bff/index.js +1 -0
  38. package/lib/commands/bff/list.js +1 -0
  39. package/lib/commands/bff/new.js +1 -0
  40. package/lib/commands/bff/pull.js +1 -0
  41. package/lib/commands/bff/push.js +1 -0
  42. package/lib/commands/bff/status.js +1 -0
  43. package/lib/commands/build.js +1 -0
  44. package/lib/commands/codegen/index.js +1 -0
  45. package/lib/commands/codegen/sdk.js +1 -0
  46. package/lib/commands/codegen/sql.js +1 -0
  47. package/lib/commands/config.js +1 -0
  48. package/lib/commands/create.js +1 -0
  49. package/lib/commands/dataset/detail.js +1 -0
  50. package/lib/commands/dataset/index.js +1 -0
  51. package/lib/commands/dataset/links.js +1 -0
  52. package/lib/commands/dataset/list.js +1 -0
  53. package/lib/commands/dataset/operations.js +1 -0
  54. package/lib/commands/init.js +1 -0
  55. package/lib/commands/logout.js +1 -0
  56. package/lib/commands/logs.js +1 -0
  57. package/lib/commands/mcp.js +1 -0
  58. package/lib/commands/menu.js +1 -0
  59. package/lib/commands/preview.js +1 -0
  60. package/lib/commands/registry.js +1 -0
  61. package/lib/commands/run.js +1 -0
  62. package/lib/commands/skill.js +1 -0
  63. package/lib/commands/sql/detail.js +1 -0
  64. package/lib/commands/sql/exec.js +1 -0
  65. package/lib/commands/sql/index.js +1 -0
  66. package/lib/commands/sql/list.js +1 -0
  67. package/lib/commands/sql/save.js +1 -0
  68. package/lib/commands/sql/validate.js +1 -0
  69. package/lib/commands/start.js +1 -0
  70. package/lib/config/config-help.js +1 -0
  71. package/lib/config/main.js +1 -0
  72. package/lib/constant/cli.js +1 -0
  73. package/lib/constant/domain.js +1 -0
  74. package/lib/constant/env.js +1 -0
  75. package/lib/context.js +1 -0
  76. package/lib/core/alias-resolver.js +1 -0
  77. package/lib/core/api-client.js +1 -0
  78. package/lib/core/bff/config.js +1 -0
  79. package/lib/core/bff/file-system.js +1 -0
  80. package/lib/core/bff/hash.js +1 -0
  81. package/lib/core/bff/lock.js +1 -0
  82. package/lib/core/bff/types.js +1 -0
  83. package/lib/core/bff/utils.js +1 -0
  84. package/lib/core/db-resolver.js +1 -0
  85. package/lib/core/sql-validator.js +1 -0
  86. package/lib/create-app/enhanced-guided-create.js +1 -0
  87. package/lib/create-app/format-elapsed.js +1 -0
  88. package/lib/create-app/main.js +1 -0
  89. package/lib/create-app/non-interactive.js +1 -0
  90. package/lib/create-app/task-finished.js +1 -0
  91. package/lib/create-app/task-loading.js +1 -0
  92. package/lib/create-app/task-running.js +1 -0
  93. package/lib/create-app/task-time.js +1 -0
  94. package/lib/create-app/use-copy-project-template.js +1 -0
  95. package/lib/create-app/use-format-code.js +1 -0
  96. package/lib/create-app/use-install-dependencies.js +1 -0
  97. package/lib/errors.js +1 -0
  98. package/lib/framework/flags.js +1 -0
  99. package/lib/framework/help.js +1 -0
  100. package/lib/framework/index.js +1 -0
  101. package/lib/framework/output.js +1 -0
  102. package/lib/framework/response.js +1 -0
  103. package/lib/framework/runner.js +1 -0
  104. package/lib/framework/types.js +1 -0
  105. package/lib/generated/build-info.js +1 -0
  106. package/lib/help.js +1 -0
  107. package/lib/init/main.js +1 -0
  108. package/lib/mcp/McpInstallUI.js +1 -0
  109. package/lib/mcp/claude.js +1 -0
  110. package/lib/mcp/cursor.js +1 -0
  111. package/lib/mcp/main.js +1 -0
  112. package/lib/mcp/mcp-install-non-interactive.js +1 -0
  113. package/lib/mcp/mcp-installer.js +1 -0
  114. package/lib/skills/main.js +1 -0
  115. package/lib/skills/npx-skills-add.js +1 -0
  116. package/lib/types/index.js +1 -0
  117. package/lib/ui/IDESelector.js +1 -0
  118. package/lib/ui/useIDESelection.js +1 -0
  119. package/lib/utils/ai_config.js +1 -0
  120. package/lib/utils/cdn-config.js +1 -0
  121. package/lib/utils/check-sdk-version.js +1 -0
  122. package/lib/utils/cli-version-check.js +1 -0
  123. package/lib/utils/config.js +1 -0
  124. package/lib/utils/copy-directory.js +1 -0
  125. package/lib/utils/file-utils.js +1 -0
  126. package/lib/utils/guides-cdn.js +1 -0
  127. package/lib/utils/http-client.js +1 -0
  128. package/lib/utils/logger.js +1 -0
  129. package/lib/utils/rules-cdn.js +1 -0
  130. package/lib/utils/sleep.js +1 -0
  131. package/lib/utils/template-replacer.js +1 -0
  132. package/package.json +77 -0
  133. package/sidecar/flags.json +10 -0
  134. package/templates/README.md +97 -0
  135. package/templates/generate-api/api.ts.tpl +47 -0
  136. package/templates/generate-api/client.ts.tpl +64 -0
  137. package/templates/projects/sub-app-react-demo/.prettierrc +1 -0
  138. package/templates/projects/sub-app-react-demo/CHANGELOG.md +53 -0
  139. package/templates/projects/sub-app-react-demo/README.md +318 -0
  140. package/templates/projects/sub-app-react-demo/docs/API_RULE_CHANGE.md +212 -0
  141. package/templates/projects/sub-app-react-demo/docs/quick-start.md +526 -0
  142. package/templates/projects/sub-app-react-demo/index.html +27 -0
  143. package/templates/projects/sub-app-react-demo/package.json +34 -0
  144. package/templates/projects/sub-app-react-demo/public/logo.svg +1 -0
  145. package/templates/projects/sub-app-react-demo/public/vite.svg +1 -0
  146. package/templates/projects/sub-app-react-demo/src/api/api.ts +83 -0
  147. package/templates/projects/sub-app-react-demo/src/api/client.ts +64 -0
  148. package/templates/projects/sub-app-react-demo/src/layouts/MainLayout.tsx +311 -0
  149. package/templates/projects/sub-app-react-demo/src/main.tsx +48 -0
  150. package/templates/projects/sub-app-react-demo/src/pages/dashboard/index.tsx +572 -0
  151. package/templates/projects/sub-app-react-demo/src/pages/data-screen/index.tsx +526 -0
  152. package/templates/projects/sub-app-react-demo/src/pages/index.tsx +467 -0
  153. package/templates/projects/sub-app-react-demo/src/pages/sdk-demo/index.tsx +453 -0
  154. package/templates/projects/sub-app-react-demo/src/pages/workbench/index.module.css +293 -0
  155. package/templates/projects/sub-app-react-demo/src/pages/workbench/index.tsx +155 -0
  156. package/templates/projects/sub-app-react-demo/src/router/index.tsx +30 -0
  157. package/templates/projects/sub-app-react-demo/src/style.css +92 -0
  158. package/templates/projects/sub-app-react-demo/src/utils/api.ts +12 -0
  159. package/templates/projects/sub-app-react-demo/src/vite-env.d.ts +2 -0
  160. package/templates/projects/sub-app-react-demo/tsconfig.json +26 -0
  161. package/templates/projects/sub-app-react-demo/vite.config.ts +111 -0
  162. package/templates/rules/lovrabet_rules.mdc.tpl +891 -0
  163. package/templates/skill/SKILL.md.tpl +120 -0
@@ -0,0 +1,467 @@
1
+ /**
2
+ * Title: Rabetbase 开发指南
3
+ */
4
+ import React from "react";
5
+ import {
6
+ Typography,
7
+ Card,
8
+ Row,
9
+ Col,
10
+ Button,
11
+ Tabs,
12
+ Alert,
13
+ Space,
14
+ Tag,
15
+ } from "antd";
16
+ import {
17
+ CodeOutlined,
18
+ RobotOutlined,
19
+ ToolOutlined,
20
+ BookOutlined,
21
+ ArrowRightOutlined,
22
+ CopyOutlined,
23
+ CheckOutlined,
24
+ RocketOutlined,
25
+ ExclamationCircleOutlined,
26
+ } from "@ant-design/icons";
27
+
28
+ const { Title, Paragraph, Text } = Typography;
29
+
30
+ // 可复制的代码块
31
+ function CopyableCode({ code, label }: { code: string; label: string }) {
32
+ const [copied, setCopied] = React.useState(false);
33
+
34
+ const handleCopy = async () => {
35
+ await navigator.clipboard.writeText(code);
36
+ setCopied(true);
37
+ setTimeout(() => setCopied(false), 2000);
38
+ };
39
+
40
+ return (
41
+ <div style={{ marginBottom: 12 }}>
42
+ <div
43
+ style={{
44
+ display: "flex",
45
+ justifyContent: "space-between",
46
+ alignItems: "center",
47
+ marginBottom: 8,
48
+ }}
49
+ >
50
+ <Text type="secondary">{label}</Text>
51
+ <Button
52
+ type="primary"
53
+ size="small"
54
+ icon={copied ? <CheckOutlined /> : <CopyOutlined />}
55
+ onClick={handleCopy}
56
+ >
57
+ {copied ? "已复制" : "复制"}
58
+ </Button>
59
+ </div>
60
+ <pre
61
+ style={{
62
+ background: "#1e1e1e",
63
+ borderRadius: 8,
64
+ padding: "16px 20px",
65
+ margin: 0,
66
+ fontFamily: "'JetBrains Mono', 'Monaco', monospace",
67
+ fontSize: 13,
68
+ lineHeight: 1.6,
69
+ color: "#e4e4e7",
70
+ overflowX: "auto",
71
+ }}
72
+ >
73
+ <code>{code}</code>
74
+ </pre>
75
+ </div>
76
+ );
77
+ }
78
+
79
+ // 从 api.ts 提取 appCode
80
+ function getAppCodeFromApi(content: string): string | null {
81
+ const match =
82
+ content.match(/RABETBASE_APP_CODE\s*=\s*["']([^"']+)["']/) ||
83
+ content.match(/appCode:\s*["']([^"']+)["']/);
84
+ return match ? match[1] : null;
85
+ }
86
+
87
+ function HomePage() {
88
+ const [appCode, setAppCode] = React.useState<string | null>(null);
89
+ const [loading, setLoading] = React.useState(true);
90
+
91
+ React.useEffect(() => {
92
+ const loadAppCode = async () => {
93
+ try {
94
+ const modules = import.meta.glob("/src/api/*.ts", {
95
+ query: "?raw",
96
+ import: "default",
97
+ });
98
+ const apiPath = "/src/api/api.ts";
99
+
100
+ if (apiPath in modules) {
101
+ const content = await modules[apiPath]();
102
+ const code = getAppCodeFromApi(content as string);
103
+ setAppCode(code);
104
+ }
105
+ } catch (err) {
106
+ console.error("加载 api.ts 失败:", err);
107
+ } finally {
108
+ setLoading(false);
109
+ }
110
+ };
111
+
112
+ loadAppCode();
113
+ }, []);
114
+
115
+ // 检查是否已配置
116
+ const isNotSet = appCode === "NOT-SET" || appCode === null;
117
+ const displayAppCode = isNotSet ? "your-app-code" : appCode;
118
+
119
+ const mcpConfig = `{
120
+ "mcpServers": {
121
+ "lovrabet-dataset": {
122
+ "command": "npx",
123
+ "args": ["-y", "@lovrabet/dataset-mcp-server"],
124
+ "env": {
125
+ "RABETBASE_APP_CODE": "${displayAppCode}"
126
+ }
127
+ }
128
+ }
129
+ }`;
130
+
131
+ const cliCode = `# 拉取最新 API 配置
132
+ lovrabet api pull
133
+
134
+ # 微前端子应用同步菜单
135
+ lovrabet menu sync`;
136
+
137
+ const configTabs = [
138
+ {
139
+ key: "mcp",
140
+ label: (
141
+ <span>
142
+ <RobotOutlined /> MCP 配置
143
+ </span>
144
+ ),
145
+ children: (
146
+ <div>
147
+ <Paragraph>claude code 配置:</Paragraph>
148
+ <Paragraph style={{ fontSize: 12, color: "#666" }}>
149
+ 配置文件路径:
150
+ <br />
151
+ macOS: ~/Library/Application
152
+ Support/Claude/claude_desktop_config.json
153
+ <br />
154
+ Windows: %APPDATA%/Claude/claude_desktop_config.json
155
+ </Paragraph>
156
+ <CopyableCode code={mcpConfig} label="claude_desktop_config.json" />
157
+
158
+ <Paragraph style={{ marginTop: 16 }}>Cursor 配置:</Paragraph>
159
+ <Paragraph style={{ fontSize: 12, color: "#666" }}>
160
+ 设置 → MCP → 添加服务器
161
+ </Paragraph>
162
+ <CopyableCode
163
+ code={`// Cursor MCP 配置
164
+ {
165
+ "mcpServers": {
166
+ "lovrabet-dataset": {
167
+ "command": "npx",
168
+ "args": ["-y", "@lovrabet/dataset-mcp-server"],
169
+ "env": {
170
+ "RABETBASE_APP_CODE": "${displayAppCode}"
171
+ }
172
+ }
173
+ }
174
+ }`}
175
+ label="Cursor MCP 配置"
176
+ />
177
+
178
+ <Paragraph style={{ marginTop: 16 }}>
179
+ Claude Code (VS Code 扩展):
180
+ </Paragraph>
181
+ <CopyableCode
182
+ code={`claude mcp add lovrabet-dataset npx @lovrabet/dataset-mcp-server@latest -e RABETBASE_APP_CODE=${displayAppCode}`}
183
+ label="Claude Code 终端命令"
184
+ />
185
+
186
+ <Button
187
+ type="link"
188
+ href="https://open.lovrabet.com/docs/mcp/intro"
189
+ target="_blank"
190
+ >
191
+ 查看完整文档 <ArrowRightOutlined />
192
+ </Button>
193
+ </div>
194
+ ),
195
+ },
196
+ {
197
+ key: "cli",
198
+ label: (
199
+ <span>
200
+ <ToolOutlined /> CLI 命令
201
+ </span>
202
+ ),
203
+ children: (
204
+ <div>
205
+ <Paragraph>常用 CLI 命令:</Paragraph>
206
+ <CopyableCode code={cliCode} label="终端命令" />
207
+ <Button
208
+ type="link"
209
+ href="https://open.lovrabet.com/docs/lovrabet-cli/quickstart"
210
+ target="_blank"
211
+ >
212
+ 查看完整文档 <ArrowRightOutlined />
213
+ </Button>
214
+ </div>
215
+ ),
216
+ },
217
+ ];
218
+
219
+ const docLinks = [
220
+ {
221
+ title: "入门指南",
222
+ icon: <RocketOutlined />,
223
+ links: [
224
+ {
225
+ label: "5 分钟上手指引",
226
+ url: "https://open.lovrabet.com/docs/guides/step-guide",
227
+ },
228
+ {
229
+ label: "开发者工具全景",
230
+ url: "https://open.lovrabet.com/docs/guides/toolchain",
231
+ },
232
+ { label: "常见问题", url: "https://open.lovrabet.com/docs/guides/faq" },
233
+ ],
234
+ },
235
+ {
236
+ title: "开发文档",
237
+ icon: <BookOutlined />,
238
+ links: [
239
+ {
240
+ label: "TypeScript SDK",
241
+ url: "https://open.lovrabet.com/docs/lovrabet-sdk/intro",
242
+ },
243
+ {
244
+ label: "Java SDK",
245
+ url: "https://open.lovrabet.com/docs/java-opensdk/quickstart",
246
+ },
247
+ {
248
+ label: "OpenAPI",
249
+ url: "https://open.lovrabet.com/docs/openapi/intro",
250
+ },
251
+ { label: "MCP", url: "https://open.lovrabet.com/docs/mcp/intro" },
252
+ {
253
+ label: "Backend Function",
254
+ url: "https://open.lovrabet.com/docs/guides/best-practices",
255
+ },
256
+ ],
257
+ },
258
+ ];
259
+
260
+ return (
261
+ <div style={{ maxWidth: "1200px", margin: "0 auto", padding: "24px" }}>
262
+ {/* 标题区 */}
263
+ <div style={{ marginBottom: 32 }}>
264
+ <div
265
+ style={{
266
+ display: "flex",
267
+ justifyContent: "space-between",
268
+ alignItems: "flex-start",
269
+ flexWrap: "wrap",
270
+ gap: 16,
271
+ }}
272
+ >
273
+ <div>
274
+ <Title level={2} style={{ margin: 0 }}>
275
+ Rabetbase 开发指南
276
+ </Title>
277
+ <Paragraph style={{ color: "#666", marginTop: 8, marginBottom: 0 }}>
278
+ 基于 Lovrabet 平台的后端即服务(BaaS)
279
+ </Paragraph>
280
+ </div>
281
+ <Space size="middle">
282
+ <a
283
+ href="https://open.lovrabet.com"
284
+ target="_blank"
285
+ rel="noopener noreferrer"
286
+ >
287
+ Rabetbase官网
288
+ </a>
289
+ <a
290
+ href="https://open.lovrabet.com/docs/changelog"
291
+ target="_blank"
292
+ rel="noopener noreferrer"
293
+ >
294
+ 更新日志
295
+ </a>
296
+ {!isNotSet && appCode && (
297
+ <a
298
+ href={`https://app.lovrabet.com/app/${appCode}/data/intro/`}
299
+ target="_blank"
300
+ rel="noopener noreferrer"
301
+ >
302
+ 应用配置后台
303
+ </a>
304
+ )}
305
+ </Space>
306
+ </div>
307
+ </div>
308
+
309
+ {/* Rabetbase 介绍卡片 */}
310
+ <Card style={{ marginBottom: 24 }}>
311
+ <Row gutter={[24, 16]} align="middle">
312
+ <Col xs={24} lg={16}>
313
+ <Title level={3} style={{ marginBottom: 12 }}>
314
+ 什么是 Rabetbase?
315
+ </Title>
316
+ <Paragraph
317
+ style={{ fontSize: 15, marginBottom: 16, color: "#595959" }}
318
+ >
319
+ <strong>Rabetbase 是 Lovrabet 面向技术岗位的开发者平台。</strong>
320
+ <br />
321
+ Lovrabet 工作台让业务人员用 AI
322
+ 生成管理系统,但有些个性化需求(如小程序、ERP
323
+ 对接、复杂业务逻辑)需要开发者介入。 Rabetbase 把 Lovrabet
324
+ 平台的数据能力开放出来,让开发者专注于写业务逻辑。
325
+ </Paragraph>
326
+ <Space wrap>
327
+ <Button
328
+ size="small"
329
+ href="https://open.lovrabet.com/docs/category/openapi"
330
+ target="_blank"
331
+ >
332
+ OpenAPI
333
+ </Button>
334
+ <Button
335
+ size="small"
336
+ href="https://open.lovrabet.com/docs/category/lovrabet-node-sdk"
337
+ target="_blank"
338
+ >
339
+ TypeScript SDK
340
+ </Button>
341
+ <Button
342
+ size="small"
343
+ href="https://open.lovrabet.com/docs/category/java-opensdk"
344
+ target="_blank"
345
+ >
346
+ Java SDK
347
+ </Button>
348
+ <Button
349
+ size="small"
350
+ href="https://open.lovrabet.com/docs/mcp/intro"
351
+ target="_blank"
352
+ >
353
+ MCP
354
+ </Button>
355
+ <Button
356
+ size="small"
357
+ href="https://open.lovrabet.com/docs/lovrabet-cli/"
358
+ target="_blank"
359
+ >
360
+ CLI 工具
361
+ </Button>
362
+ </Space>
363
+ </Col>
364
+ <Col xs={24} lg={8}>
365
+ <div
366
+ style={{
367
+ background: "#f5f5f5",
368
+ borderRadius: 8,
369
+ padding: 20,
370
+ }}
371
+ >
372
+ <Text
373
+ style={{ fontSize: 14, display: "block", marginBottom: 12 }}
374
+ >
375
+ <strong>核心价值:</strong>
376
+ </Text>
377
+ <ul
378
+ style={{
379
+ color: "#595959",
380
+ margin: 0,
381
+ paddingLeft: 20,
382
+ fontSize: 14,
383
+ }}
384
+ >
385
+ <li style={{ marginBottom: 8 }}>AI 自动理解业务模型</li>
386
+ <li style={{ marginBottom: 8 }}>现成的 API 和 SDK</li>
387
+ <li style={{ marginBottom: 8 }}>开发效率提升 2~5 倍</li>
388
+ <li>你只需要专注写业务逻辑</li>
389
+ </ul>
390
+ </div>
391
+ </Col>
392
+ </Row>
393
+ </Card>
394
+
395
+ {/* 未配置提示 */}
396
+ {isNotSet && !loading && (
397
+ <Alert
398
+ type="warning"
399
+ icon={<ExclamationCircleOutlined />}
400
+ message="项目尚未配置 AppCode"
401
+ description={
402
+ <div style={{ marginTop: 8 }}>
403
+ <Paragraph style={{ marginBottom: 8 }}>
404
+ 请先执行以下命令初始化项目(替换{" "}
405
+ <code>&lt;your-app-code&gt;</code> 为你的应用代码):
406
+ </Paragraph>
407
+ <CopyableCode
408
+ code={`# 1. 设置 AppCode
409
+ lovrabet config set app <your-app-code>
410
+
411
+ # 2. 拉取 API 配置
412
+ lovrabet api pull`}
413
+ label="初始化命令"
414
+ />
415
+ <Paragraph style={{ marginBottom: 0 }}>
416
+ 执行完成后刷新页面即可。
417
+ </Paragraph>
418
+ </div>
419
+ }
420
+ style={{ marginBottom: 24 }}
421
+ />
422
+ )}
423
+
424
+ {/* 配置代码 */}
425
+ <Card style={{ marginBottom: 24 }}>
426
+ <Tabs items={configTabs} />
427
+ </Card>
428
+
429
+ {/* 文档链接 */}
430
+ <Row gutter={16}>
431
+ {docLinks.map((section) => (
432
+ <Col xs={24} md={12} key={section.title}>
433
+ <Card style={{ height: "100%" }}>
434
+ <div
435
+ style={{
436
+ display: "flex",
437
+ alignItems: "center",
438
+ gap: 8,
439
+ marginBottom: 16,
440
+ }}
441
+ >
442
+ {section.icon}
443
+ <Title level={4} style={{ margin: 0 }}>
444
+ {section.title}
445
+ </Title>
446
+ </div>
447
+ {section.links.map((link) => (
448
+ <div key={link.label}>
449
+ <Button
450
+ type="link"
451
+ href={link.url}
452
+ target="_blank"
453
+ style={{ padding: "8px 0" }}
454
+ >
455
+ {link.label} <ArrowRightOutlined />
456
+ </Button>
457
+ </div>
458
+ ))}
459
+ </Card>
460
+ </Col>
461
+ ))}
462
+ </Row>
463
+ </div>
464
+ );
465
+ }
466
+
467
+ export default HomePage;