A Chrome extension (Manifest V3, version 1.1.0) for saving articles to lists, generating AI summaries, chatting with a Gemini model about each article, taking rich notes, and exporting everything to Excel.
- Local library — articles, notes, chats and settings are stored in browser IndexedDB. Optional AI sends article text and chat to Google using your API key; see Privacy.
- Official repository:
https://github.com/Barak-elisha/articles-extension.git(branchmain).
Name: Article Saver
Description: Save articles to lists, take notes, generate AI summaries, chat about your reading, and export to Excel.
The extension name, Chrome toolbar title and description are in English. On a fresh installation, the interface starts in English with a left-to-right layout, English AI responses and English Excel headers. Dates follow the selected interface language. Automatic AI summaries are off by default; saving articles and taking notes do not require an API key.
Hebrew is available as an optional language in Settings. An existing saved language choice is preserved. Article text remains in its original language.
The current release exports Excel workbooks; PDF export is not implemented.
- Side panel opens on the right, and opens automatically when the extension icon is clicked.
- Soft blue and lavender background with flowing waves across the side panel, full-page view, and settings; the backdrop stays fixed while content scrolls.
- List management — create, rename and delete lists (deleting a list also deletes its articles).
- Filter by active list — select a list in the "Save to list" dropdown (or "All lists") to show only that list's articles and hide the rest.
- Search your articles — a search box filters articles by title, summary, notes, URL and full article content, with a live result count and the last-opened article kept highlighted.
- Save article from the active tab — extracts title, article body and URL, optionally with an automatic AI summary.
- Chat with AI about each article — a built-in chat grounded in the article's body but also able to answer broader questions about the article (its topic, author, journal, concepts) with general knowledge. Chat messages render formatting (bold, italic, lists) inline, are persisted, and are exported to Excel.
- Personal notes per article with a rich editor (bold, italic, lists, font size and color), saved automatically.
- Edit the full article text directly in the panel, with automatic saving, automatic cleanup of 2+ blank lines, and a color highlight marker (a palette of preset colors or a custom one) whose highlights are persisted.
- Auto-aligned full text — the article text automatically aligns right for Hebrew/Arabic and left for English/Latin.
- Edit the article title inline with a small pencil next to it.
- Full-window mode — a responsive workspace on a full screen: lists | summary+notes+chat | full text.
- Excel export — an "All articles" sheet plus one sheet per list, with pale green headers, embedded green icons, rich text, clickable links, an APA citation and an AI-chat column.
- AI settings — API key from Google AI Studio; when you click Refresh models the extension fetches compatible Gemini models from Google's API and lets you pick one from a dropdown (default:
gemini-2.5-flash). - Interface language — switch between English and Hebrew in Settings (English is the default; the choice is persisted and also drives the AI output language and the Excel headers).
Save an article to your library and optionally generate an AI summary
- Browser: Google Chrome 121+ (required for side panel support and
tabs.Tab.lastAccessedused by full-window mode). Other Chromium browsers need separate compatibility checks. - Optional AI account: a Google account with access to Google AI Studio (free or paid tier API key).
- Open
chrome://extensionsin Chrome. - Enable Developer mode.
- Click "Load unpacked" and choose this folder.
- Click the extension icon in the toolbar to open the panel.
- Create a list in the "Create a list" section.
- Choose an active list and click "Save current article".
- (Optional) In Settings → "AI settings", paste an API key from Google AI Studio and click Save key. Click Refresh models to query Google for compatible generation models; choose a model and save. Saving a key or opening the panel does not make a network request.
- (Optional) In Settings → "Interface language", choose English or Hebrew (default: English).
- Click "Export to Excel" to export only the selected list, using its name as the filename (
List name.xlsx; characters unsupported in filenames are replaced with underscores). Choose "All lists" to export the entire library (articles.xlsxby default; the filename is localized when Hebrew is selected).
- Clicking an article title opens its details: AI summary (+ "Regenerate" button), My notes, Chat with AI, and the full text.
- Article rows include Open source and Delete article icon buttons.
- The active article is highlighted in blue.
- Summaries and chat messages render Markdown (headings, lists, bold, italic, code and links). Notes use the rich-text editor and its formatting toolbar.
- Select text in AI summary or Notes, click the small marker button and choose a preset or custom color. The eraser removes highlighting from the selection. Highlights save automatically and reappear when the article is reopened. Generating a new summary clears the previous summary's highlights.
- Search within the full text — a search bar above the article text highlights every match, shows a running count, and lets you jump between matches with ▲/▼.
- Edit the title — click the small pencil (✎) next to the title, type, then press Enter (or click away) to save; Esc cancels.
- The full text is cleaned automatically on save: 2+ consecutive blank lines collapse to one, and trailing spaces/newlines are removed.
- Highlight important text — select text and pick a color from the marker bar above the text (preset palette or custom color); highlights are saved with the article.
- Auto direction — Hebrew/Arabic articles align right, English/Latin articles align left, automatically.
Full-window reading workspace — feature illustration
- The Open in full size button opens
sidepanel.html?mode=fullin a new tab of the same window. - On wide screens: My lists | AI summary + notes + chat | Full text. On narrower screens, article details stack vertically.
- The page height follows the lists column (the page ends where the lists end); panels size to their content and scroll internally only when space is tight. The chat box stretches to the end of the page.
The extension talks to Google Gemini (v1beta generateContent) in two modes:
| Mode | background message | Description |
|---|---|---|
| Summary | GENERATE_SUMMARY |
A comprehensive summary of the article body in the interface language (up to 12,000 characters sent, up to 2,048 output tokens). |
| Chat | CHAT_ARTICLE |
Q&A about the article in the interface language; systemInstruction anchors factual answers to the article's content (noting when an answer goes beyond it) while allowing relevant general knowledge, and the last 20 messages are sent. |
An API key is required only for AI. The "Include an AI summary" checkbox is off by default and its choice is persisted. Enabling it sends saved article content to Google on subsequent saves. Regenerate and chat are explicit AI actions. Requests time out after 60 seconds.
Model dropdown — Refresh models explicitly calls Google's models endpoint using the key in a request header, follows pagination, and lists unique gemini-* models supporting generateContent. The default is gemini-2.5-flash; previously saved retired Gemini 2.0 selections resolve to that default. The selected model is stored as geminiModel.
Ask questions about your saved articles
English is the default for every new installation and whenever a stored language setting is missing or unsupported. The extension does not automatically switch to the browser or operating-system language.
To change the language, open Settings → Interface language and select English or Hebrew. This preference is saved and controls interface labels, dates, AI response language and Excel headers. Hebrew enables right-to-left layout. Switching the interface language does not translate previously saved articles, notes or AI responses.
After updating an unpacked extension, click Reload on its card in chrome://extensions and reopen the panel to refresh its name, description and interface. If an existing installation opens in Hebrew, select English in Settings; reloading preserves saved preferences.
- Bring your own key — the extension does not ship or bundle any API key. You must provide your own key from Google AI Studio, under Settings → "AI settings".
- Stored locally only — the key is saved exclusively in the browser's own storage (IndexedDB via the
settingsstore), never transmitted to or stored on any server owned by this extension, and never written to Excel or the article records. - Sent only to Google — the key and your article content are sent directly from your browser to Google's Gemini API only when you generate a summary or chat (model refresh sends the key without article content); nothing is routed through a third-party backend.
Treat your key like a password: anyone who can access your browser's profile can read saved keys. If a key is ever leaked, revoke and regenerate it in Google AI Studio.
The extension renders and stores content that originates outside your control — article bodies, titles, AI output — so it never inserts that data as raw HTML:
- Article body & title — the title is always rendered with
textContent. The full-text editor renders throughsanitizeHtmland is always sanitized on save (sanitizeHtml(content.innerHTML)), so HTML from the source page or pasted in is neutralized before it is stored; color highlights survive becausebackground-color(a non-URL, text-affecting property) is allowlisted. On extraction the body is stored as plain text. - AI summaries are rendered through
renderMarkdown, which HTML-escapes the entire input (&<>") before building any markup. - Notes (the only HTML the user can author) are passed through a self-contained sanitizer —
sanitizeHtmlinsanitize.js— before rendering, on paste, before saving, and before the Excel rich-text export. It is an allowlist (no external library, works fully offline): it drops<script>,<style>,<iframe>,<object>,<embed>,<form>, interactive elements and everyon*handler, stripsjavascript:/vbscript:/data:/file:URLs andexpression()/url()CSS, while keeping the safe formatting tags (b,i,u,font, lists, …). A malicious<img onerror=…>or<a href="javascript:…">inside a note is neutralized before it ever reaches the live DOM. - Anchor links produced by the sanitizer always get
rel="noopener noreferrer".
Because article content sent to Gemini is untrusted and could contain hidden instructions, the prompts isolate it:
- The article body is wrapped in explicit, unusual delimiters (
[START_OF_ARTICLE] … [END_OF_ARTICLE]). - The system instruction tells the model to treat everything between the markers strictly as reference data, never as instructions — to ignore any request, injection attempt, or "ignore previous instructions" text found inside the article.
Export your selected list, or choose All lists to export the library
Columns in the "All articles" sheet (and in the per-list sheets):
| Column | Source |
|---|---|
| List | List name |
| Title | Article title |
| AI summary | Current a.summaryHtml when available; otherwise a.summary (Markdown → rich text) |
| Notes | a.notes (HTML → runs with bold/italic/underline/color/size) |
| APA citation | buildApaCitation — APA 7th edition webpage format: Title. (n.d.). Site Name. Retrieved Month D, YYYY, from URL (retrieval date uses the saved date; (n.d.) when no publication date) |
| URL | active hyperlink |
| Saved on | a.savedAt → numeric Excel date/time, displayed as dd/mm/yyyy hh:mm |
| Chat with AI | a.chat formatted as Me: … / AI: … (with localized speaker labels when Hebrew is selected), with rich-text bold/italic, real bullets, paragraph breaks, and bold colored speaker labels (no raw Markdown markers) |
Excel exports store Saved on as a numeric date/time (dd/mm/yyyy hh:mm), suitable for sorting and date formulas. Highlights from current AI summaries and Notes are underlined in the main sheets. Because Excel rich text does not support a background fill for part of a cell, an additional Highlights sheet stores each marked passage in a separate editable cell with its original background color. The sheet is omitted when nothing is highlighted. Regenerated summaries do not reuse stale highlights.
The export pipeline:
buildExcelBlob— builds the workbook withxlsx-js-style(styles, text wrapping, column widths, one sheet per list).enhanceWorkbook— a post-processing pass with JSZip: converts the summary into rich-text runs (inlineStr), turns every URL column into hyperlinks (with_rels/sheet*.xml.rels), and enforces OOXML element ordering.isWellFormedWorkbook— re-opens the package and verifies well-formed XML and<rPr>tag order; if anything breaks, it falls back to the safe raw SheetJS output.
| File | Role |
|---|---|
manifest.json |
Extension configuration and permissions |
background.js |
Service worker — article extraction from the active tab and Gemini calls |
storage.js |
IndexedDB layer (lists, articles, settings) |
i18n.js |
Hebrew/English dictionaries and translation helpers |
sanitize.js |
Self-contained HTML sanitizer (allowlist) for untrusted content |
sidepanel.html/css/js |
The panel UI and the full-window mode |
excel-export.js |
Excel export including rich-text styling, links and validation |
lib/ |
Local libraries: jszip.min.js, xlsx-js-style.min.js, cpexcel.js |
lib/THIRD_PARTY_LICENSES.md |
Preserved license notices for the bundled libraries |
icons/ |
Extension icons (16/32/48/128) |
LICENSE |
The project's MIT license |
SECURITY.md |
How to report security vulnerabilities privately |
CONTRIBUTING.md |
Contribution guidelines (local-first, no unneeded deps) |
Scripts are loaded in sidepanel.html in this order (it matters): jszip → cpexcel → xlsx-js-style → storage → i18n → sanitize → highlighter → excel-export → sidepanel.
| type | input | output |
|---|---|---|
EXTRACT_ARTICLE |
{ lang } |
{ ok, data: { title, content, url } } |
GENERATE_SUMMARY |
{ apiKey, content, title, model, lang } |
{ ok, summary } |
CHAT_ARTICLE |
{ apiKey, model, title, content, messages, lang } |
{ ok, text } |
extractFromPage runs inside the tab (via chrome.scripting.executeScript): title from og:title → h1 → document.title, body from article → main → #content → body, stripping script/style/nav/header/footer/form/....
The extension requests HTTP/HTTPS host access for user-triggered article extraction. tabs supports selecting the last web tab while full-window mode is focused. It does not automatically scan browsing history; storage permission is unnecessary because data uses IndexedDB. When the focused tab is the extension's own side panel, extractActiveTab falls back to the most recently used HTTP tab, so saving an article works while the panel is focused.
- lists —
{ id, name, createdAt }(indexname) - articles —
{ id, listId, title, content, url, savedAt, summary?, notes?, chat? }(indexeslistId,savedAt)content— extracted plain text or sanitized edited HTML;contentFormatdistinguishestextfromhtml. Legacy records are sanitized on display.summary— Markdown stringnotes— HTML stringchat— array of[{ role: "user"|"assistant", text }]
- settings —
{ key, value }; keys:activeListId,geminiApiKey,geminiModel,autoSummary,uiLang
loadAll()— loads lists + articles + settings, picks the active list, persistsactiveListId, applies the interface language, re-renders.window.I18N(i18n.js) —load()/set()read and write theuiLangsetting (defaulten), andapply()swapsdata-i18n*strings and sets<html lang>/dir.renderLists()/renderArticleRow()— built in the DOM (no templates).renderListsfilters to the active list (or shows all when "All lists"), applies the search query viaarticleMatches, and shows a filtered/total count.articleMatches(a, query)— case-insensitive search acrosstitle,content,summary,notesandurl.normalizeBody(s)— collapses 2+ consecutive blank lines into one and strips trailing whitespace/CRLF, applied on extraction and on save of the full text.detectDirection(s)— returnsrtlfor Hebrew/Arabic text,ltrotherwise; applied to the full-text editor for auto-alignment.contentToHtml(s)— converts plain text (with<br>for newlines) or existing HTML into sanitized HTML for the full-textcontentEditableeditor.showDetail(a)— builds dynamically (per article): editable title row (pencil ✎), URL, meta (meta.dataset.base),.detail-midwith AI summary (+ "Regenerate"), Notes (contentEditableeditor with a toolbar wired todocument.execCommand), Chat (renderChat/sendChatrendering messages throughrenderMarkdown), and the full text (contentEditable, saved onblur) with an in-panel search + highlight bar (applySearch) and a color-marker toolbar (execCommand("hiliteColor", …)).renderMarkdown/mdInline— convert Markdown (headings, bold, italic, lists, code, links) to styled, HTML-escaped output; used by summaries, and reused for chat bubbles.applyActiveRow()— highlights.article-item.activebased onactiveArticleId.fitDetailToLists()— in full mode binds.detailBodyheight to the lists column height; also runs onresize.- Re-renders on
visibilitychange(when the panel comes to the foreground).
- Base (RTL): cards, buttons,
.rich-text,.chat-*,.detail-*; active article state; placeholders for empty values. - Full mode (
@media (min-width:760px)+body.full): a grid with 31frcolumns;#detailBodyis a1fr 1frgrid withgrid-template-rows: auto auto auto 1fr;.detail-midis a flexible column (flex), the chat isflex: 1 1 auto(extends to the end of the page), and the text panel isstickywith internal scrolling.
See regression test instructions and pre-store review.
- No build step — load the folder as "load unpacked" and refresh.
- Libraries live locally under
lib/(no CDN; everything stays fully local). - Manual Excel checks are done by opening the file in LibreOffice/Excel; the internal validation pipeline in
excel-export.jsguarantees a well-formed file even with fragile XML tweaks.
Run python3 scripts/package-extension.py from the repository root to create dist/article-saver-1.1.0.zip and its SHA-256 checksum. The archive contains the manifest at its root, runtime code, local libraries, icons and required license notices. Tests, screenshots, development scripts, Git metadata and machine-specific files are excluded. Generated archives are ignored by Git.
Upload this ZIP to the existing extension's Package page in the Chrome Developer Dashboard. Uploading a draft is separate from submitting it for review. Check the pre-release review and complete the remaining verification and listing requirements before submission.
If you discover a security vulnerability or sensitive data issue, please do not open a public issue. Contact the maintainer directly via GitHub instead, so the problem can be handled privately before it is fixed and disclosed. See the full Security Policy for details.
Contributions are welcome. Before opening a pull request, please review the Contributing guidelines — including keeping the project local-first (no new server dependencies) and avoiding unnecessary third-party libraries.
This project's own code is released under the MIT License — see the root LICENSE file. Copyright (c) 2026 Barak Elisha.
The extension bundles third-party libraries locally under lib/ (JSZip, xlsx-js-style, cpexcel). Their respective license terms and copyright notices are preserved and reproduced in lib/THIRD_PARTY_LICENSES.md; redistribution of this software must retain those notices.
This software is provided by the copyright holders and contributors "AS IS", and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed.
In no event shall the author(s) or copyright holders be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; business interruption; API billing overages; or system malfunctions) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
This extension is provided "AS IS", without warranty of any kind, express or implied. To the maximum extent permitted by applicable law, the author(s) disclaim all warranties, including fitness for a particular purpose and non-infringement.
By using this extension you acknowledge that:
- No Medical or Clinical Advice — This extension is designed for academic, study, and research workflows. AI-generated summaries and responses do not constitute medical, legal, or professional advice.
- API costs & Quotas are yours — The extension connects directly to Google's Gemini API using your personal API key. You are solely responsible for managing your API quotas, billing, and any incurred costs.
- Content ownership & Copyright — You are solely responsible for the content you extract, store, or export, and must comply with the terms of service and copyright terms of each source site.
- Local Credential Security — API keys reside in the browser's local IndexedDB. You are responsible for maintaining the physical and digital security of your browser profile and machine.
- Non-Affiliation: This project is an independent open-source tool and is not affiliated, endorsed, or associated with Google LLC or Google Chrome.
- Author: Barak Elisha (LinkedIn | GitHub)
- Issues: Feedback, bug reports, and feature requests are welcome via GitHub Issues.
- Refreshed interface and icons, with English metadata and defaults.
- Hardened article/notes rendering and fixed Excel names, duplicate saves and list deletion.
- Optional AI disclosure, updated Gemini default and bounded network requests.
- Dynamic Gemini model selection dropdown via Google AI Studio API.
- Full-text interactive highlight marker toolbar with persistent sanitized styling.
- In-article text search with match counter and navigation controls (▲/▼).
- Multi-field article search across titles, content, notes, and summaries.
- APA 7th Edition compliant citation export for webpages.
- Markdown rendering support inside chat dialogue bubbles.
- Contextual right-click deletion for chat messages.
- Side-panel fallback extraction handling for non-HTTP tabs.
- Initial release: Side panel UI, local IndexedDB storage, Gemini AI summaries, rich notes, full-window mode, and styled OOXML Excel export.
