-
Notifications
You must be signed in to change notification settings - Fork 625
feat: support rebrand #778
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Add support for welcome page title and setup description customization - Extend updateI18nFiles() to handle both about.json and welcome.json files - Add updateAllI18nDeepChatReferences() function to replace DeepChat references in: - mcp.json (MCP service descriptions) - settings.json (UI text and descriptions) - update.json (update notifications) - index.ts (search disclaimer) - Make brand assets (icons/logos) completely optional with friendly info messages - Support all 9 languages: en-US, zh-CN, zh-TW, zh-HK, ja-JP, ko-KR, ru-RU, fr-FR, fa-IR - Improve error handling and user feedback 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
…e support - Add HTML title replacement functionality for all renderer HTML files - Update shell page title to maintain "App Name - Shell" format - Preserve floating button functional title unchanged - Integrate HTML title updates into main rebrand workflow - Add proper error handling and success feedback 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
WalkthroughAdds a rebranding system: a configurable template and example brand JSON, a Node.js script to apply branding across project files, a placeholder for brand assets, and a Chinese rebranding guide. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Dev as Developer
participant CLI as node scripts/rebrand.js
participant FS as File System
participant Cfg as brand-config.*.json
participant Pkg as package.json
participant EB as electron-builder*.yml
participant Main as src/main/index.ts
participant Upg as .../upgradePresenter*
participant I18N as i18n/.../*.json
participant MCP as .../mcpConfHelper.ts
participant HTML as .../index.html
Dev->>CLI: Execute rebrand script
CLI->>Cfg: Read brand-config.template.json
alt Config loaded
CLI->>Pkg: Update name, description, author
CLI->>EB: Update appId, productName, executableName, URLs
CLI->>Main: Set app user model ID
CLI->>Upg: Set update baseUrl (if provided)
CLI->>I18N: Update titles, descriptions, website text
CLI->>MCP: Update server description suffixes
CLI->>HTML: Update page titles
CLI->>FS: Copy icons/logos from scripts/brand-assets/*
CLI-->>Dev: Log success and next steps
else Config missing/invalid
CLI-->>Dev: Warn and exit with error
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 10
🧹 Nitpick comments (5)
scripts/brand-assets/.gitkeep (1)
1-15: Consider moving guidance to README.md and keep .gitkeep emptyIt’s unconventional to put user-facing docs into a .gitkeep. Suggest:
- Create scripts/brand-assets/README.md with this guidance (bilingual if possible).
- Keep .gitkeep empty to preserve the directory in Git.
brand-config.example-banana.json (1)
16-38: Include welcome screen i18n in the example to showcase new capabilityTemplate supports welcomeTitle and welcomeSetupDescription, but the example lacks them. Adding sample values helps users verify the new welcome page customization end‑to‑end.
"i18n": { "appTitle": { @@ }, "appDescription": { @@ }, + "welcomeTitle": { + "en-US": "Welcome to BananaAI", + "zh-CN": "欢迎使用 BananaAI", + "zh-TW": "歡迎使用 BananaAI", + "zh-HK": "歡迎使用 BananaAI", + "ja-JP": "BananaAI へようこそ", + "ko-KR": "BananaAI에 오신 것을 환영합니다", + "ru-RU": "Добро пожаловать в BananaAI", + "fr-FR": "Bienvenue sur BananaAI", + "fa-IR": "به BananaAI خوش آمدید" + }, + "welcomeSetupDescription": { + "en-US": "Let's start setting up BananaAI", + "zh-CN": "让我们开始设置 BananaAI", + "zh-TW": "讓我們開始設定 BananaAI", + "zh-HK": "讓我們開始設置 BananaAI", + "ja-JP": "BananaAI の設定を始めましょう", + "ko-KR": "BananaAI 설정을 시작합시다", + "ru-RU": "Начнем настройку BananaAI", + "fr-FR": "Commençons la configuration de BananaAI", + "fa-IR": "بیایید تنظیم BananaAI را شروع کنیم" + } },brand-config.template.json (2)
50-71: Consider using productName rather than “MyApp” in welcome defaultsDefaults like “Welcome to MyApp” can feel off-brand if users forget to change them. Using “DeepChat” or adding a comment hint reduces accidental leakage into branded builds.
- "welcomeTitle": { - "en-US": "Welcome to MyApp", - "zh-CN": "欢迎使用 MyApp", + "welcomeTitle": { + "en-US": "Welcome to DeepChat", // Replace with your productName + "zh-CN": "欢迎使用 DeepChat", // 替换为你的产品名 @@ - "welcomeSetupDescription": { - "en-US": "Let's start setting up MyApp", - "zh-CN": "让我们开始设置 MyApp", + "welcomeSetupDescription": { + "en-US": "Let's start setting up DeepChat", // Replace with your productName + "zh-CN": "让我们开始设置 DeepChat", // 替换为你的产品名
14-15: Keep a trailing slash in update.baseUrlYour defaults include a trailing slash — good. Add a short inline comment to preserve this behavior for custom values.
"update": { - "baseUrl": "https://cdn.deepchatai.cn/upgrade/" + "baseUrl": "https://cdn.deepchatai.cn/upgrade/" // Keep trailing slash },scripts/rebrand.js (1)
468-499: Add lint step and translate end-of-run instructions into EnglishVerified that running
pnpm dlx oxlint scripts/rebrand.jscompletes with no errors.Apply the following changes at the end of
scripts/rebrand.js:
- Replace the Chinese checklist logs with English text.
- Insert a lint invocation (
pnpm dlx oxlint scripts/rebrand.js) as step 2.Suggested diff:
log('') - log('📋 接下来的步骤:') - log('1. 检查修改的文件是否符合预期') - log('2. 提交代码到您的仓库') - log('3. 构建应用: pnpm run build:mac:arm64 (或其他平台)') + log('📋 Next steps:') + log('1. Review and commit the changes') + log('2. Run lint: pnpm dlx oxlint scripts/rebrand.js') + log('3. Build your app: pnpm run build:mac:arm64 (or other targets)')This aligns with the project’s guideline to use OxLint for JS/TS and to keep all logs and comments in English.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (5)
brand-config.example-banana.json(1 hunks)brand-config.template.json(1 hunks)docs/rebrand-guide.md(1 hunks)scripts/brand-assets/.gitkeep(1 hunks)scripts/rebrand.js(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Use English for logs and comments
Files:
scripts/rebrand.js
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)
**/*.{js,jsx,ts,tsx}: 使用 OxLint 进行代码检查
Log和注释使用英文书写
Files:
scripts/rebrand.js
🪛 LanguageTool
docs/rebrand-guide.md
[uncategorized] ~104-~104: "必需"后面不应接动词,您的意思是""必须""吗?
Context: ...ux:x64 # Linux x64 ``` ## 配置说明 ### 必需配置 - app.name - 应用包名,用于 package.json - ...
(ZH2)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build-check (x64)
🔇 Additional comments (1)
brand-config.example-banana.json (1)
14-15: Trailing slash confirmed – no changes neededI ran the provided check and verified that
update.baseUrlinbrand-config.example-banana.jsonends with/, so the existing configuration already meets the requirement.• File: brand-config.example-banana.json
• Field:update.baseUrl
• Value:https://updates.banana.co/(ends with/)All good here, so we can resolve this comment.
| ### 1. 准备品牌资源 | ||
|
|
||
| 将以下文件放入 `scripts/brand-assets/` 目录: | ||
|
|
||
| - `icon.png` - 应用图标 (512x512 PNG) | ||
| - `icon.ico` - Windows 图标文件 | ||
| - `logo.png` - 亮色主题 Logo (建议 256x256) | ||
| - `logo-dark.png` - 暗色主题 Logo (建议 256x256) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Assets are optional — reflect this in the workflow section
Step 1 implies assets are strictly required. Make this explicitly optional to avoid blocking text-only rebrands.
-### 1. 准备品牌资源
+### 1.(可选)准备品牌资源
@@
-将以下文件放入 `scripts/brand-assets/` 目录:
+如需自定义图标/Logo,请将以下文件放入 `scripts/brand-assets/` 目录(均为可选):📝 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.
| ### 1. 准备品牌资源 | |
| 将以下文件放入 `scripts/brand-assets/` 目录: | |
| - `icon.png` - 应用图标 (512x512 PNG) | |
| - `icon.ico` - Windows 图标文件 | |
| - `logo.png` - 亮色主题 Logo (建议 256x256) | |
| - `logo-dark.png` - 暗色主题 Logo (建议 256x256) | |
| ### 1.(可选)准备品牌资源 | |
| 如需自定义图标/Logo,请将以下文件放入 `scripts/brand-assets/` 目录(均为可选): | |
| - `icon.png` - 应用图标 (512x512 PNG) | |
| - `icon.ico` - Windows 图标文件 | |
| - `logo.png` - 亮色主题 Logo (建议 256x256) | |
| - `logo-dark.png` - 暗色主题 Logo (建议 256x256) |
🤖 Prompt for AI Agents
In docs/rebrand-guide.md around lines 15 to 23, Step 1 currently makes brand
assets sound mandatory; update the wording and workflow to mark these assets as
optional (e.g., add “(optional)” to the heading and each asset bullet), and add
a short note explaining that if no assets are provided the rebrand process will
proceed with text-only defaults or fallback placeholders; also adjust any
subsequent steps or scripts referenced in the guide to mention they should
handle missing assets gracefully or use defaults.
| 这个脚本会自动替换以下文件中的品牌信息: | ||
|
|
||
| - `package.json` - 包配置 | ||
| - `electron-builder.yml` - 构建配置 | ||
| - `electron-builder-macx64.yml` - macOS x64 构建配置 | ||
| - `src/main/index.ts` - 主进程配置 | ||
| - `src/main/presenter/upgradePresenter/index.ts` - 更新服务配置 | ||
| - `src/renderer/src/i18n/*/about.json` - 国际化文件 | ||
| - `src/main/presenter/configPresenter/mcpConfHelper.ts` - MCP 服务描述 | ||
|
|
||
| 以及复制品牌资源文件到相应位置。 | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Document HTML <title> replacements (index, shell, floating) to match behavior
The PR promises HTML title updates across index.html, shell/index.html, and floating/index.html, but this list omits them. Add them so users know to expect window title changes.
这个脚本会自动替换以下文件中的品牌信息:
- `package.json` - 包配置
- `electron-builder.yml` - 构建配置
- `electron-builder-macx64.yml` - macOS x64 构建配置
- `src/main/index.ts` - 主进程配置
- `src/main/presenter/upgradePresenter/index.ts` - 更新服务配置
- `src/renderer/src/i18n/*/about.json` - 国际化文件
- `src/main/presenter/configPresenter/mcpConfHelper.ts` - MCP 服务描述
+ - `src/renderer/index.html` - 页面标题 <title>
+ - `src/renderer/shell/index.html` - Shell 窗口标题 <title>(格式:Brand - Shell)
+ - `src/renderer/floating/index.html` - 悬浮窗标题 <title>
以及复制品牌资源文件到相应位置。📝 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.
| 这个脚本会自动替换以下文件中的品牌信息: | |
| - `package.json` - 包配置 | |
| - `electron-builder.yml` - 构建配置 | |
| - `electron-builder-macx64.yml` - macOS x64 构建配置 | |
| - `src/main/index.ts` - 主进程配置 | |
| - `src/main/presenter/upgradePresenter/index.ts` - 更新服务配置 | |
| - `src/renderer/src/i18n/*/about.json` - 国际化文件 | |
| - `src/main/presenter/configPresenter/mcpConfHelper.ts` - MCP 服务描述 | |
| 以及复制品牌资源文件到相应位置。 | |
| 这个脚本会自动替换以下文件中的品牌信息: | |
| - `package.json` - 包配置 | |
| - `electron-builder.yml` - 构建配置 | |
| - `electron-builder-macx64.yml` - macOS x64 构建配置 | |
| - `src/main/index.ts` - 主进程配置 | |
| - `src/main/presenter/upgradePresenter/index.ts` - 更新服务配置 | |
| - `src/renderer/src/i18n/*/about.json` - 国际化文件 | |
| - `src/main/presenter/configPresenter/mcpConfHelper.ts` - MCP 服务描述 | |
| - `src/renderer/index.html` - 页面标题 <title> | |
| - `src/renderer/shell/index.html` - Shell 窗口标题 <title>(格式:Brand - Shell) | |
| - `src/renderer/floating/index.html` - 悬浮窗标题 <title> | |
| 以及复制品牌资源文件到相应位置。 |
🤖 Prompt for AI Agents
In docs/rebrand-guide.md around lines 66 to 77, the list of files that the
script updates omits the HTML files whose <title> tags are modified; update the
list to include index.html, shell/index.html, and floating/index.html so the
guide accurately documents that the script replaces the HTML <title> values for
those windows—add those three paths into the enumerated file list and mention
they control window titles.
| ## 必需文件 | ||
| - `icon.png` - 应用图标 (512x512 PNG) | ||
| - `icon.ico` - Windows 图标文件 | ||
| - `logo.png` - 亮色主题 Logo (建议 256x256) | ||
| - `logo-dark.png` - 暗色主题 Logo (建议 256x256) | ||
|
|
||
| ## 文件要求 | ||
| - 图标文件应该是高质量的,符合各平台设计规范 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Docs say “required files” but PR goal makes assets optional — tighten wording
Your PR objective explicitly states brand assets are optional to support text‑only rebranding. This file currently lists them as “必需文件” (required), which contradicts that and may confuse users.
Apply this diff to align the guidance:
-## 必需文件
+## 可选文件(如需自定义图标/Logo)
+- 以下资源为可选项。若未提供,本工具将仅替换文本品牌信息:
- `icon.png` - 应用图标 (512x512 PNG)
- `icon.ico` - Windows 图标文件
- `logo.png` - 亮色主题 Logo (建议 256x256)
- `logo-dark.png` - 暗色主题 Logo (建议 256x256)📝 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.
| ## 必需文件 | |
| - `icon.png` - 应用图标 (512x512 PNG) | |
| - `icon.ico` - Windows 图标文件 | |
| - `logo.png` - 亮色主题 Logo (建议 256x256) | |
| - `logo-dark.png` - 暗色主题 Logo (建议 256x256) | |
| ## 文件要求 | |
| - 图标文件应该是高质量的,符合各平台设计规范 | |
| ## 可选文件(如需自定义图标/Logo) | |
| - 以下资源为可选项。若未提供,本工具将仅替换文本品牌信息: | |
| - `icon.png` - 应用图标 (512x512 PNG) | |
| - `icon.ico` - Windows 图标文件 | |
| - `logo.png` - 亮色主题 Logo (建议 256x256) | |
| - `logo-dark.png` - 暗色主题 Logo (建议 256x256) | |
| ## 文件要求 | |
| - 图标文件应该是高质量的,符合各平台设计规范 |
🤖 Prompt for AI Agents
In scripts/brand-assets/.gitkeep around lines 5 to 12, the header and list label
these assets as “必需文件” which conflicts with the PR goal that assets are
optional; change the wording to indicate they are optional/recommended (e.g.,
“可选/建议文件” or “推荐文件”) and update any descriptive text to state these assets are
recommended for richer branding but not required, keeping the same file list and
size suggestions.
| /** | ||
| * DeepChat 品牌替换脚本 | ||
| * | ||
| * 使用方法: | ||
| * 1. 修改 brand-config.template.json 中的配置 | ||
| * 2. 将品牌资源文件放在 scripts/brand-assets/ 目录下 | ||
| * 3. 运行 node scripts/rebrand.js | ||
| * | ||
| * 这将一次性替换整个项目的品牌信息 | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logs and comments must be in English per coding guidelines
Repository guideline for JS/TS requires English logs/comments. This file is entirely Chinese, which will fail compliance checks and hinder non‑Chinese contributors.
Apply this diff to translate the header comment; replicate the pattern for in‑line comments below:
-/**
- * DeepChat 品牌替换脚本
- *
- * 使用方法:
- * 1. 修改 brand-config.template.json 中的配置
- * 2. 将品牌资源文件放在 scripts/brand-assets/ 目录下
- * 3. 运行 node scripts/rebrand.js
- *
- * 这将一次性替换整个项目的品牌信息
- */
+/**
+ * DeepChat Rebranding Script
+ *
+ * Usage:
+ * 1. Edit branding in brand-config.template.json
+ * 2. (Optional) Put brand assets in scripts/brand-assets/
+ * 3. Run: node scripts/rebrand.js
+ *
+ * This performs a one‑time project‑wide brand replacement.
+ */Also, please convert all user‑visible log messages passed to success/info/warning/error to English (or make them bilingual).
📝 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.
| /** | |
| * DeepChat 品牌替换脚本 | |
| * | |
| * 使用方法: | |
| * 1. 修改 brand-config.template.json 中的配置 | |
| * 2. 将品牌资源文件放在 scripts/brand-assets/ 目录下 | |
| * 3. 运行 node scripts/rebrand.js | |
| * | |
| * 这将一次性替换整个项目的品牌信息 | |
| */ | |
| /** | |
| * DeepChat Rebranding Script | |
| * | |
| * Usage: | |
| * 1. Edit branding in brand-config.template.json | |
| * 2. (Optional) Put brand assets in scripts/brand-assets/ | |
| * 3. Run: node scripts/rebrand.js | |
| * | |
| * This performs a one-time project-wide brand replacement. | |
| */ |
🤖 Prompt for AI Agents
In scripts/rebrand.js around lines 3 to 12, the file header comment and
subsequent comments/logs are in Chinese which violates repository guidelines;
update the header comment to English (or bilingual English+Chinese) and apply
the same translation pattern to all inline comments in the file, and change all
user-visible log messages passed to console/ logger.info/warn/error to English
(or bilingual) while preserving original meaning; ensure phrasing is clear,
concise, and consistent with other JS/TS files in the repo.
| // 更新 electron-builder.yml | ||
| function updateElectronBuilder(config) { | ||
| const builderPath = path.join(PROJECT_ROOT, 'electron-builder.yml') | ||
|
|
||
| try { | ||
| let content = fs.readFileSync(builderPath, 'utf8') | ||
|
|
||
| // 替换 appId | ||
| content = content.replace(/appId: .+/, `appId: ${config.app.appId}`) | ||
|
|
||
| // 替换 productName | ||
| content = content.replace(/productName: .+/, `productName: ${config.app.productName}`) | ||
|
|
||
| // 替换 executableName (Windows) | ||
| content = content.replace(/executableName: .+/, `executableName: ${config.app.executableName}`) | ||
|
|
||
| // 替换 shortcutName (Windows) | ||
| content = content.replace(/shortcutName: .+/, `shortcutName: ${config.app.productName}`) | ||
|
|
||
| // 替换 uninstallDisplayName (Windows) | ||
| content = content.replace(/uninstallDisplayName: .+/, `uninstallDisplayName: ${config.app.productName}`) | ||
|
|
||
| // 替换 maintainer (Linux) | ||
| content = content.replace(/maintainer: .+/, `maintainer: ${config.app.author}`) | ||
|
|
||
| // 替换 publish URL | ||
| if (config.update && config.update.baseUrl) { | ||
| content = content.replace(/url: https:\/\/cdn\.deepchatai\.cn\/upgrade\//, `url: ${config.update.baseUrl}`) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
YAML replacements are too brittle and only replace the first occurrence
Regex /appId: .+/ etc. will:
- Match only once (no g flag)
- Break on leading spaces/quotes/comments
- Miss other occurrences across targets (win/linux/mac blocks)
Use anchored multiline and global patterns; normalize the publish URL.
- // 替换 appId
- content = content.replace(/appId: .+/, `appId: ${config.app.appId}`)
-
- // 替换 productName
- content = content.replace(/productName: .+/, `productName: ${config.app.productName}`)
-
- // 替换 executableName (Windows)
- content = content.replace(/executableName: .+/, `executableName: ${config.app.executableName}`)
-
- // 替换 shortcutName (Windows)
- content = content.replace(/shortcutName: .+/, `shortcutName: ${config.app.productName}`)
-
- // 替换 uninstallDisplayName (Windows)
- content = content.replace(/uninstallDisplayName: .+/, `uninstallDisplayName: ${config.app.productName}`)
-
- // 替换 maintainer (Linux)
- content = content.replace(/maintainer: .+/, `maintainer: ${config.app.author}`)
-
- // 替换 publish URL
- if (config.update && config.update.baseUrl) {
- content = content.replace(/url: https:\/\/cdn\.deepchatai\.cn\/upgrade\//, `url: ${config.update.baseUrl}`)
- }
+ // Replace common fields (all occurrences, preserve indentation)
+ content = content
+ .replace(/^(\s*appId:\s*).*/gm, `$1${config.app.appId}`)
+ .replace(/^(\s*productName:\s*).*/gm, `$1${config.app.productName}`)
+ .replace(/^(\s*executableName:\s*).*/gm, `$1${config.app.executableName}`)
+ .replace(/^(\s*shortcutName:\s*).*/gm, `$1${config.app.productName}`)
+ .replace(/^(\s*uninstallDisplayName:\s*).*/gm, `$1${config.app.productName}`)
+ .replace(/^(\s*maintainer:\s*).*/gm, `$1${config.app.author}`)
+
+ // Replace publish URL (match old default; keep trailing slash)
+ if (config.update?.baseUrl) {
+ const base = config.update.baseUrl.replace(/\/?$/, '/')
+ content = content.replace(
+ /^(\s*url:\s*)https:\/\/cdn\.deepchatai\.cn\/upgrade\/?/gm,
+ `$1${base}`
+ )
+ }📝 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.
| // 更新 electron-builder.yml | |
| function updateElectronBuilder(config) { | |
| const builderPath = path.join(PROJECT_ROOT, 'electron-builder.yml') | |
| try { | |
| let content = fs.readFileSync(builderPath, 'utf8') | |
| // 替换 appId | |
| content = content.replace(/appId: .+/, `appId: ${config.app.appId}`) | |
| // 替换 productName | |
| content = content.replace(/productName: .+/, `productName: ${config.app.productName}`) | |
| // 替换 executableName (Windows) | |
| content = content.replace(/executableName: .+/, `executableName: ${config.app.executableName}`) | |
| // 替换 shortcutName (Windows) | |
| content = content.replace(/shortcutName: .+/, `shortcutName: ${config.app.productName}`) | |
| // 替换 uninstallDisplayName (Windows) | |
| content = content.replace(/uninstallDisplayName: .+/, `uninstallDisplayName: ${config.app.productName}`) | |
| // 替换 maintainer (Linux) | |
| content = content.replace(/maintainer: .+/, `maintainer: ${config.app.author}`) | |
| // 替换 publish URL | |
| if (config.update && config.update.baseUrl) { | |
| content = content.replace(/url: https:\/\/cdn\.deepchatai\.cn\/upgrade\//, `url: ${config.update.baseUrl}`) | |
| } | |
| // 更新 electron-builder.yml | |
| function updateElectronBuilder(config) { | |
| const builderPath = path.join(PROJECT_ROOT, 'electron-builder.yml') | |
| try { | |
| let content = fs.readFileSync(builderPath, 'utf8') | |
| // Replace common fields (all occurrences, preserve indentation) | |
| content = content | |
| .replace(/^(\s*appId:\s*).*/gm, `$1${config.app.appId}`) | |
| .replace(/^(\s*productName:\s*).*/gm, `$1${config.app.productName}`) | |
| .replace(/^(\s*executableName:\s*).*/gm, `$1${config.app.executableName}`) | |
| .replace(/^(\s*shortcutName:\s*).*/gm, `$1${config.app.productName}`) | |
| .replace(/^(\s*uninstallDisplayName:\s*).*/gm, `$1${config.app.productName}`) | |
| .replace(/^(\s*maintainer:\s*).*/gm, `$1${config.app.author}`) | |
| // Replace publish URL (match old default; keep trailing slash) | |
| if (config.update?.baseUrl) { | |
| const base = config.update.baseUrl.replace(/\/?$/, '/') | |
| content = content.replace( | |
| /^(\s*url:\s*)https:\/\/cdn\.deepchatai\.cn\/upgrade\/?/gm, | |
| `$1${base}` | |
| ) | |
| } | |
| // ...rest of the function... | |
| } catch (err) { | |
| // handle error | |
| } | |
| } |
🤖 Prompt for AI Agents
In scripts/rebrand.js around lines 88 to 116, the current single-occurrence
regex replacements (e.g. /appId: .+/) are brittle and only replace the first
match; update them to robust, global, multiline-safe replacements by either
parsing the YAML (preferred) with a YAML library (js-yaml) and updating the keys
programmatically, or if sticking with regex use anchored, case-insensitive,
multiline/global patterns that tolerate leading whitespace and optional quotes
(e.g. match ^\s*appId:\s*['"]?.+?['"]?\s*$ with /gmi) for appId, productName,
executableName, shortcutName, uninstallDisplayName and maintainer so all
occurrences in win/linux/mac blocks are replaced; also normalize and replace the
publish URL using a pattern that matches http/https and optional trailing path
(e.g. ^\s*url:\s*https?:\/\/[^\s'"]+) with a global/multiline flag so every
publish entry is updated.
| // 替换 appId | ||
| content = content.replace(/appId: .+/, `appId: ${config.app.appId}`) | ||
|
|
||
| // 替换 productName | ||
| content = content.replace(/productName: .+/, `productName: ${config.app.productName}`) | ||
|
|
||
| // 替换 publish URL | ||
| if (config.update && config.update.baseUrl) { | ||
| content = content.replace(/url: https:\/\/cdn\.deepchatai\.cn\/upgrade\//, `url: ${config.update.baseUrl}`) | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Same YAML robustness issue in electron-builder-macx64.yml
Mirror the anchored gm replacements and flexible URL handling here as well.
- // 替换 appId
- content = content.replace(/appId: .+/, `appId: ${config.app.appId}`)
-
- // 替换 productName
- content = content.replace(/productName: .+/, `productName: ${config.app.productName}`)
-
- // 替换 publish URL
- if (config.update && config.update.baseUrl) {
- content = content.replace(/url: https:\/\/cdn\.deepchatai\.cn\/upgrade\//, `url: ${config.update.baseUrl}`)
- }
+ content = content
+ .replace(/^(\s*appId:\s*).*/gm, `$1${config.app.appId}`)
+ .replace(/^(\s*productName:\s*).*/gm, `$1${config.app.productName}`)
+
+ if (config.update?.baseUrl) {
+ const base = config.update.baseUrl.replace(/\/?$/, '/')
+ content = content.replace(
+ /^(\s*url:\s*)https:\/\/cdn\.deepchatai\.cn\/upgrade\/?/gm,
+ `$1${base}`
+ )
+ }📝 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.
| // 替换 appId | |
| content = content.replace(/appId: .+/, `appId: ${config.app.appId}`) | |
| // 替换 productName | |
| content = content.replace(/productName: .+/, `productName: ${config.app.productName}`) | |
| // 替换 publish URL | |
| if (config.update && config.update.baseUrl) { | |
| content = content.replace(/url: https:\/\/cdn\.deepchatai\.cn\/upgrade\//, `url: ${config.update.baseUrl}`) | |
| } | |
| content = content | |
| .replace(/^(\s*appId:\s*).*/gm, `$1${config.app.appId}`) | |
| .replace(/^(\s*productName:\s*).*/gm, `$1${config.app.productName}`) | |
| if (config.update?.baseUrl) { | |
| const base = config.update.baseUrl.replace(/\/?$/, '/') | |
| content = content.replace( | |
| /^(\s*url:\s*)https:\/\/cdn\.deepchatai\.cn\/upgrade\/?/gm, | |
| `$1${base}` | |
| ) | |
| } |
🤖 Prompt for AI Agents
In scripts/rebrand.js around lines 136 to 146, the current replacements for
appId, productName and the publish URL are brittle; update them to use anchored,
multi-line-safe regexes (use ^ and the gm flags) that match keys at the start of
a line and tolerate optional whitespace and quoting (e.g.
^\s*appId:\s*['"]?.+['"]?), similarly for productName, and replace with values
properly interpolated; for the publish URL, make the regex flexible (match the
existing url line regardless of the exact literal cdn path or trailing slash)
and replace it with config.update.baseUrl if present, otherwise skip/leave
existing value; ensure the replacements are done with global/multi-line flags
and do not rely on a single exact substring.
| // 替换 setAppUserModelId | ||
| content = content.replace( | ||
| /electronApp\.setAppUserModelId\('.*?'\)/, | ||
| `electronApp.setAppUserModelId('${config.app.appId}')` | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Make setAppUserModelId replacement resilient to quote style
Current regex only matches single quotes. Support ", ', and ` to avoid missing updates.
- content = content.replace(
- /electronApp\.setAppUserModelId\('.*?'\)/,
- `electronApp.setAppUserModelId('${config.app.appId}')`
- )
+ content = content.replace(
+ /electronApp\.setAppUserModelId\((["'`]).*?\1\)/,
+ `electronApp.setAppUserModelId('${config.app.appId}')`
+ )📝 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.
| // 替换 setAppUserModelId | |
| content = content.replace( | |
| /electronApp\.setAppUserModelId\('.*?'\)/, | |
| `electronApp.setAppUserModelId('${config.app.appId}')` | |
| ) | |
| // 替换 setAppUserModelId | |
| content = content.replace( | |
| /electronApp\.setAppUserModelId\((["'`]).*?\1\)/, | |
| `electronApp.setAppUserModelId('${config.app.appId}')` | |
| ) |
🤖 Prompt for AI Agents
In scripts/rebrand.js around lines 161 to 165, the current regex only matches
single quotes; change it to match any quote style by using a capturing group and
backreference like /electronApp\.setAppUserModelId\((['"`]).*?\1\)/ so it
accepts ", ' or `, and make the replacement use the captured quote (e.g. use $1)
to wrap config.app.appId so the original quote style is preserved.
| content = content.replace( | ||
| /return 'https:\/\/cdn\.deepchatai\.cn\/upgrade'/, | ||
| `return '${config.update.baseUrl}'` | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Broaden upgrade URL match and normalize trailing slash
Match both quotes and optional trailing slash to avoid a no‑op on slight source changes.
- content = content.replace(
- /return 'https:\/\/cdn\.deepchatai\.cn\/upgrade'/,
- `return '${config.update.baseUrl}'`
- )
+ const base = config.update.baseUrl.replace(/\/?$/, '/')
+ content = content.replace(
+ /return\s+["']https:\/\/cdn\.deepchatai\.cn\/upgrade\/?["']/,
+ `return '${base}'`
+ )📝 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.
| content = content.replace( | |
| /return 'https:\/\/cdn\.deepchatai\.cn\/upgrade'/, | |
| `return '${config.update.baseUrl}'` | |
| ) | |
| const base = config.update.baseUrl.replace(/\/?$/, '/') | |
| content = content.replace( | |
| /return\s+["']https:\/\/cdn\.deepchatai\.cn\/upgrade\/?["']/, | |
| `return '${base}'` | |
| ) |
🤖 Prompt for AI Agents
In scripts/rebrand.js around lines 186 to 189, the current regex only matches a
single-quote URL without a trailing slash so small source variations can skip
replacement; update the regex to match either single or double quotes and an
optional trailing slash (for example: /return
['"]https:\/\/cdn\.deepchatai\.cn\/upgrade\/?['"]/), and replace the match using
a properly quoted replacement (e.g. use JSON.stringify(config.update.baseUrl) or
otherwise escape quotes) so the replacement always inserts config.update.baseUrl
with correct quoting.
| const assetMappings = [ | ||
| // 图标文件 | ||
| { src: 'icon.png', dest: 'resources/icon.png' }, | ||
| { src: 'icon.ico', dest: 'resources/icon.ico' }, | ||
| { src: 'icon.png', dest: 'build/icon.png' }, | ||
|
|
||
| // Logo 文件 | ||
| { src: 'logo.png', dest: 'src/renderer/src/assets/logo.png' }, | ||
| { src: 'logo-dark.png', dest: 'src/renderer/src/assets/logo-dark.png' } | ||
| ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify asset destinations are actually wired in electron-builder
The script copies to resources/* and build/icon.png. Ensure electron-builder.yml points to these paths; otherwise the copied assets won’t ship.
Run:
If not referenced, either adjust the builder config or copy into the configured locations.
🏁 Script executed:
#!/bin/bash
# Inspect builder config for icon paths (expect references to build/icon.png or resources/*)
rg -nP -C2 'icon|icon[ _-]?path|resources|logo' electron-builder*.ymlLength of output: 98
🏁 Script executed:
#!/bin/bash
# Search for key build config sections in all electron-builder YAMLs
rg -nP -C5 '^(files|extraResources|directories):' electron-builder*.ymlLength of output: 2099
Verify and include icon assets in the packaged build
Your current scripts/rebrand.js copies icons into both resources/ and build/, but your Electron Builder config only treats build/ (via directories.buildResources: build) as the source for platform icons. As a result, your .ico (Windows) and (likely) .icns (macOS) files aren’t being packaged.
• In scripts/rebrand.js (lines 371–380):
const assetMappings = [
- { src: 'icon.png', dest: 'resources/icon.png' },
- { src: 'icon.ico', dest: 'resources/icon.ico' },
- { src: 'icon.png', dest: 'build/icon.png' },
+ { src: 'icon.png', dest: 'resources/icon.png' }, // optional: runtime asset
+ { src: 'icon.ico', dest: 'build/icon.ico' }, // Windows icon must live under buildResources
+ { src: 'icon.icns', dest: 'build/icon.icns' }, // macOS icon must live under buildResources
+ { src: 'icon.png', dest: 'build/icon.png' }, // keep PNG for Linux or fallback• In electron-builder.yml (uses directories.buildResources: build):
– No references to resources/ or other icon overrides.
– extraResources only includes ./runtime/ (no resources/).
Next steps
- Update your asset mappings as shown above so that
.icoand.icnsland inbuild/(yourbuildResources). - If you must ship files from
resources/, add anextraResourcesentry inelectron-builder.yml:
extraResources:
- from: resources/
to: resources/- Alternatively, change
directories.buildResourcestoresourcesif you prefer keeping icons there.
This will ensure all your icon assets are actually picked up by Electron Builder.
🤖 Prompt for AI Agents
In scripts/rebrand.js around lines 371–380 update the assetMappings so platform
icon files are placed into the buildResources directory (build/) instead of only
resources/ — specifically add destination entries for the .ico (Windows) and
.icns (macOS) files that point to build/ (e.g., copy icon.ico and icon.icns into
build/), or alternatively modify electron-builder.yml to include resources/ in
packaging (either set directories.buildResources to resources or add an
extraResources entry that copies resources/ into the packaged app); implement
one of these two fixes so Electron Builder actually picks up the .ico/.icns
files during packaging.
| if (filePath.includes('shell/index.html')) { | ||
| // shell 页面的标题格式:AppName - Shell | ||
| content = content.replace( | ||
| /<title>DeepChat - Shell<\/title>/, | ||
| `<title>${config.app.productName} - Shell</title>` | ||
| ) | ||
| } else if (filePath.includes('floating/index.html')) { | ||
| // floating 页面保持 "Floating Button" 不变 | ||
| // 这个页面的标题是功能性的,不需要改为品牌名称 | ||
| } else { | ||
| // 主页面和其他页面使用应用名称 | ||
| content = content.replace( | ||
| /<title>DeepChat<\/title>/, | ||
| `<title>${config.app.productName}</title>` | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Floating window title isn’t updated; index/shell matches are too strict
- floating/index.html is intentionally skipped, but PR scope says it should include brand name.
- Title replacements assume exact DeepChat strings and will fail if whitespace/other text differs.
Use generic <title>…</title> matching; set “Brand - Shell” and “Brand - Floating”.
- // 替换 title 标签中的内容
- if (filePath.includes('shell/index.html')) {
- // shell 页面的标题格式:AppName - Shell
- content = content.replace(
- /<title>DeepChat - Shell<\/title>/,
- `<title>${config.app.productName} - Shell</title>`
- )
- } else if (filePath.includes('floating/index.html')) {
- // floating 页面保持 "Floating Button" 不变
- // 这个页面的标题是功能性的,不需要改为品牌名称
- } else {
- // 主页面和其他页面使用应用名称
- content = content.replace(
- /<title>DeepChat<\/title>/,
- `<title>${config.app.productName}</title>`
- )
- }
+ // Replace <title>...</title> generically
+ if (filePath.includes('shell/index.html')) {
+ // Shell window title: Brand - Shell
+ content = content.replace(
+ /<title>.*?\s*-\s*Shell<\/title>/i,
+ `<title>${config.app.productName} - Shell</title>`
+ )
+ } else if (filePath.includes('floating/index.html')) {
+ // Floating window title: Brand - Floating
+ content = content.replace(
+ /<title>.*?<\/title>/i,
+ `<title>${config.app.productName} - Floating</title>`
+ )
+ } else {
+ // Main page and others: Brand
+ content = content.replace(
+ /<title>.*?<\/title>/i,
+ `<title>${config.app.productName}</title>`
+ )
+ }Also applies to: 442-444
🤖 Prompt for AI Agents
In scripts/rebrand.js around lines 435 to 449 (and also apply the same change
for lines 442-444), the current logic skips floating/index.html and matches
exact "<title>DeepChat</title>" strings which is too strict; update it to always
replace titles using a generic pattern that matches any content between <title>
and </title>, set shell pages to "<title>{brand} - Shell</title>", floating
pages to "<title>{brand} - Floating</title>", and all other pages to
"<title>{brand}</title>"; implement safe regex matching that tolerates
surrounding whitespace and different existing text, and ensure the floating
branch is no longer skipped so the brand is applied.
Pull Request Description
Is your feature request related to a problem? Please describe.
The existing rebranding functionality in DeepChat was incomplete, only handling
about.jsonfiles in the i18n directory. Many other internationalization files contained hardcoded "DeepChat" references in titles and descriptions that were not being replaced during the rebranding process. Additionally, HTML files had title tags that also needed updating for complete brand customization.Describe the solution you'd like
Enhanced the rebranding system to provide comprehensive brand customization support:
brand-config.template.jsonto include welcome page customization options for all 9 supported languagesrebrand.jsscript to handle multiple file types and replacement scenariosUI/UX changes for Desktop Application
This PR primarily affects the rebranding/white-labeling experience rather than the core application UI:
Platform Compatibility Notes
The enhancement is cross-platform compatible:
Additional context
This enhancement completes the rebranding system by addressing the comprehensive i18n support that was previously missing. The solution follows the existing architecture patterns and maintains backward compatibility. Users can now perform complete brand customization with a single configuration file and script execution.
Key improvements:
welcome.json,mcp.json,settings.json,update.json, andindex.tsfilesindex.html,shell/index.html, andfloating/index.htmlPull Request Description (中文)
你的功能请求是否与某个问题有关?请描述一下。
DeepChat 现有的品牌定制功能不够完整,仅处理 i18n 目录中的
about.json文件。许多其他国际化文件在标题和描述中包含硬编码的 "DeepChat" 引用,在品牌化过程中没有被替换。此外,HTML 文件的标题标签也需要更新以实现完整的品牌定制。请描述你希望的解决方案
增强了品牌化系统以提供全面的品牌定制支持:
brand-config.template.json,为所有 9 种支持的语言包含欢迎页面定制选项rebrand.js脚本以处理多种文件类型和替换场景桌面应用程序的 UI/UX 更改
此 PR 主要影响品牌化/白标体验,而不是核心应用程序 UI:
平台兼容性注意事项
增强功能跨平台兼容:
附加背景
此增强通过解决之前缺失的全面 i18n 支持完成了品牌化系统。解决方案遵循现有架构模式并保持向后兼容性。用户现在可以通过单个配置文件和脚本执行进行完整的品牌定制。
主要改进:
welcome.json、mcp.json、settings.json、update.json和index.ts文件index.html、shell/index.html和floating/index.html中的 HTML 标题标签Summary by CodeRabbit
New Features
Documentation
Chores