Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
48170f7
Merge pull request #10 from LukaHuang/001-retro-neobrutalism-ui
Eva813 Nov 18, 2025
443aac8
Merge pull request #16 from LukaHuang/feat/version-check-2
Eva813 Dec 2, 2025
0868abb
Merge pull request #17 from LukaHuang/speckit-agents
Eva813 Dec 8, 2025
76f1099
feat: rebrand to promptbear.ai domain and fix initialization issues
LukaHuang Dec 16, 2025
86e401f
feat: make dashboard URL environment-aware
LukaHuang Dec 16, 2025
bc2346b
Merge branch 'main' of github.com:LukaHuang/promptbear-chrome-extension
LukaHuang Dec 18, 2025
9fe24ca
feat: implement dark mode with gray background, white text, and yello…
LukaHuang Dec 18, 2025
5c5f5c7
refactor(dark-mode): adjust colors to neutral grays and improve works…
LukaHuang Dec 18, 2025
07c261e
fix(dark-mode): update form popup background to neutral-700 gray
LukaHuang Dec 18, 2025
0ec5339
style: add PromptBear.ai footer and reduce UI element sizes
LukaHuang Dec 18, 2025
31d808a
chore: disable shared with me button temporarily
LukaHuang Dec 18, 2025
214bbbb
chore: bump version to 1.4.0
Eva813 Dec 18, 2025
cd3c648
fix: resolve ESLint Tailwind custom classname warnings
Eva813 Dec 18, 2025
64048d5
Merge pull request #18 from LukaHuang/release/v1.4.0
Eva813 Dec 18, 2025
8220a88
fix: prevent apiDomain from being set to wrong website origin
LukaHuang Dec 18, 2025
93bbcea
fix: add content script URL validation before sending messages
LukaHuang Dec 18, 2025
065d3b4
fix: strip pre and code tags when converting HTML to plain text
LukaHuang Dec 19, 2025
5b30ab1
chore: bump version to 1.4.2
Eva813 Dec 20, 2025
52445d1
docs: update release guide with versioned ZIP naming and standardized…
Eva813 Dec 20, 2025
733ce70
Merge pull request #20 from LukaHuang/release/v1.4.2
Eva813 Dec 20, 2025
2298229
refactor: replace MutationObserver with visibilitychange for session …
LukaHuang Jan 18, 2026
8934431
Merge branch 'main' of github.com:LukaHuang/promptbear-chrome-extension
LukaHuang Jan 18, 2026
226da8c
chore: 移除不必要的 process 型別宣告以避免 TypeScript 錯誤
Eva813 Jan 19, 2026
e341ec4
chore: 更新版本號至 1.4.3 並整理 manifest.json 和 package.json 格式
Eva813 Jan 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ This is a Chrome/Firefox extension built with React, TypeScript, and Vite using
### Extension Structure
- Uses Manifest V3 with service worker background script
- Content scripts inject on all websites (`*://*/*`)
- Communicates with remote API at `https://linxly-nextjs.vercel.app`
- Communicates with remote API at `https://promptbear.ai`
- Supports both Chrome and Firefox with conditional builds

### Authentication Flow
Expand Down
117 changes: 91 additions & 26 deletions .claude/release-guide.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,84 @@
# Chrome 擴充功能上架流程指南

此文件說明如何為 Chrome 擴充功能創建乾淨的上架版本,確保沒有開發用代碼(如 HMR WebSocket 連接)。

## 前置條件
- Node.js 版本 >= 20(推薦使用 v22.12.0)
- pnpm 已安裝並更新至最新版本
- 位於專案根目錄 `/Users/black-star-point-frontend/snippets-extension
nvm use v22.12.0 , 並遵循 /Users/black-star-point-frontend/snippets-extension/.claude/release-guide.md 產出打包文件
- 位於專案根目錄 `/Users/Eva/snippets-extension`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The file path in this guide is hardcoded to a specific user's absolute path (/Users/Eva/snippets-extension). This makes the documentation less portable for other developers.

It would be better to use a more generic placeholder or instruction, such as mentioning "the project's root directory" or using a relative path.

Suggested change
- 位於專案根目錄 `/Users/Eva/snippets-extension`
- In the project root directory


---

## 🤖 Claude Code 自動化執行流程

**當用戶要求「建立 ZIP 檔案」或「打包上架」時,請依序執行以下命令:**

### 步驟 1: 清理舊文件和快取
```bash
pnpm clean
```
**預期結果:** 清除 dist/, .turbo/, node_modules/

---

### 步驟 2: 安裝依賴(必須執行)
```bash
pnpm install
```
**預期結果:** 所有依賴安裝完成,顯示 "Done in Xs"

---

### 步驟 3: 生產構建(重要:不要使用 pnpm dev)
```bash
pnpm build
```
**預期結果:** 構建成功,dist 目錄包含所有編譯後的文件

---

### 步驟 4: 驗證生產構建
```bash
node scripts/verify-production-build.js
```
**必須通過驗證,期望輸出:**
```
🔍 驗證生產構建...
✅ 生產構建驗證通過!沒有發現開發用的代碼。
🚀 可以安全地用於生產環境或上架。
```

---

## 🚀 完整上架流程
### 步驟 5: 檢查版本號
```bash
grep '"version"' dist/manifest.json
```
**預期輸出範例:** `"version": "1.4.2",` (這是會變更的)

---

### 步驟 6: 創建帶版本號的 ZIP 檔案
```bash
# 取得版本號
VERSION=$(grep '"version"' dist/manifest.json | sed 's/.*"version": "\([^"]*\)".*/\1/')

