Skip to content
imShubh03Public

About

Web extension (MV3) that summarises any article with the Gemini API — streaming Brief/Short/Bullets output, side panel, and PDF/Markdown export.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Lucid — AI Article Summariser

A Chrome extension (Manifest V3) that reads the article in your current tab and summarises it with the Gemini API — streaming output, three lengths, side panel, and one-click PDF / Markdown export.

Chrome MV3 React 19 Vite 7 TypeScript Gemini API License


Table of Contents


Screenshots

Popup — streaming summary Side panel — finished summary Settings — key, model, length, theme
Popup summary Side panel summary Settings

Features

  • Three summary lengths — Brief (2–3 sentences), Short (~120–180 words), Bullets (5–8 key points).
  • Streaming output — tokens render as the model produces them, with Stop/Regenerate.
  • Popup + side panel — quick popup for fast reads, persistent side panel for long articles.
  • Summarise a selection — highlight any passage, right-click → Summarise selection with Lucid.
  • Exports — styled A4 PDF, Markdown download, and Copy to clipboard.
  • Resilient Gemini client — SSE streaming with thought-part filtering, plain-generateContent fallback, and clear per-error messages.
  • Survives popup closes — in-flight state is mirrored to chrome.storage.session; reopen anywhere to resume.
  • Light / dark / system themes — applied across popup, side panel, and settings.
  • Safe rendering — model output goes through react-markdown with HTML skipped, so summaries can't inject markup.

Quick Start

Prerequisites

Requirement Version
Node.js ≥ 18
Google Chrome ≥ 116 (side-panel API)
Gemini API key Free from Google AI Studio

1. Install & build

npm install
npm run build

This typechecks, builds the extension pages with CRXJS into dist/, then bundles the standalone Readability extractor (dist/content-extract.js).

2. Load in Chrome

  1. Open chrome://extensions.
  2. Enable Developer mode (top right).
  3. Click Load unpacked and select the dist/ folder.
  4. Pin Lucid to the toolbar.

3. Add your API key

  1. Click the Lucid icon → gear icon (Settings).
  2. Paste your Gemini key → Verify & save (it is validated against the API before saving).
  3. Pick a model (Gemini 3.5 Flash-Lite is the safest default for free-tier quota), a default length, and a theme.

Your key is stored in chrome.storage.local (this browser profile only — never synced) and is only ever sent to generativelanguage.googleapis.com in an x-goog-api-key header. See Permissions & Privacy.


Usage

  1. Open any article (news, blog, docs, Wikipedia…).
  2. Click the Lucid toolbar icon.
  3. Choose Brief / Short / Bullets and hit Summarise.
  4. While streaming you can Stop; after finishing you can Regenerate, Export PDF, Copy, or save Markdown.
  5. For long reads, click the panel icon in the popup header to move into the side panel.
  6. To summarise just a passage: select text → right-click → Summarise selection with Lucid.

