Fix/footer layout theme sync ux - #2956
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
- 统一语言状态: 修复 PageLayout 遗留 i18nextLng 引用为 locale - 统一图标库: UserArea 使用 Lucide React 替换 Semi UI 图标 - 全局页脚: 移除 shouldHideFooter 逻辑,所有页面显示统一页脚
- Sync language and dark/light theme between openclawapi.ai and api.openclawapi.ai via shared cookies - Align backend footer/header behavior and copy with frontend, removing visible "console" wording in favor of api.openclawapi.ai Co-authored-by: Cursor <cursoragent@cursor.com>
- 移除所有console.log/console.error/console.warn语句(214行,63个文件) - 确认语言和主题已通过cookie(oc_locale/oc_theme)在前后端同步 - 确认footer样式正确:h4标题使用白色,li子项使用红色/brand颜色 - footer定位已正确实现(滚动到底部才显示)
fix: 清理后端console语句,确认语言/主题同步和footer样式
- Footer: remove broken IntersectionObserver; show compact copyright bar on console pages, full multi-column footer on non-console pages - PageLayout: move footer outside Content for proper sticky-bottom; add mobile sidebar backdrop overlay (click to close) - LanguageSelector: show target language name (match frontend behavior) - UserArea: replace hardcoded dark: Tailwind classes with Semi UI CSS variables for correct dark/light mode rendering - User context: set/clear oc_logged_in cookie on login/logout so the frontend (openclawapi.ai) can detect auth state cross-domain
WalkthroughThe pull request implements a comprehensive rebranding from "New API" to "OpenClaw API," introducing deployment automation via GitHub Actions, updating branding assets and color constants, refactoring frontend layout and styling with simplified empty-state placeholders and semantic color tokens, expanding i18n with footer content, adding cookie-based persistence for theme and locale, and systematically removing console logging statements throughout the frontend for cleaner production behavior. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
Note
Due to the large number of review comments, Critical severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (13)
web/src/components/topup/InvitationCard.jsx (1)
64-168:⚠️ Potential issue | 🟠 MajorWhite text on a light background — stats section will be unreadable in light mode.
The cover background was changed from a (presumably dark) gradient to
var(--semi-color-bg-1), which is a light color in light theme. However, the three stat values (lines 98, 123, 148) still usestyle={{ color: 'white' }}and their labels (lines 107, 110, 130, 134, 153, 158) usergba(255,255,255,0.8). This makes the "待使用收益", "总收益", "邀请人数" figures and labels invisible against the new light background.Update these to use semantic tokens (e.g.,
var(--semi-color-text-0)for values andvar(--semi-color-text-2)for labels) to match the header text treatment on line 73.Proposed fix (representative — apply same pattern to all three stat blocks)
<div className='text-base sm:text-2xl font-bold mb-2' - style={{ color: 'white' }} + style={{ color: 'var(--semi-color-text-0)' }} >- style={{ color: 'rgba(255,255,255,0.8)' }} + style={{ color: 'var(--semi-color-text-2)' }}web/src/pages/Setting/Performance/SettingsPerformance.jsx (1)
125-126:⚠️ Potential issue | 🟡 MinorSilent error swallowing in
fetchStats.Removing
console.errorleaves a completely emptycatchblock — network or server errors when fetching performance stats will be invisible to both users and developers debugging in the browser. Consider at minimum keeping a lightweight log or callingshowError.🛠️ Suggested minimal fix
} catch (error) { + // stats fetch is non-critical; log for debugging + console.warn('Failed to fetch performance stats', error); } finally {web/src/components/settings/OtherSetting.jsx (1)
494-494:⚠️ Potential issue | 🟠 MajorXSS risk with
dangerouslySetInnerHTMLon external content.
marked.parse(body)on the GitHub API response is rendered unsanitized. While this is an admin-only update check, a compromised or spoofed response could inject scripts. Consider sanitizing with a library likeDOMPurifybefore rendering.Proposed fix
+import DOMPurify from 'dompurify';Then at Line 259:
- content: marked.parse(body), + content: DOMPurify.sanitize(marked.parse(body)),web/src/components/table/model-pricing/layout/header/PricingVendorIntroSkeleton.jsx (1)
134-142:⚠️ Potential issue | 🟡 MinorHardcoded
rgba(255, 255, 255, 0.15)may be invisible on light backgrounds.The second description skeleton (
desc2) overridesbackgroundColorwithrgba(255, 255, 255, 0.15). Previously this worked against a colored/dark cover, but the cover now usesvar(--semi-color-bg-1), which is typically a light color in light mode. A nearly-white skeleton on a white background would be invisible.Consider using a CSS variable consistent with the other skeleton elements:
Proposed fix
{createSkeletonRect( { ...SKELETON_STYLES.description, - backgroundColor: 'rgba(255, 255, 255, 0.15)', + backgroundColor: 'var(--semi-color-fill-0)', width: '75%', height: SIZES.description.height, }, 'desc2', )}web/src/helpers/utils.jsx (3)
18-30:⚠️ Potential issue | 🟠 Major
JSON.parsewithout try/catch will crash on corrupted localStorage.Both
isAdmin()andisRoot()callJSON.parse(user)without a try/catch. If theuserkey in localStorage contains malformed JSON (e.g., from a different version or manual tampering), these functions will throw an unhandled exception, potentially breaking any component that calls them.Proposed fix
export function isAdmin() { let user = localStorage.getItem('user'); if (!user) return false; - user = JSON.parse(user); - return user.role >= 10; + try { + user = JSON.parse(user); + return user.role >= 10; + } catch { + return false; + } } export function isRoot() { let user = localStorage.getItem('user'); if (!user) return false; - user = JSON.parse(user); - return user.role >= 100; + try { + user = JSON.parse(user); + return user.role >= 100; + } catch { + return false; + } }
44-49:⚠️ Potential issue | 🟠 MajorSame
JSON.parsecrash risk ingetUserIdFromLocalStorage.Same issue as
isAdmin/isRoot— wrap in try/catch and return the fallback-1on parse failure.
14-16:⚠️ Potential issue | 🟠 Major
dangerouslySetInnerHTMLin toast content — XSS vector.
HTMLToastContentrenders arbitrary HTML. If thehtmlContentoriginates from an untrusted or insufficiently sanitized source, this is a stored XSS risk. Consider sanitizing with a library like DOMPurify before rendering.web/src/index.jsx (1)
38-43:⚠️ Potential issue | 🔴 CriticalSyntax error: missing
console.log(— this will crash on load.The
console.log(call appears to have been removed when the string argument was modified. The current code is a bare string expression followed by);, which is a syntax error.Proposed fix
if (typeof window !== 'undefined') { + console.log( '%cOpenClaw API%c https://openclawapi.ai', 'color: `#10b981`; font-weight: bold; font-size: 24px;', 'color: inherit; font-size: 14px;', ); }web/src/pages/Home/index.jsx (1)
226-239:⚠️ Potential issue | 🟡 Minor
IconGithubLogoused for a non-GitHub docs link — misleading.The button now navigates to
https://openclawapi.ai/docsbut still usesIconGithubLogoas its icon. Users will expect a GitHub icon to lead to a GitHub page. Consider usingIconFileor another docs-appropriate icon instead.web/src/components/settings/personal/cards/PreferencesSettings.jsx (1)
101-111:⚠️ Potential issue | 🟡 MinorCookie and localStorage are not reverted on backend save failure.
When the backend save fails (lines 101–111),
currentLanguageandi18nare reverted topreviousLang, but thelocalStorage('locale')andsetCookie('oc_locale', lang)writes from lines 72–73 are not undone. On next page load, the stale cookie/localStorage value may override the user's actual preference.Proposed fix
} else { showError(res.data.message || t('保存失败')); // Revert on error setCurrentLanguage(previousLang); i18n.changeLanguage(previousLang); + try { + localStorage.setItem('locale', previousLang); + setCookie('oc_locale', previousLang); + } catch (e) { + // ignore + } } } catch (error) { showError(t('保存失败,请重试')); // Revert on error setCurrentLanguage(previousLang); i18n.changeLanguage(previousLang); + try { + localStorage.setItem('locale', previousLang); + setCookie('oc_locale', previousLang); + } catch (e) { + // ignore + } } finally {web/src/i18n/locales/fr.json (1)
1-2724:⚠️ Potential issue | 🟡 MinorThis file is now unused —
i18n.jsonly loadszhandenresources.The updated
web/src/i18n/i18n.jsrestrictssupportedLngsto['zh', 'en']and only importsen.jsonandzh.json. French translations in this file will never be loaded at runtime. Either removefr.json(and other dropped locale files) to avoid maintenance burden, or re-add French to the i18n configuration if it should remain supported.web/src/i18n/locales/en.json (1)
2763-2802:⚠️ Potential issue | 🟠 MajorRemove duplicated disk-cache/perf-monitor keys to avoid overrides.
Biome reports this block as duplicate keys; JSON keeps only the last occurrence, so earlier translations are ignored and lint fails. Please dedupe and keep a single block.web/src/i18n/locales/zh.json (1)
2775-2784:⚠️ Potential issue | 🟠 MajorRemove duplicate translation keys (“自动检测”, “确认解绑”).
Biome flags these as duplicates; the last entry wins, and earlier values are ignored. Please keep a single definition for each key.
🤖 Fix all issues with AI agents
In `@docs/BACKEND-FRONTEND-ALIGNMENT.md`:
- Around line 45-48: The documentation currently instructs replacing the
QuantumNous/AGPL copyright header with a short "OpenClaw API" note (the line
containing "将 QuantumNous/AGPL 版权头替换为简短「OpenClaw API」说明"), which violates the
project's rule to preserve all 'new-api' and 'QuantumNous' attributions; revert
or remove that sentence and update the section "注释与品牌" to explicitly state that
license headers and copyright notices for 'new-api' and 'QuantumNous' must be
retained unchanged, referencing the project's rules in .cursor/rules/project.mdc
and CLAUDE.md for wording consistency.
In `@scripts/deploy-remote.sh`:
- Around line 6-8: The current defaults hardcode a production server IP and
Docker image; replace these silent fallbacks by requiring the env vars and
failing fast: change the assignments for SERVER, COMPOSE_DIR and IMAGE to
enforce that DEPLOY_SERVER, DEPLOY_COMPOSE_DIR and DEPLOY_IMAGE must be set (use
shell parameter-expansion or explicit checks) and print a clear error and exit
non-zero if any are missing so the script cannot accidentally target a real
server.
In `@web/src/components/table/model-pricing/layout/header/PricingVendorIntro.jsx`:
- Around line 262-268: The title and description styles
(COMPONENT_STYLES.titleText and descriptionText) use hardcoded white, causing
white-on-white in light mode after createCoverStyle() switched to
var(--semi-color-bg-1); change those hardcoded colors to semantic CSS tokens
(e.g., var(--semi-color-text-0) for primary title and a slightly muted token
like var(--semi-color-text-2) or rgba token derived from semantic tokens for
description) so text contrasts with the new background, and update the same
hardcoded white usages later in the file (the other title/description blocks
around the 329-351 region) to the same semantic tokens.
In `@web/src/index.jsx`:
- Around line 36-42: The welcome message string was altered to "OpenClaw API"
contrary to the project's branding rules; revert the altered console/message
content in web/src/index.jsx back to the original NEWAPI / QuantumNous
attribution and URL, keeping the surrounding protective comment ("欢迎信息... Do not
remove...") intact; locate the conditional block that checks typeof window !==
'undefined' (the welcome message statements on lines near the current snippet)
and replace the changed literal/branding tokens with the original
NEWAPI/QuantumNous text so the exact required attribution and URL are restored.
In `@web/src/pages/Setting/Dashboard/SettingsAPIInfo.jsx`:
- Around line 419-423: The Empty component usage uses the non-existent static
Empty.PRESENTED_IMAGE_SIMPLE (AntD API); update the Empty in SettingsAPIInfo.jsx
to use Semi UI-compatible images by replacing
image={Empty.PRESENTED_IMAGE_SIMPLE} with either image={null} for a simple state
or import and pass a Semi illustration (from `@douyinfe/semi-illustrations`) as
image={MyIllustration}; ensure the change targets the Empty element and its
image prop so it renders correctly in Semi v2.69.1.
🟠 Major comments (17)
web/src/pages/Setting/Operation/SettingsGeneral.jsx-182-182 (1)
182-182:⚠️ Potential issue | 🟠 MajorComplete the
docs_linkdeprecation or restore the UI field.The backend still actively supports
docs_link—it's defined inGeneralSettingstruct and returned via the API (controller/misc.go). The frontend still uses it in multiple places (header bar inuseHeaderBar.js, home page inHome/index.jsx, and stored in localStorage). Removing only the UI form field fromSettingsGeneral.jsxwhile leaving the backend and other frontend consumers intact creates an inconsistency.Either: (1) complete the deprecation by removing
DocsLinkfrom the backend struct and API response, then remove all frontend usage, or (2) restore the UI field so admins can update the value. The hardcoded URL fallback in the comment is a good UX safeguard, but it doesn't resolve the underlying architectural mismatch.web/src/components/common/DocumentRenderer/index.jsx-24-26 (1)
24-26: 🛠️ Refactor suggestion | 🟠 MajorNon-standard statement interleaved between imports.
const { Title } = Typography;(line 25) is sandwiched betweenimportstatements (lines 22–23 and 26). While bundlers hoist imports so this technically works at runtime, it violates the conventional (and spec-intended) ordering where allimportdeclarations appear before other statements, making the code confusing to read.♻️ Suggested fix
import { Empty, Card, Spin, Typography } from '@douyinfe/semi-ui'; import { useTranslation } from 'react-i18next'; - -const { Title } = Typography; import MarkdownRenderer from '../markdown/MarkdownRenderer'; + +const { Title } = Typography;.github/workflows/deploy.yml-32-32 (1)
32-32:⚠️ Potential issue | 🟠 MajorHardcoded Docker Hub image tag — use a repository variable or secret.
chasebank2023/new-api:latestis hardcoded both here and inscripts/deploy-remote.sh. Extract to a workflow-levelenvvariable or GitHub repository variable to avoid drift and make it configurable.docs/DEPLOY-VIA-DOCKERHUB.md-42-44 (1)
42-44:⚠️ Potential issue | 🟠 MajorDefault credentials exposed in documentation.
The default MySQL password (
openclawapi2024) and session secret (openclawapi-session-secret-change-me) are shown inline. While they use${VAR:-default}syntax, readers often copy-paste verbatim. Add a prominent warning to change these values, or omit the defaults from the doc and reference a.env.examplefile instead..github/workflows/deploy.yml-8-45 (1)
8-45:⚠️ Potential issue | 🟠 MajorNo concurrency control — overlapping deploys possible.
Multiple pushes to
mainin quick succession can trigger parallel workflow runs, leading to race conditions during deployment. Add aconcurrencygroup to cancel or queue.Proposed fix: add concurrency at job or workflow level
on: push: branches: [ main ] workflow_dispatch: +concurrency: + group: deploy-production + cancel-in-progress: false + jobs: build-and-deploy:.github/workflows/deploy.yml-37-38 (1)
37-38:⚠️ Potential issue | 🟠 MajorHardcoded production IP and root SSH access.
The host IP (
101.36.104.77) is hardcoded and SSH access runs asroot. Store the host in a GitHub secret (e.g.,secrets.DEPLOY_HOST) and use a non-root deploy user with minimal privileges.Proposed fix
- name: SSH Remote Deploy uses: appleboy/ssh-action@v1.0.3 with: - host: 101.36.104.77 - username: root + host: ${{ secrets.DEPLOY_HOST }} + username: ${{ secrets.DEPLOY_USER }} key: ${{ secrets.SSH_PRIVATE_KEY }}makefile-1-4 (1)
1-4:⚠️ Potential issue | 🟠 MajorHardcoded production server IP and credentials in source control.
The Makefile contains a hardcoded public IP address (
101.36.104.77), deployment path, and Docker image name. Committing infrastructure details to a public repository exposes the server to targeted attacks and makes the Makefile non-portable for other contributors.Use environment variables with sensible defaults or a
.envfile (gitignored) instead:Proposed fix
-REMOTE_IP = 101.36.104.77 -REMOTE_DIR = /opt/openclawapi.ai -DOCKER_IMAGE = chasebank2023/new-api:latest +REMOTE_IP ?= $(error REMOTE_IP is not set) +REMOTE_DIR ?= /opt/openclawapi.ai +DOCKER_IMAGE ?= chasebank2023/new-api:latestweb/src/index.css-1020-1028 (1)
1020-1028:⚠️ Potential issue | 🟠 MajorOverly broad tag selector overrides all semantic colors.
The
[class*='semi-tag']:not(.channel-affinity-tag)selector will force brand-red on every Semi tag variant (green, blue, amber, etc.), breaking semantic color coding (e.g., success/warning/error indicators, the green discount tag on line 454 ofRechargeCard.jsx).Consider scoping this to only the tags you actually want branded, or remove the catch-all
[class*='semi-tag']rule.web/src/helpers/utils.jsx-1-1 (1)
1-1:⚠️ Potential issue | 🟠 MajorLicense/attribution header was replaced with a one-line comment.
The original AGPL/QuantumNous license header was removed and replaced with
/** OpenClaw API - Shared utils ... */. Based on learnings, references and attributions related to 'new-api' and 'QuantumNous' must not be modified or removed — this includes license headers and copyright notices.docs/OPENCLAW_DEPLOY.md-9-14 (1)
9-14:⚠️ Potential issue | 🟠 MajorDeployment doc describes source-level branding changes that conflict with project policy.
The modifications table lists changes to
common/constants.go(SystemName, Footer) andweb/src/helpers/utils.jsx(default system name). Per project rules, references and attributions related to 'new-api' and 'QuantumNous' must not be modified in source. Method 1 (environment variables) is the correct approach for customization without source modifications. Consider clarifying that the table describes runtime configuration overrides rather than source code edits, or note that these source changes are for a fork. Based on learnings from.cursor/rules/project.mdcandCLAUDE.md.web/index.html-10-13 (1)
10-13:⚠️ Potential issue | 🟠 MajorBranding policy violation:
new-api/QuantumNousreferences must not be replaced.The project rules explicitly state that all references, mentions, branding, metadata, or attributions related to
new-apiandQuantumNous— including HTML titles, meta tags, and descriptions — must not be modified, deleted, replaced, or removed. This change replaces the title,<meta name="generator">, and<meta name="description">with "OpenClaw API" branding, which violates that policy.Please revert the title, generator, and description meta tags to their original
new-api/QuantumNousvalues, or get explicit approval from the maintainers before proceeding.Based on learnings: "Project information including all references, mentions, branding, metadata, or attributions related to 'new-api' (project name) and 'QuantumNous' (organization/author) MUST NOT be modified, deleted, replaced, or removed under any circumstances. This includes README files, license headers, copyright notices, package metadata, HTML titles, meta tags, Go module paths, Docker image names, CI/CD references, comments, and documentation."
web/src/helpers/cookie.js-6-7 (1)
6-7:⚠️ Potential issue | 🟠 MajorHardcoded cookie domain breaks self-hosted and development environments.
COOKIE_DOMAINis hardcoded to'.openclawapi.ai'. Since this is an open-source project intended for self-hosting, cookies set with this domain will silently fail on any other domain (localhost, custom domains, etc.). Consider deriving the domain fromwindow.location.hostnameor making it configurable (e.g., via an environment variable or a config constant).web/src/context/User/index.jsx-48-61 (1)
48-61: 🛠️ Refactor suggestion | 🟠 MajorInconsistent cookie clearing: use the
setCookiehelper instead of rawdocument.cookie.Setting the cookie uses
setCookie(...)but clearing hardcodesdocument.cookiewith a literal domain. This duplicates the domain string and diverges from the helper's behavior. UsesetCookiewithmaxAge: 0for both consistency and maintainability.♻️ Proposed fix
if (state.user) { setCookie('oc_logged_in', '1'); } else { - // Clear the cookie on logout by setting max-age=0 - document.cookie = 'oc_logged_in=; path=/; max-age=0; domain=.openclawapi.ai'; - document.cookie = 'oc_logged_in=; path=/; max-age=0'; + setCookie('oc_logged_in', '', { maxAge: 0 }); + setCookie('oc_logged_in', '', { maxAge: 0, domain: '' }); }web/src/components/layout/headerbar/HeaderLogo.jsx-58-60 (1)
58-60:⚠️ Potential issue | 🟠 MajorLogo click navigates away from the SPA to a hardcoded external URL.
frontendHomeis hardcoded tohttps://openclawapi.aiand the anchor usestarget='_self', so clicking the header logo will navigate the user away from the current application in the same tab. This is a breaking UX change for any deployment not hosted at that exact domain — the user loses their current app state. Also,rel='noopener noreferrer'has no effect withtarget='_self'.If the intent is to link to the project homepage externally, use
target='_blank'. If the intent is SPA navigation to/, restore the<Link to="/">from react-router-dom.Proposed fix if external link is intended
- const frontendHome = 'https://openclawapi.ai'; + const frontendHome = 'https://openclawapi.ai'; return ( - <a href={frontendHome} className='group flex items-center gap-2' target='_self' rel='noopener noreferrer'> + <a href={frontendHome} className='group flex items-center gap-2' target='_blank' rel='noopener noreferrer'>Proposed fix if SPA home navigation is intended
Restore the
Linkimport and use it:+import { Link } from 'react-router-dom'; ... - const frontendHome = 'https://openclawapi.ai'; return ( - <a href={frontendHome} className='group flex items-center gap-2' target='_self' rel='noopener noreferrer'> + <Link to='/' className='group flex items-center gap-2'> ... - </a> + </Link>web/src/components/layout/Footer.jsx-49-81 (1)
49-81:⚠️ Potential issue | 🟠 MajorUse Chinese source keys for footer translations.
t('footer.*')relies on nested English keys; the project i18n convention expects Chinese source-string keys. Please switch these calls to Chinese keys and align locale files to the flat format.
As per coding guidelines: “web/src/**/*.{ts,tsx,json}: Frontend internationalization (i18n) usesi18next+react-i18next+i18next-browser-languagedetector. Translation files are flat JSON atweb/src/i18n/locales/{lang}.jsonwith Chinese source strings as keys. UseuseTranslation()hook and callt('中文key')in components.”web/src/i18n/locales/zh.json-2797-2815 (1)
2797-2815:⚠️ Potential issue | 🟠 MajorFlatten footer translations and keep Chinese source keys.
The nestedfooterobject introduces English keys, but locale files are expected to be flat with Chinese source-string keys. Please flatten these entries and update consumers to use Chinese keys.
As per coding guidelines: “web/src/i18n/**: Frontend i18n usesi18next+react-i18next+i18next-browser-languagedetectorwith translation files atweb/src/i18n/locales/{lang}.jsonusing flat JSON format with Chinese source strings as keys”.web/src/i18n/locales/en.json-2852-2870 (1)
2852-2870:⚠️ Potential issue | 🟠 MajorFlatten the new footer translations and use Chinese source-string keys.
The nestedfooterobject introduces English keys, but the i18n files are expected to be flat with Chinese source strings as keys. Please flatten these entries (e.g., “页脚产品”: “Product”) and adjust consumers accordingly.
As per coding guidelines: “web/src/i18n/**: Frontend i18n usesi18next+react-i18next+i18next-browser-languagedetectorwith translation files atweb/src/i18n/locales/{lang}.jsonusing flat JSON format with Chinese source strings as keys”.
🟡 Minor comments (8)
Dockerfile-9-11 (1)
9-11:⚠️ Potential issue | 🟡 Minor
NODE_OPTIONS=--max-old-space-size=2048is a V8 flag and has no effect under Bun.Bun uses JavaScriptCore, not V8, so
--max-old-space-sizeis not recognized. ThisENVline will be ignored. If you need to constrain memory during the build, use Docker's--memoryflag or--memory-reservationinstead.docker-compose.yml-19-22 (1)
19-22:⚠️ Potential issue | 🟡 MinorSwitching to local build changes the deployment experience for existing users.
Previously,
docker-compose up -dpulled a pre-built image (calciumion/new-api:latest), making it a quick start. Now it triggers a full local build, which is significantly slower and requires the complete source tree. This could surprise users following the "Quick Start" guide on line 4.Consider either:
- Keeping the remote image reference as the default for end-user deployment (perhaps pointing to the new
chasebank2023/new-api:latestimage from the CI pipeline), and providing this local-build compose file separately (e.g.,docker-compose.dev.yml).- Or at minimum, updating the Quick Start comment to note the build requirement and expected build time.
docs/DEPLOY-VIA-DOCKERHUB.md-8-8 (1)
8-8:⚠️ Potential issue | 🟡 MinorHardcoded personal machine path in documentation.
/Users/chasebank2017/Downloads/new-apiis a developer-specific path. Replace with a generic placeholder like/path/to/new-apiso the guide is usable by anyone.scripts/deploy-remote.sh-11-15 (1)
11-15:⚠️ Potential issue | 🟡 MinorUnquoted variables in SSH command may break with special characters.
$COMPOSE_DIRand$IMAGEare interpolated unquoted inside the SSH command string. If they ever contain spaces or shell metacharacters, the command will break or behave unexpectedly. Quote them properly.Proposed fix
-ssh "$SERVER" "cd $COMPOSE_DIR && \ - sed -i 's|image:.*new-api.*|image: $IMAGE|g' docker-compose.yml && \ +ssh "$SERVER" "cd '$COMPOSE_DIR' && \ + sed -i 's|image:.*new-api.*|image: $IMAGE|g' docker-compose.yml && \makefile-7-11 (1)
7-11:⚠️ Potential issue | 🟡 MinorSSH as root and fragile
sedreplacement.Two concerns with
DEPLOY_CMD:
- SSH as root — Consider using a non-root deploy user with limited sudo permissions for security.
- Fragile sed pattern —
sed -i 's|image:.*new-api.*|...|g'will match any line containing bothimage:andnew-api, which could unintentionally modify comments or other services. A more targeted pattern would be safer.web/src/components/layout/headerbar/LanguageSelector.jsx-9-12 (1)
9-12:⚠️ Potential issue | 🟡 MinorHeader toggle only supports zh/en but settings offers 6 languages.
If a user selects French, Russian, Japanese, or Vietnamese via
PreferencesSettings, this toggle will cycle them tozh(sincecurrentLang !== 'zh'→nextLang = 'zh'), with no way to return to their chosen language from the header. Consider either:
- Cycling through all supported languages, or
- Hiding this toggle when the active language isn't
zh/en, or- Limiting
PreferencesSettingsto the same two languages.web/src/pages/Docs/index.jsx-32-34 (1)
32-34:⚠️ Potential issue | 🟡 MinorPossibly wrong i18n key for the docs page description.
t('页脚品牌描述(与官网一致)')looks like a footer branding description key, not a docs page subtitle. This would render footer copy as the docs page description. Was a dedicated key intended here?web/src/helpers/cookie.js-18-24 (1)
18-24:⚠️ Potential issue | 🟡 MinorMissing
SecureandSameSiteattributes on cross-subdomain cookies.For cookies shared across subdomains (as described in the file comment), you should set
SameSite=None; Secure(or at minimumSameSite=Lax). Without these, modern browsers may silently drop or restrict the cookies in cross-site/cross-subdomain contexts.🔒 Proposed fix
export function setCookie(name, value, options = {}) { if (typeof document === 'undefined') return; - const { domain = COOKIE_DOMAIN, maxAge = MAX_AGE_YEAR, path = '/' } = options; + const { domain = COOKIE_DOMAIN, maxAge = MAX_AGE_YEAR, path = '/', secure = true, sameSite = 'Lax' } = options; const encoded = encodeURIComponent(value); const parts = [`${name}=${encoded}`, `path=${path}`, `max-age=${maxAge}`]; if (domain) parts.push(`domain=${domain}`); + if (secure) parts.push('Secure'); + if (sameSite) parts.push(`SameSite=${sameSite}`); document.cookie = parts.join('; '); }
🧹 Nitpick comments (22)
web/src/components/settings/SystemSetting.jsx (1)
522-527: Silenced OIDC fetch error may hinder debugging.Removing
console.error(err)means the actual error details (network failure, malformed response, CORS issue, etc.) are lost. The user-facing message is generic. Consider keeping a minimal log or structured error report for operators diagnosing OIDC configuration issues.💡 Suggested improvement
} catch (err) { + console.warn('[OIDC] Failed to fetch well-known config:', err.message || err); showError( t('获取 OIDC 配置失败,请检查网络状况和 Well-Known URL 是否正确'), ); return; }web/src/pages/Setting/Operation/SettingsHeaderNavModules.jsx (2)
229-232: Redundant ternary — themodule.key === 'pricing'guard makes the else-branch dead code.Line 229 already restricts this block to
module.key === 'pricing', so the ternary on line 230 will always evaluate the truthy branch. The: headerNavModules[module.key]path is unreachable. Simplify to just checkheaderNavModules.pricing?.enabled.♻️ Suggested simplification
- {module.key === 'pricing' && - (module.key === 'pricing' - ? headerNavModules[module.key]?.enabled - : headerNavModules[module.key]) && ( + {module.key === 'pricing' && + headerNavModules.pricing?.enabled && (
122-146: Old config keys (home, docs, about) are silently carried into state.When a previously stored
HeaderNavModulesJSON is parsed at line 136, any legacy keys (home,docs,about) are loaded intoheaderNavModulesstate as-is. They won't cause a runtime error since there's no UI for them, but they'll be persisted back on the next save, creating unnecessary clutter. Consider stripping unknown keys during initialization.♻️ Optional: normalize parsed config
// 处理向后兼容性:如果pricing是boolean,转换为对象格式 if (typeof modules.pricing === 'boolean') { modules.pricing = { enabled: modules.pricing, requireAuth: false, }; } - setHeaderNavModules(modules); + // Only keep known module keys + setHeaderNavModules({ + console: modules.console ?? true, + pricing: modules.pricing ?? { enabled: true, requireAuth: false }, + });web/src/hooks/common/useNavigation.js (1)
22-22: Remove unuseddocsLinkparameter from function signature.The
docsLinkparameter is accepted in the function signature but never referenced in the function body—the docs link is hardcoded to/docs. Callers still pass this parameter (found one call site inweb/src/components/layout/headerbar/index.jsxline 48), making it dead code in the signature.Remove the parameter and update the call site.
♻️ Suggested changes
In
web/src/hooks/common/useNavigation.jsline 22:-export const useNavigation = (t, docsLink, headerNavModules) => { +export const useNavigation = (t, headerNavModules) => {In
web/src/components/layout/headerbar/index.jsxline 48:- const { mainNavLinks } = useNavigation(t, docsLink, headerNavModules); + const { mainNavLinks } = useNavigation(t, headerNavModules);router/web-router.go (1)
20-24: Avoid hardcoding a specific domain in code comments.The comment on line 20 references
api.openclawapi.ai, which will become stale if the domain changes. Use a generic description instead.Suggested comment
- // 显式处理根路径,确保 api.openclawapi.ai/ 可访问 + // 显式处理根路径,确保首页可正常访问并禁用缓存web/src/pages/Setting/Dashboard/SettingsAnnouncements.jsx (1)
459-462: Consider removing empty callback stubs.
onSelectandonSelectAllare now no-ops. They can be removed from therowSelectionobject entirely since Semi UI doesn't require them.♻️ Suggested cleanup
const rowSelection = { selectedRowKeys, onChange: (selectedRowKeys, selectedRows) => { setSelectedRowKeys(selectedRowKeys); }, - onSelect: (record, selected, selectedRows) => { - }, - onSelectAll: (selected, selectedRows) => { - }, getCheckboxProps: (record) => ({ disabled: false, name: record.id, }), };web/src/pages/Setting/Dashboard/SettingsFAQ.jsx (1)
372-375: Same as SettingsAnnouncements: empty callback stubs can be removed.These no-op
onSelect/onSelectAllhandlers are unnecessary.web/src/components/settings/OtherSetting.jsx (2)
181-197: Dead code:submitOptionis no longer reachable.The HomePageContent UI that invoked
submitOptionwas removed (Line 438 comment), but the handler and related state (HomePageContentininputsat Line 50 andloadingInputat Line 81) remain. Consider removing them to avoid confusion.
173-175: Inconsistent i18n: hardcoded Chinese strings inshowSuccess/showError.
submitLogo,submitOption,submitAbout, andsubmitFooter(Lines 173–175, 188–190, 204–205, 215–217) use hardcoded Chinese strings, whilesubmitNotice,submitSystemName, etc. wrap messages int(). Wrap all user-facing strings int()for consistency.web/src/components/table/model-pricing/layout/header/PricingVendorIntro.jsx (1)
318-318: UnusedprimaryDarkerChannelparameter.
renderHeaderCardstill acceptsprimaryDarkerChannelin its destructured props (Line 318), but it's no longer used sincecreateCoverStyletakes no arguments. Remove it to avoid confusion — callers at Lines 379 and 402 also pass it unnecessarily.web/src/i18n/locales/ru.json (1)
134-135: Orphaned translation key at line 134.The key
"New API项目仓库地址:"(line 134) appears to still be present, but per the AI summary, the corresponding UI text was removed from the About page. This key may now be unused. Consider removing it to keep locale files clean, or verify it's still referenced elsewhere.#!/bin/bash # Check if the old key is still referenced anywhere in the codebase rg -n "New API项目仓库地址" --type-add 'jsx:*.jsx' --type-add 'tsx:*.tsx' --type=jsx --type=tsx --type=ts --type=jsweb/src/components/dashboard/DashboardHeader.jsx (1)
55-55: Redundanthover:!bg-[var(--oc-accent)]— same value as the base background.The hover background color is identical to the base background. Since the hover effect is achieved via
hover:!opacity-90, thehover:!bg-[var(--oc-accent)]class is unnecessary.Simplify
- className={`!bg-[var(--oc-accent)] hover:!bg-[var(--oc-accent)] hover:!opacity-90 ${ICON_BUTTON_CLASS}`} + className={`!bg-[var(--oc-accent)] hover:!opacity-90 ${ICON_BUTTON_CLASS}`}web/src/index.css (3)
1062-1070: Attribute-substring selectors onstyleare fragile.Selectors like
.semi-tag[style*="background"][style*="red"]match inline style strings, which are sensitive to whitespace, property order, and value formatting. A minor change in how React serializes thestyleprop (or a library update) will silently break these rules.Prefer assigning explicit CSS classes instead of matching against inline style substrings.
4-5: Stylelint: use@importstring notation instead ofurl().Per Stylelint
import-notationrule, the@import url(...)should be@import '...'.Proposed fix
-@import url('https://api.fontshare.com/v2/css?f[]=satoshi@400,500,700&display=swap'); +@import 'https://api.fontshare.com/v2/css?f[]=satoshi@400,500,700&display=swap';
80-86: Stylelint: minor value-casing and quote issues.Static analysis flags:
optimizeLegibilityshould be lowercase (optimizelegibility), and'Satoshi'should be unquoted perfont-family-name-quotes. These are low-priority but will fail linting.Proposed fix
html { font-size: 16px; - text-rendering: optimizeLegibility; + text-rendering: optimizelegibility; } body { - font-family: 'Satoshi', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', - 'Microsoft YaHei', sans-serif; + font-family: Satoshi, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', + 'Microsoft YaHei', sans-serif;web/src/pages/Home/index.jsx (1)
131-132: Empty catch block silently swallows errors.The
console.errorwas removed but no alternative error handling was added. Consider at minimum logging to a monitoring service, or adding a comment explaining why the error is intentionally ignored.web/src/components/dashboard/UptimePanel.jsx (1)
42-42:ILLUSTRATION_SIZEprop is now unused.This prop is still destructured but no longer referenced after removing the custom illustrations. Consider removing it from the props to keep the interface clean.
web/src/components/dashboard/ApiInfoPanel.jsx (1)
31-31:ILLUSTRATION_SIZEprop is now unused.Same as in
UptimePanel.jsx— this destructured prop is no longer referenced after removing custom illustrations.web/src/App.jsx (1)
52-52:DocsPageis eagerly imported but wrapped inSuspense— inconsistent with other routes.
DocsPageis directly imported (notlazy()), so theSuspensewrapper on lines 191-193 serves no purpose. Either lazy-load it to match other routes' pattern, or remove theSuspensewrapper for clarity.♻️ Option A: Make it lazy (consistent with other routes)
-import DocsPage from './pages/Docs'; +const DocsPage = lazy(() => import('./pages/Docs'));Also applies to: 188-195
web/src/i18n/i18n.js (1)
22-22: Dropping support for fr/ja/ru/vi is a significant scope reduction.If users have previously selected one of these languages (stored as
localein localStorage),supportedLngswill reject it and fall back tozh. This is correct behavior given thefallbackLngsetting, but existing users on those locales will see an abrupt language switch with no explanation. Consider whether a migration note or UI toast is warranted.web/src/context/Theme/index.jsx (2)
27-37: Users migrating from "auto" theme will silently switch to dark.Previously stored
"auto"values in localStorage will be ignored and default to"dark". This is likely intentional but worth noting — users who preferred system-following behavior will see a one-time theme change without explanation.
58-68: Duplicate persistence:setThemewrites to storage, thenuseEffectwrites again.The
useEffecton[theme](lines 50–55) already persists tolocalStorageand cookie wheneverthemechanges. The manual writes insetTheme(lines 63–64) are redundant since_setTheme(value)triggers the effect.♻️ Remove duplicate writes from setTheme
const setTheme = useCallback((newTheme) => { const value = newTheme === 'light' || newTheme === 'dark' ? newTheme : theme === 'dark' ? 'light' : 'dark'; _setTheme(value); - try { - localStorage.setItem(STORAGE_KEY, value); - setCookie('oc_theme', value); - } catch (e) { - // ignore - } }, [theme]);
| ### 5. 注释与品牌 | ||
|
|
||
| - 已修改的模块中,将 QuantumNous/AGPL 版权头替换为简短「OpenClaw API」说明,避免露出上游项目信息。 | ||
|
|
There was a problem hiding this comment.
Documentation endorses removing required license attributions.
Line 47 states: "将 QuantumNous/AGPL 版权头替换为简短「OpenClaw API」说明,避免露出上游项目信息." This directly contradicts the project rule that all references, mentions, and attributions related to 'new-api' and 'QuantumNous' — including license headers and copyright notices — must not be modified, deleted, or removed. This guidance should be revised or removed. Based on learnings from .cursor/rules/project.mdc and CLAUDE.md.
🤖 Prompt for AI Agents
In `@docs/BACKEND-FRONTEND-ALIGNMENT.md` around lines 45 - 48, The documentation
currently instructs replacing the QuantumNous/AGPL copyright header with a short
"OpenClaw API" note (the line containing "将 QuantumNous/AGPL 版权头替换为简短「OpenClaw
API」说明"), which violates the project's rule to preserve all 'new-api' and
'QuantumNous' attributions; revert or remove that sentence and update the
section "注释与品牌" to explicitly state that license headers and copyright notices
for 'new-api' and 'QuantumNous' must be retained unchanged, referencing the
project's rules in .cursor/rules/project.mdc and CLAUDE.md for wording
consistency.
| SERVER="${DEPLOY_SERVER:-root@101.36.104.77}" | ||
| COMPOSE_DIR="${DEPLOY_COMPOSE_DIR:-/opt/openclawapi.ai}" | ||
| IMAGE="${DEPLOY_IMAGE:-chasebank2023/new-api:latest}" |
There was a problem hiding this comment.
Hardcoded production IP and Docker Hub username in defaults.
The script defaults to a specific server IP (101.36.104.77) and image (chasebank2023/new-api:latest). These should not have production values as fallbacks — a missing env var should fail explicitly rather than silently targeting a real server.
Proposed fix: fail fast if env vars are unset
-SERVER="${DEPLOY_SERVER:-root@101.36.104.77}"
-COMPOSE_DIR="${DEPLOY_COMPOSE_DIR:-/opt/openclawapi.ai}"
-IMAGE="${DEPLOY_IMAGE:-chasebank2023/new-api:latest}"
+SERVER="${DEPLOY_SERVER:?DEPLOY_SERVER is required}"
+COMPOSE_DIR="${DEPLOY_COMPOSE_DIR:?DEPLOY_COMPOSE_DIR is required}"
+IMAGE="${DEPLOY_IMAGE:?DEPLOY_IMAGE is required}"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| SERVER="${DEPLOY_SERVER:-root@101.36.104.77}" | |
| COMPOSE_DIR="${DEPLOY_COMPOSE_DIR:-/opt/openclawapi.ai}" | |
| IMAGE="${DEPLOY_IMAGE:-chasebank2023/new-api:latest}" | |
| SERVER="${DEPLOY_SERVER:?DEPLOY_SERVER is required}" | |
| COMPOSE_DIR="${DEPLOY_COMPOSE_DIR:?DEPLOY_COMPOSE_DIR is required}" | |
| IMAGE="${DEPLOY_IMAGE:?DEPLOY_IMAGE is required}" |
🤖 Prompt for AI Agents
In `@scripts/deploy-remote.sh` around lines 6 - 8, The current defaults hardcode a
production server IP and Docker image; replace these silent fallbacks by
requiring the env vars and failing fast: change the assignments for SERVER,
COMPOSE_DIR and IMAGE to enforce that DEPLOY_SERVER, DEPLOY_COMPOSE_DIR and
DEPLOY_IMAGE must be set (use shell parameter-expansion or explicit checks) and
print a clear error and exit non-zero if any are missing so the script cannot
accidentally target a real server.
| const createCoverStyle = useCallback( | ||
| (primaryColor) => ({ | ||
| '--palette-primary-darkerChannel': primaryColor, | ||
| backgroundImage: `linear-gradient(0deg, rgba(var(--palette-primary-darkerChannel) / 80%), rgba(var(--palette-primary-darkerChannel) / 80%)), url('/cover-4.webp')`, | ||
| backgroundSize: 'cover', | ||
| backgroundPosition: 'center', | ||
| backgroundRepeat: 'no-repeat', | ||
| () => ({ | ||
| backgroundColor: 'var(--semi-color-bg-1)', | ||
| borderBottom: '1px solid var(--semi-color-border)', | ||
| }), | ||
| [], | ||
| ); |
There was a problem hiding this comment.
White text on theme background — unreadable in light mode.
createCoverStyle() now uses var(--semi-color-bg-1) (a light/neutral background), but the title and description still use hardcoded white text (COMPONENT_STYLES.titleText = { color: 'white' } and descriptionText = { color: 'rgba(255,255,255,0.9)' }). In light mode this will be white-on-white — invisible.
Update the text styles to use semantic color tokens consistent with the new background:
Proposed fix
const COMPONENT_STYLES = {
tag: {
- backgroundColor: 'rgba(255,255,255,0.95)',
- color: '#1f2937',
- border: '1px solid rgba(255,255,255,0.8)',
+ backgroundColor: 'var(--semi-color-bg-2)',
+ color: 'var(--semi-color-text-0)',
+ border: '1px solid var(--semi-color-border)',
fontWeight: '500',
},
avatarContainer:
'w-16 h-16 rounded-2xl bg-white/90 shadow-md backdrop-blur-sm flex items-center justify-center',
- titleText: { color: 'white' },
- descriptionText: { color: 'rgba(255,255,255,0.9)' },
+ titleText: { color: 'var(--semi-color-text-0)' },
+ descriptionText: { color: 'var(--semi-color-text-2)' },
};Also applies to: 329-351
🤖 Prompt for AI Agents
In `@web/src/components/table/model-pricing/layout/header/PricingVendorIntro.jsx`
around lines 262 - 268, The title and description styles
(COMPONENT_STYLES.titleText and descriptionText) use hardcoded white, causing
white-on-white in light mode after createCoverStyle() switched to
var(--semi-color-bg-1); change those hardcoded colors to semantic CSS tokens
(e.g., var(--semi-color-text-0) for primary title and a slightly muted token
like var(--semi-color-text-2) or rgba token derived from semantic tokens for
description) so text contrasts with the new background, and update the same
hardcoded white usages later in the file (the other title/description blocks
around the 329-351 region) to the same semantic tokens.
| // 欢迎信息(二次开发者未经允许不准将此移除) | ||
| // Welcome message (Do not remove this without permission from the original developer) | ||
| if (typeof window !== 'undefined') { | ||
| console.log( | ||
| '%cWE ❤ NEWAPI%c Github: https://github.com/QuantumNous/new-api', | ||
| '%cOpenClaw API%c https://openclawapi.ai', | ||
| 'color: #10b981; font-weight: bold; font-size: 24px;', | ||
| 'color: inherit; font-size: 14px;', | ||
| ); |
There was a problem hiding this comment.
Welcome message branding changed despite explicit prohibition.
Lines 36–37 state: "二次开发者未经允许不准将此移除 / Do not remove this without permission from the original developer." The message content was changed from the original NEWAPI/QuantumNous branding to OpenClaw. Per project rules, attributions related to 'new-api' and 'QuantumNous' must not be modified or removed. Based on learnings from .cursor/rules/project.mdc and CLAUDE.md.
🤖 Prompt for AI Agents
In `@web/src/index.jsx` around lines 36 - 42, The welcome message string was
altered to "OpenClaw API" contrary to the project's branding rules; revert the
altered console/message content in web/src/index.jsx back to the original NEWAPI
/ QuantumNous attribution and URL, keeping the surrounding protective comment
("欢迎信息... Do not remove...") intact; locate the conditional block that checks
typeof window !== 'undefined' (the welcome message statements on lines near the
current snippet) and replace the changed literal/branding tokens with the
original NEWAPI/QuantumNous text so the exact required attribution and URL are
restored.
| <Empty | ||
| image={ | ||
| <IllustrationNoResult style={{ width: 150, height: 150 }} /> | ||
| } | ||
| darkModeImage={ | ||
| <IllustrationNoResultDark style={{ width: 150, height: 150 }} /> | ||
| } | ||
| image={Empty.PRESENTED_IMAGE_SIMPLE} | ||
| description={t('暂无API信息')} | ||
| style={{ padding: 30 }} | ||
| /> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find package.json to check Semi UI version
find . -name "package.json" -type f | head -5Repository: QuantumNous/new-api
Length of output: 105
🏁 Script executed:
# Check the web directory package.json for Semi UI version
cat web/package.json | grep -A 2 -B 2 "semi-ui"Repository: QuantumNous/new-api
Length of output: 229
🏁 Script executed:
# Read the file to understand context
cat -n web/src/pages/Setting/Dashboard/SettingsAPIInfo.jsx | sed -n '1,50p'Repository: QuantumNous/new-api
Length of output: 2092
🏁 Script executed:
# Check imports in the file
cat -n web/src/pages/Setting/Dashboard/SettingsAPIInfo.jsx | grep -i "import\|from" | head -20Repository: QuantumNous/new-api
Length of output: 372
🏁 Script executed:
# Check if there's a node_modules or type definitions for semi-ui
find . -path "*node_modules/@douyinfe/semi-ui*" -name "*.d.ts" -type f 2>/dev/null | grep -i empty | head -10Repository: QuantumNous/new-api
Length of output: 45
🏁 Script executed:
# Search for usage of Empty component in the codebase to see other examples
rg "Empty\." web/src --type jsx --type js -A 2 -B 2 | head -50Repository: QuantumNous/new-api
Length of output: 90
🏁 Script executed:
# Check the specific lines 419-423 in context
cat -n web/src/pages/Setting/Dashboard/SettingsAPIInfo.jsx | sed -n '415,425p'Repository: QuantumNous/new-api
Length of output: 436
🌐 Web query:
@douyinfe/semi-ui Empty component PRESENTED_IMAGE_SIMPLE v2.69.1
💡 Result:
In @douyinfe/semi-ui v2.69.1, the Empty component does not provide AntD-style static presets like Empty.PRESENTED_IMAGE_SIMPLE. Semi’s Empty only lets you control the illustration via the image prop (and darkModeImage for dark mode), typically by importing an illustration from @douyinfe/semi-illustrations, or by passing your own custom ReactNode (or by not using an image at all). [1]
If you want a “simple” empty style in Semi, you generally do one of these:
import { Empty } from '@douyinfe/semi-ui';
// option A: no image (simple)
<Empty image={null} title="No data" />
// option B: pick an illustration yourself
import { IllustrationIdle } from '@douyinfe/semi-illustrations';
<Empty image={<IllustrationIdle />} title="No data" />Semi’s v2.69.1 changelog entry also doesn’t mention adding any PRESENTED_IMAGE_* preset API for Empty. [2]
Sources
[1] Semi Design docs – Empty component API/usage: https://semi.design/en-US/show/empty
[2] Semi Design changelog – v2.69.1 entry: https://semi.design/zh-CN/ecosystem/changelog
Empty.PRESENTED_IMAGE_SIMPLE does not exist in Semi UI v2.69.1 and will render as undefined.
Empty.PRESENTED_IMAGE_SIMPLE is an Ant Design API. Semi UI's Empty component does not provide this static property. To display a simple empty state, use image={null} or import an illustration from @douyinfe/semi-illustrations.
🤖 Prompt for AI Agents
In `@web/src/pages/Setting/Dashboard/SettingsAPIInfo.jsx` around lines 419 - 423,
The Empty component usage uses the non-existent static
Empty.PRESENTED_IMAGE_SIMPLE (AntD API); update the Empty in SettingsAPIInfo.jsx
to use Semi UI-compatible images by replacing
image={Empty.PRESENTED_IMAGE_SIMPLE} with either image={null} for a simple state
or import and pass a Semi illustration (from `@douyinfe/semi-illustrations`) as
image={MyIllustration}; ensure the change targets the Empty element and its
image prop so it renders correctly in Semi v2.69.1.
Summary by CodeRabbit
New Features
Improvements