# 創建 ZIP(檔名包含版本號)
cd dist && zip -r "../extension-v${VERSION}.zip" * && cd ..
```
**預期結果:** 生成 `extension-v1.4.2.zip` (版本號會自動從 manifest.json 讀取)

---

### 步驟 7: 確認 ZIP 檔案已創建
```bash
ls -lh extension-v*.zip
```
**預期輸出:** 顯示檔案名稱和大小,例如 `extension-v1.4.2.zip`

---

## 🚀 手動執行流程

### 1️⃣ 準備階段

Expand All @@ -17,7 +88,7 @@ cd /Users/Eva/snippets-extension

# 更新版本號
# 手動編輯 package.json 中的 "version" 欄位
# 例如:從 "0.4.1" 改為 "0.4.2"
# 例如:從 "1.4.1" 改為 "1.4.2"
```

### 2️⃣ 清理與構建
Expand All @@ -26,7 +97,7 @@ cd /Users/Eva/snippets-extension
# 完全清理舊文件和快取
pnpm clean

# 安裝依賴(如果需要)
# 安裝依賴(必須執行)
pnpm install

# 生產構建(重要:不要使用 pnpm dev)
Expand Down Expand Up @@ -54,30 +125,24 @@ node scripts/verify-production-build.js
grep '"version"' dist/manifest.json
```

**期望輸出:**
**期望輸出範例:**
```
"version": "0.4.2",
"version": "1.4.2",
```

### 5️⃣ 創建上架 ZIP
### 5️⃣ 創建上架 ZIP(帶版本號)

```bash
# 進入 dist 目錄並打包
cd dist
zip -r ../extension.zip *

# 回到根目錄
cd ..
# 取得版本號並創建 ZIP
VERSION=$(grep '"version"' dist/manifest.json | sed 's/.*"version": "\([^"]*\)".*/\1/')
cd dist && zip -r "../extension-v${VERSION}.zip" * && cd ..
```

### 6️⃣ 最終確認

```bash
# 檢查 zip 文件
ls -la extension.zip

# 查看 zip 內容(可選)
unzip -l extension.zip | head -20
ls -lh extension-v*.zip
```

## 🤖 一鍵自動化腳本
Expand All @@ -98,7 +163,7 @@ fi

# 1. 清理並構建
echo "📦 清理並構建..."
pnpm clean && pnpm build
pnpm clean && pnpm install && pnpm build

if [[ $? -ne 0 ]]; then
echo "❌ 構建失敗"
Expand All @@ -119,19 +184,19 @@ echo "📋 當前版本:"
VERSION=$(grep '"version"' dist/manifest.json | sed 's/.*"version": "\([^"]*\)".*/\1/')
echo "Version: $VERSION"

# 4. 創建 ZIP
# 4. 創建 ZIP(帶版本號)
echo "📦 創建 ZIP 文件..."
cd dist
zip -r "../extension-$VERSION.zip" *
zip -r "../extension-v${VERSION}.zip" *
cd ..

# 5. 完成
if [[ -f "extension-$VERSION.zip" ]]; then
echo "🎉 上架文件已準備完成:extension-$VERSION.zip"
echo "📁 文件大小:$(ls -lh "extension-$VERSION.zip" | awk '{print $5}')"
if [[ -f "extension-v${VERSION}.zip" ]]; then
echo "🎉 上架文件已準備完成:extension-v${VERSION}.zip"
echo "📁 文件大小:$(ls -lh "extension-v${VERSION}.zip" | awk '{print $5}')"
echo ""
echo "📋 接下來的步驟:"
echo "1. 測試 extension-$VERSION.zip 在本地 Chrome"
echo "1. 測試 extension-v${VERSION}.zip 在本地 Chrome"
echo "2. 上傳到 Chrome Web Store"
echo "3. 備份此版本的 zip 文件"
else
Expand Down Expand Up @@ -209,5 +274,5 @@ extension.zip

---

*最後更新:2025-01-19*
*最後更新:2025-12-20*
*此指南確保每次上架都能創建乾淨、無錯誤的 Chrome 擴充功能。*
9 changes: 9 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@
"bg-card",
"text-card-foreground",
"bg-third",
// Sidebar colors
"bg-sidebar-header",
"bg-sidebar-content",
// Dark mode colors
"bg-dark-elevated",
"border-dark-elevated",
"text-dark-text-secondary",
"text-dark-text-primary",
"bg-dark-accent-bg",
"slide-panel",
"content-area",
"sidebar-toggle-container",
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ pnpm clean:install # Reinstall dependencies

## API Integration

This extension integrates with the PromptBear platform (`https://linxly-nextjs.vercel.app`):
This extension integrates with the PromptBear platform (`https://promptbear.ai`):