Naming conventions

  • src/lib/* — framework-free modules (no React, no Chrome UI); unit-testable in Node.
  • src/ui/* — shared presentational code used by all three surfaces.
  • src/{popup,sidepanel,options}/* — thin per-surface entries (index.html + main.tsx).
  • Path alias @/* maps to src/* (see tsconfig.json + vite.config.ts).

Architecture

flowchart LR
    A[Popup / Side panel] -- Port: START/CANCEL --> B[Service worker]
    B -- chrome.scripting.executeScript --> C[Readability extractor]
    C -- article text --> B
    B -- SSE stream --> D[Gemini API]
    D -- text deltas --> B
    B -- CHUNK messages --> A
    A --> E[PDF / Markdown / Clipboard]
Loading
  • The service worker owns the API key and all network calls; UI surfaces only ever receive text deltas.
  • Article extraction uses Mozilla Readability on a cloned document, with a main/article fallback; text is capped at 100,000 chars and the UI flags truncation.
  • The extractor is a separate IIFE bundle (vite.content.config.ts → dist/content-extract.js) because chrome.scripting.executeScript({ files }) loads classic scripts. It parks its result on __LUCID_EXTRACT__ for a follow-up call to collect.
  • The Gemini client (src/lib/gemini.ts) streams via :streamGenerateContent?alt=sse, skips 3.x thought parts, tolerates non-SSE JSON-array bodies, and retries once via plain :generateContent if the stream is empty.
  • In-flight jobs live in chrome.storage.session, so closing the popup mid-stream loses nothing.

Configuration

Models (src/lib/types.ts → GEMINI_MODELS)

Model Label Best for
gemini-3.8-flash Gemini 3.8 Flash Most intelligent Flash model
gemini-3.5-flash Gemini 3.5 Flash Balanced speed and quality
gemini-3.5-flash-lite (default) Gemini 3.5 Flash-Lite Fastest, lowest cost / quota

Note (Sept 2026 Google change): fresh API keys are blocked from gemini-2.5-* (404 … no longer available to new users) even though models.list still advertises them. This project targets the 3.x models above. Stored 2.5 values from older installs auto-migrate to the new default via normaliseSettings().

Summary modes (src/lib/prompts.ts)

Mode Output contract
Brief Exactly 2–3 sentences, one plain paragraph
Short One ~120–180-word paragraph, argument → facts → conclusion
Bullets 5–8 one-sentence bullets (- prefix, ≤ 25 words each)

Prompts force source-language matching, plain-Markdown-only output, and treat page content as data (prompt-injection resistant).


Permissions & Privacy

Permission Why it is needed
storage Save key/preferences (local); hold in-flight summaries (session)
activeTab + scripting Read article text — only from the tab you explicitly act on. No always-on content script, no broad host access
sidePanel Open the persistent summary panel
contextMenus The Summarise selection right-click item
host_permissions: generativelanguage.googleapis.com Call the Gemini API — the only network destination
  • Page text is sent to Google's Gemini API to produce the summary. Nothing is sent anywhere else, nothing is stored off your machine.
  • Extension local storage is not encrypted. Anyone with access to this computer profile could read the key — treat it like any local credential and revoke it in AI Studio if exposed.

Scripts

Command What it does
npm install Install dependencies
npm run dev Vite dev server with HMR for extension pages (does not rebuild the extractor)
npm run build tsc --noEmit + main CRXJS build + extractor IIFE build → dist/
npm run build:content Rebuild only the extractor (run after editing src/content/extract.ts)
npm run typecheck Typecheck only
npm run preview Preview the Vite build
npm run clean Remove dist/
node scripts/generate-icons.mjs Regenerate public/icons/ PNGs from the vector spec

Troubleshooting

Symptom Cause / Fix
Add your Gemini API key in Settings No key saved — open Settings (gear icon) and verify & save one.
That API key was rejected / not authorised Wrong, revoked, or API-disabled key. Recreate it in AI Studio.
That model is not available for your key (404) Fresh keys can't use retired 2.5 models. Pick 3.5 Flash-Lite / 3.8 Flash in Settings and reload the extension.
Gemini returned an empty summary… Model answered with no text (thought-only/filtered) — retry Bullets mode or another model. The client already retries once via non-streaming generateContent.
Rate limit reached Free-tier per-minute quota. Wait, or switch to Gemini 3.5 Flash-Lite.
Could not read this page / does not have access yet Tab opened before install, or permission not yet granted. Reload the tab, click the Lucid icon on that page, retry.
Nothing to read here / Not enough readable text chrome://, Web Store, PDFs, login walls, and very short pages are unreadable by design. Try selection mode on a passage.
Gemini is having trouble right now Google-side 5xx. Wait and retry.
Summary from another tab shows as empty By design — a summary belongs to its tab (job.tabId). Switch back to the original tab.
Changed extract.ts but nothing changed npm run dev doesn't rebuild it — run npm run build:content.

Still stuck? Open the service-worker console (chrome://extensions → Lucid → Inspect views: service worker) and look for [Lucid] empty Gemini stream — it logs { model, mode, state } (event count, candidates seen, block reason), which pinpoints the failure class.


Contributing

  1. npm install → npm run dev for UI work; npm run build:content after extractor changes.
  2. npm run typecheck must pass; npm run build must produce a loadable dist/.
  3. Keep secrets out of the repo — the API key lives only in your browser profile, never in code.
  4. Small, focused commits; don't commit dist/, node_modules/, or exported *-summary.pdf/md files (all git-ignored).

License

Private project — all rights reserved. Dependencies retain their own licenses (see package.json).

About

Web extension (MV3) that summarises any article with the Gemini API — streaming Brief/Short/Bullets output, side panel, and PDF/Markdown export.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages