Files

1 line
8.8 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "bsquang/naotab", "files": {"CLAUDE.md": {"ed23f22c804b4e00a2aa21149ff95484fe582e1a": {"t": 1785674436.627878, "n": 8110, "h": "449bc07c2a84305a", "c": "# naoTab — Chrome Extension\n\n## Project overview\n\nChrome Extension (Manifest V3) that turns browser tabs into a **personal knowledge base**. No server, no backend — everything runs inside the extension, data stored in `chrome.storage.local`.\n\nUI language: **English**. Codebase comments: mixed EN/VI.\n\n---\n\n## File structure\n\n```\nnaoTab/\n├── manifest.json # Manifest V3, permissions: tabs + storage + unlimitedStorage + scripting\n├── popup.html/css/js # Popup — view tabs, save, export\n├── app.html/js # Knowledge Base full-page\n├── settings.html/js # AI provider config page\n├── build.sh # Build script → naotab-vX.Y.Z.zip\n├── core/\n│ ├── schema.js # ⚠️ Single source of truth for data structure — never remove fields\n│ ├── storage.js # Bookmarks CRUD + settings (reads only, no business logic)\n│ ├── ai.js # callAI() + suggestTags()\n│ └── export.js # exportJSON / importJSON / exportObsidian / bookmarkToObsidianMd\n│ └── sync/ # (future) drive.js, notion.js, etc.\n├── vendor/\n│ ├── d3.min.js # D3.js v7.9.0 — bundled locally (CSP compliance)\n│ └── jszip.min.js # JSZip 3.10.1 — bundled locally (CSP compliance)\n├── icons/ # icon16/48/128.png\n├── README.md # English README (links to VI version)\n├── README.vi.md # Vietnamese README (links to EN version)\n└── CLAUDE.md # This file\n```\n\n---\n\n## Architecture & Data flow\n\n```\npopup.js ──────────────────────┐\nsettings.js ────────────────────┤──► storage.js ──► chrome.storage.local\napp.js ────────────────────────┘ │\n └──► External AI API (optional)\n```\n\n### Data schema — bookmark object\n\n```json\n{\n \"id\": \"1712345678901\",\n \"url\": \"https://...\",\n \"title\": \"Page title\",\n \"reason\": \"Why user saved this\",\n \"summary\": \"AI-generated or manual summary\",\n \"tags\": [\"rust\", \"async\", \"performance\"],\n \"favIconUrl\": \"https://...\",\n \"pageMeta\": {\n \"description\": \"og:description or meta description\",\n \"ogTitle\": \"og:title\",\n \"ogType\": \"article\",\n \"keywords\": \"meta keywords\",\n \"author\": \"meta author\",\n \"siteName\": \"og:site_name\",\n \"ogImage\": \"og:image URL\",\n \"lang\": \"html lang attribute\",\n \"canonical\": \"canonical URL\"\n },\n \"savedAt\": \"2024-01-01T00:00:00.000Z\",\n \"updatedAt\": \"2024-01-01T00:00:00.000Z\"\n}\n```\n\nNote: `status` field removed from UI (was: unread/reading/done/revisit). `pageMeta` is `null` if meta read failed or tab was a chrome:// page.\n\n### Data schema — settings object\n\n```json\n{\n \"aiEnabled\": false,\n \"aiBaseUrl\": \"https://api.openai.com/v1\",\n \"aiApiKey\": \"sk-...\",\n \"aiModel\": \"gpt-4o-mini\",\n \"featTags\": true,\n \"featSummary\": true\n}\n```\n\n---\n\n## Key files and responsibilities\n\n### `core/schema.js`\n⚠️ **Never remove or rename existing fields.** Only ADD new fields with a default value.\n\n- `SCHEMA_VERSION` — current version integer, increment when adding fields\n- `BOOKMARK_DEFAULTS` — canonical bookmark shape with all fields and defaults\n- `SETTINGS_DEFAULTS` — canonical settings shape\n- `migrateBookmark(raw)` — heals old bookmark objects: fills missing fields, drops removed ones\n- `createBookmark(fields)` — builds a new bookmark object with all required fields\n\n### `core/storage.js`\nCRUD only. Loaded into popup, app, settings pages.\n\n- `getBookmarks()` — read all bookmarks, runs `migrateBookmark()` on each (safe for old data)\n- `saveBookmark(fields)` — save new, dedup by URL, calls `createBookmark()`\n- `updateBookmark(id, changes)` — partial update\n- `deleteBookmark(id)` — delete by id\n- `getSettings()` / `saveSettings(settings)` — read/write settings\n\n### `core/ai.js`\n- `callAI(title, url, pageMetaText)` — call AI API, returns `{tags, summary}` or throws\n- `suggestTags(title, url)` — offline keyword + domain matching, returns tag array\n\n### `core/export.js`\n- `exportJSON()` / `importJSON(jsonString)` — full backup/restore\n- `bookmarkToObsidianMd(bookmark)` / `exportObsidian()` — Obsidian .md export\n\n### `popup.js`\n- `loadTabs()` — queries all tabs + bookmarks, marks saved URLs\n- `getPageMeta(tabId)` — uses `chrome.scripting.executeScript` to read SEO meta tags; returns structured object with `_aiText` field for AI prompt\n- `openSaveModal(tab)` — async, reads meta in background, shows/hides AI row\n- Window save: calls `getPageMeta()` for each tab, shows `⏳ N/total` progress, saves `pageMeta`\n- Single tab save: passes `pageMeta` to `saveBookmark()`\n- **\"💾 Tab this\"** button — saves active tab directly from toolbar\n\n### `app.js`\nState: `allBookmarks`, `activeTag`, `excludedTags` (Set), `searchQuery`, `currentView` (default: `'graph'`), `editingId`, `panelId`\n\nKey features:\n- **Graph view** (default): D3 force simulation, single-click → node panel + highlight connected nodes, double-click → open URL, click background → reset. Node color: blue (has summary) vs grey (no summary)\n- **List view**: card per bookmark, click card → node panel (links/buttons still work normally)\n- **Node panel**: slide-in right panel with full details, editable fields, AI Suggest button (shown only when AI enabled), Connected nodes section (only within current filter), save/delete/open-url actions\n- **Sidebar**: split into Tags (top, scrollable) + Node list (bottom, realtime). Node list updates with filter/search; click item → open panel; hover item → tooltip with title + summary\n- **Graph tooltip**: shows title, URL, summary (blue border), reason, tags on hover\n- **AI Batch**: `✨ AI All` button in topbar — processes only visible nodes without a summary, shows confirm with counts, progress bar + notify in bottom-right, nodes update color live\n- **Exclude tags**: tag pills in sidebar have `✕` button on hover → excluded tags shown as strikethrough red, not used for graph edges\n- **Delete all**: button in topbar with confirmation\n- **Refresh**: 🔄 button in topbar\n- **Obsidian export**: JSZip → .zip of .md files with YAML frontmatter\n\n### `settings.js`\n- PRESETS: openai, claude, ollama, groq, openrouter, custom\n- Detects active preset by matching saved URL\n- Test connection: detects Anthropic vs OpenRouter vs standard; adds `HTTP-Referer` + `X-Title` headers for OpenRouter\n- Save settings to `chrome.storage.local`\n\n---\n\n## AI Integration\n\n`callAI()` in `storage.js` supports 2 formats:\n\n**OpenAI-compatible** (OpenAI, Groq, Ollama, OpenRouter, etc.):\n- Endpoint: `{baseUrl}/chat/completions`\n- Header: `Authorization: Bearer {apiKey}`\n- OpenRouter also needs: `HTTP-Referer: https://github.com/bsquang/naotab` + `X-Title: naoTab`\n\n**Anthropic native**:\n- Detect: `baseUrl.includes('anthropic.com')`\n- Endpoint: `{baseUrl}/messages`\n- Header: `x-api-key: {apiKey}` + `anthropic-version: 2023-06-01`\n\n**Token efficiency**: AI receives page meta tags (~75 tokens) instead of body text (~750 tokens) — 10× cheaper. `_aiText` field is a preformatted string built from `pageMeta` fields.\n\n---\n\n## Permissions\n\n| Permission | Reason |\n|---|---|\n| `tabs` | Read title, URL, favIconUrl of all tabs |\n| `storage` | Save bookmarks and settings to chrome.storage.local |\n| `unlimitedStorage` | Remove 10MB default cap |\n| `scripting` | Execute script in tabs to read meta tags |\n| `host_permissions: <all_urls>` | Allow meta reading on any tab |\n\n---\n\n## Conventions when working with Claude\n\n- Claude edits files directly in this folder\n- User reloads extension via 🔄 button in popup\n- `storage.js` is shared — when adding functions, update popup.js and/or app.js as needed\n- No ES modules (`import/export`) — Chrome Extension uses classic script loading\n- No inline scripts in HTML — CSP requires all JS in external `.js` files\n- No CDN scripts — bundle all libraries locally for CSP compliance\n- Commit only when user explicitly asks\n- All UI text in **English**\n\n## Roadmap\n\n- [ ] Google Drive sync (`core/sync/drive.js` — branch: feature/google-drive-sync)\n- [ ] Semantic / AI-powered search\n- [ ] AI Cluster Summary (summarize all visible nodes as a group)\n- [ ] Dark mode\n- [ ] Duplicate tab detector\n- [ ] AI-powered bookmark grouping\n- [ ] Browser history integration\n"}}}}