### Main API Endpoints
- **User Authentication**: `/api/auth/*`
Expand All @@ -201,7 +201,7 @@ This extension integrates with the PromptBear platform (`https://linxly-nextjs.v
### Environment Configuration
Create a `.env` file to set environment variables:
```bash
VITE_API_DOMAIN=https://linxly-nextjs.vercel.app
VITE_API_DOMAIN=https://promptbear.ai
VITE_VERCEL_PREVIEW_BYPASS=your_bypass_token
```

Expand Down
4 changes: 2 additions & 2 deletions README.zh-TW.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ pnpm clean:install # 重新安裝依賴

## API 整合

本擴展程式與 PromptBear 平台 (`https://linxly-nextjs.vercel.app`) 整合:
本擴展程式與 PromptBear 平台 (`https://promptbear.ai`) 整合:

### 主要 API 端點
- **用戶認證**: `/api/auth/*`
Expand All @@ -201,7 +201,7 @@ pnpm clean:install # 重新安裝依賴
### 環境配置
創建 `.env` 檔案設定環境變數:
```bash
VITE_API_DOMAIN=https://linxly-nextjs.vercel.app
VITE_API_DOMAIN=https://promptbear.ai
VITE_VERCEL_PREVIEW_BYPASS=your_bypass_token
```

Expand Down
8 changes: 4 additions & 4 deletions chrome-extension/manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ const manifest = {
host_permissions: [
// 'https://linxly-nextjs-git-feat-promptspace-v3-s-80d4ea-eva813s-projects.vercel.app/*',
// 'https://linxly-nextjs-git-feat-firebase-eva813s-projects.vercel.app/*',
'https://linxly-nextjs.vercel.app/*',
'http://localhost:3000/*',
'https://promptbear.ai/*',
'http://localhost:3003/*',
],
permissions: ['storage', 'windows', 'activeTab', 'contextMenus', 'tabs', 'notifications'],
// optional_permissions: ['notifications', 'cookies', 'sidePanel'],
Expand Down Expand Up @@ -76,9 +76,9 @@ const manifest = {
externally_connectable: {
matches: [
// 'https://linxly-nextjs-git-feat-promptspace-v3-s-80d4ea-eva813s-projects.vercel.app/*',
'https://linxly-nextjs.vercel.app/*',
'https://promptbear.ai/*',
// 如果您在本地開發後台,也加入本地位址,例如:
'http://localhost:3000/*',
'http://localhost:3003/*',
],
},
};
Expand Down
Binary file added chrome-extension/public/icon-128-blue.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified chrome-extension/public/icon-128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified chrome-extension/public/icon-16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified chrome-extension/public/icon-32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified chrome-extension/public/icon-34-gray.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified chrome-extension/public/icon-34.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified chrome-extension/public/icon-48.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 37 additions & 4 deletions chrome-extension/src/background/config/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
const isDev = process.env.NODE_ENV === 'development';

// 定義域名常量(避免重複)
const DEVELOPMENT_DOMAIN = 'http://localhost:3000';
const PRODUCTION_DOMAIN = 'https://linxly-nextjs.vercel.app';
const DEVELOPMENT_DOMAIN = 'http://localhost:3003';
const PRODUCTION_DOMAIN = 'https://promptbear.ai';

export const API_CONFIG = {
// 根據環境動態設定預設域名
Expand All @@ -18,13 +18,46 @@ export const API_CONFIG = {
PRODUCTION_DOMAIN,
} as const;

/**
* 驗證 API domain 是否為有效的 PromptBear 網域
*/
function isValidApiDomain(domain: string): boolean {
if (!domain) return false;
try {
const url = new URL(domain);
// 只允許 PromptBear 網域或本地開發環境
return (
url.hostname === 'promptbear.ai' ||
url.hostname === 'www.promptbear.ai' ||
url.hostname.endsWith('.promptbear.ai') ||
url.hostname === 'localhost' ||
url.hostname === '127.0.0.1'
);
} catch {
return false;
}
}

/**
* 取得當前使用的 API domain
* 優先級:chrome.storage.local.apiDomain > DEFAULT_DOMAIN
* 優先級:chrome.storage.local.apiDomain(需驗證) > DEFAULT_DOMAIN
* 如果儲存的 domain 無效,會自動清除並使用預設值
*/
export async function getApiDomain(): Promise<string> {
const { apiDomain } = await chrome.storage.local.get(['apiDomain']);
return apiDomain || API_CONFIG.DEFAULT_DOMAIN;

// 驗證儲存的 domain 是否有效
if (apiDomain && isValidApiDomain(apiDomain)) {
return apiDomain;
}

// 如果有無效的 domain,清除它
if (apiDomain) {
console.warn(`[API Config] 清除無效的 apiDomain: ${apiDomain}`);
await chrome.storage.local.remove(['apiDomain']);
}

return API_CONFIG.DEFAULT_DOMAIN;
}

/**
Expand Down
Loading
Loading