Skip to content

PrabinDevkota/Keeper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Keeper

Save things you want to learn later.

Keeper is a small Chrome extension built with Manifest V3, plain HTML, plain CSS, and plain JavaScript. It is designed to help you quickly save terms, concepts, tools, and topics while browsing, then come back to them later in a simple popup list.

The project is intentionally beginner-friendly:

  • no frameworks
  • no backend
  • no database
  • no build tools
  • no external APIs
  • local-only storage with chrome.storage.local

What Keeper can do

Keeper currently supports:

  • save selected text from the popup
  • save manual text when nothing is selected
  • save selected text from the right-click context menu
  • save selected text with a keyboard shortcut
  • save the current page title
  • save the current page URL
  • save an optional note
  • save one optional tag
  • store data locally in the browser
  • show saved items in the popup
  • filter items by status
  • sort items in different ways
  • mark items as learned
  • delete items
  • open the original saved page
  • jump close to the selected text when a text-fragment URL is available
  • copy the original source URL
  • export saved items to JSON
  • import saved items from JSON

How Keeper works

Keeper has two main parts:

  • a popup UI
  • a background service worker

The popup handles:

  • manual saving
  • selected text capture when the popup opens
  • rendering saved items
  • filtering
  • sorting
  • export and import
  • item actions like learned, delete, open, and copy URL

The background service worker handles:

  • creating the right-click context menu
  • saving directly from the context menu
  • handling the keyboard shortcut

This split is important because the popup is only open when the user clicks the extension, but the context menu and keyboard shortcut must work even when the popup is closed.

Current project structure

Keeper/
├─ background.js
├─ manifest.json
├─ popup.html
├─ popup.css
├─ popup.js
└─ README.md

File-by-file overview

manifest.json

This is the main Chrome extension configuration file.

It tells Chrome:

  • this extension uses Manifest V3
  • the extension name and description
  • which permissions are needed
  • which popup opens from the toolbar icon
  • which background service worker runs
  • which keyboard shortcut command exists

background.js

This is the service worker.

It handles background-only tasks:

  • creating the Save to Keeper context menu
  • clearing and recreating the menu during reloads to avoid duplicate development issues
  • handling right-click saves from selected text
  • handling the quick-save keyboard shortcut
  • writing saved items to chrome.storage.local

popup.html

This is the popup layout.

It includes:

  • the term/topic input
  • the note field
  • the tag field
  • the current page info
  • the save button
  • the filter tabs
  • the sort control
  • the export button
  • the import button
  • the saved items list

popup.css

This file styles the popup.

It keeps the UI:

  • compact
  • readable
  • simple
  • lightweight

popup.js

This is the main popup logic file.

It handles:

  • reading the active tab
  • reading selected text from the page
  • creating new items
  • normalizing older stored items
  • rendering cards
  • showing hostnames
  • filtering
  • sorting
  • marking items as learned
  • deleting items
  • opening source pages
  • opening jump-to-text links
  • copying URLs
  • exporting JSON
  • importing JSON safely

Data model

Keeper keeps each item in local storage using this shape:

{
  id: "unique-id",
  text: "Saved text",
  note: "Optional note",
  tag: "Optional tag",
  pageTitle: "Page title",
  pageUrl: "Original page URL",
  sourceUrl: "Original page URL",
  jumpUrl: "Optional text-fragment URL",
  status: "saved",
  createdAt: "ISO timestamp"
}

Field notes

  • id Unique identifier for the item.

  • text The main term, topic, or selected text the user saved.

  • note Optional note written by the user. Defaults to an empty string.

  • tag One optional simple tag string. Defaults to an empty string.

  • pageTitle The title of the page where the item was saved from.

  • pageUrl The original page URL.

  • sourceUrl The original source page URL used for opening the page again.

  • jumpUrl A text-fragment URL used to jump near the originally selected text when possible.

  • status Either saved or learned.

  • createdAt The timestamp when the item was created.

Permissions used

Keeper keeps permissions minimal for the features it supports.

  • storage Required to save and read items from chrome.storage.local.

  • contextMenus Required to add the Save to Keeper right-click menu item.

  • tabs Required so the background service worker can read the active tab title and URL for quick save.

  • activeTab Required for temporary access to the current active page after a user action.

  • scripting Required to read selected text from the active page.

Popup save flow

When the popup opens:

  1. Keeper reads the active tab
  2. Keeper gets the page title and URL
  3. Keeper tries to read the currently selected text
  4. If text is selected, it auto-fills the text input
  5. If no text is selected, the user can type manually

When the user clicks Save item:

  1. Keeper validates that the main text field is not empty
  2. It creates an item object
  3. It stores that item in chrome.storage.local
  4. It re-renders the list in the popup

Right-click “Save to Keeper”

Keeper adds a context menu item named:

  • Save to Keeper

This menu item appears when:

  • the user selects text on a normal webpage
  • the user right-clicks the selection

When clicked, Keeper saves immediately:

  • selected text
  • empty note
  • empty tag
  • page title
  • page URL
  • default status of saved
  • timestamp

If no text is selected, Keeper does not save a blank item.

Why this uses the service worker

The popup cannot handle right-click saves reliably because it is usually closed.

In Manifest V3, context menu creation and click handling belong in the background service worker. That is why background.js exists.

Keyboard shortcut

Keeper registers a quick-save command through Chrome commands.

Default shortcut:

  • Windows/Linux: Ctrl+Shift+K
  • macOS: Command+Shift+K

You can change it here:

  • chrome://extensions/shortcuts

When triggered:

  1. Keeper finds the active tab
  2. Keeper reads the current selection from the page
  3. If selected text exists, it saves it immediately
  4. If nothing is selected, it skips saving

Keyboard shortcut limitations

  • Chrome shortcuts can conflict with browser shortcuts
  • Chrome shortcuts can conflict with operating system shortcuts
  • The shortcut may not work on chrome:// pages
  • The shortcut may not work on some restricted pages
  • If Chrome blocks page scripting, Keeper cannot read the selection
  • No selection means no save

Tags

Keeper supports one simple optional tag per item.

How it works:

  • the popup includes a Tag field
  • the tag is stored as a plain string
  • the saved card shows the tag only if it exists
  • right-click save and keyboard quick save use an empty string as the default tag

This stays intentionally simple. There is no multi-tag support yet.

Filters

Keeper supports these popup filters:

  • All
  • To Learn
  • Learned

How they work:

  • All shows every item
  • To Learn shows items with status saved
  • Learned shows items with status learned

The popup updates the list immediately when a filter is clicked. It does not reload the extension.

Sorting

Keeper supports these sort options:

  • Newest first
  • Oldest first
  • A-Z
  • Learned last

Sort behavior

  • Newest first Newer createdAt values come first.

  • Oldest first Older createdAt values come first.

  • A-Z Sorts by the saved text field alphabetically.

  • Learned last Keeps saved items first and places learned items after them. Inside each group, newer items stay first.

Hostname display

In the saved items list, Keeper shows a clean hostname instead of the full raw URL.

Example:

  • shown in popup: developer.chrome.com
  • stored in data: full source URL remains unchanged

This keeps the popup compact while still preserving the full URL for:

  • Open Page
  • Jump to Text
  • Copy URL

Saved item actions

Each saved item can support the following actions:

  • Open Page Opens the original page URL.

  • Jump to Text Opens the text-fragment URL when available.

  • Copy URL Copies the original source URL.

  • Mark learned Changes the status from saved to learned.

  • Delete Removes the item from storage.

Text jump feature

Keeper tries to save a text-fragment URL when selected text exists on an http or https page.

That means Keeper stores:

  • the original source page URL
  • an optional jump URL that points near the selected text

Jump behavior

  • Open Page always opens the normal page
  • Jump to Text opens the text-fragment link
  • if there was no valid selected text, no jump link is saved

Limitations of text fragments

  • works best on normal http and https pages
  • some sites may ignore text fragments
  • some pages may re-render in ways that break text matching
  • chrome:// pages, extension pages, PDFs, and some apps may not support this behavior

Export JSON

Keeper can export all saved data as a JSON file.

How export works:

  1. Click Export
  2. Keeper serializes all saved items
  3. The browser downloads a .json file

The export uses only native browser APIs:

  • Blob
  • URL.createObjectURL
  • a temporary download link

Import JSON

Keeper can import saved data from a JSON file.

How import works:

  1. Click Import
  2. Choose a .json file
  3. Keeper reads the file
  4. Keeper parses the JSON
  5. Keeper validates each item enough to avoid crashing
  6. Keeper merges valid items into storage

Accepted import shapes

Keeper accepts:

  • a JSON array of items
  • an object with an items array

Import validation rules

Keeper keeps validation intentionally simple:

  • the imported value must contain an array of items
  • each item must be an object
  • each item must have a non-empty text field
  • invalid dates are replaced with the current time
  • invalid status values fall back to saved
  • missing note/tag/page title values fall back to simple defaults
  • invalid items are skipped instead of crashing the popup

Duplicate rule

Keeper avoids duplicates using this practical rule:

  • skip the item if its id already exists
  • also skip the item if text, sourceUrl, and createdAt all match an existing item

This is simple, easy to understand, and helps avoid duplicate imports when the same file is imported again.

Storage compatibility

Keeper includes a light normalization step for older saved items.

This helps when the stored shape changed slightly over time, for example:

  • older items using pageUrl without sourceUrl
  • older items with a text-fragment URL stored in pageUrl
  • older items with no tag

The popup normalizes those items before rendering so older data still works.

How to load the extension in Chrome

  1. Open Chrome
  2. Go to chrome://extensions
  3. Turn on Developer mode
  4. Click Load unpacked
  5. Select the Keeper project folder
  6. Pin the extension if you want quick access

If the extension is already loaded and you changed the code:

  1. Go to chrome://extensions
  2. Find Keeper
  3. Click Reload

Manual usage guide

Save from popup

  1. Open a web page
  2. Optionally select text
  3. Open the Keeper popup
  4. Review or edit the text field
  5. Add an optional note
  6. Add an optional tag
  7. Click Save item

Save from right-click

  1. Select text on a page
  2. Right-click
  3. Click Save to Keeper

Save from keyboard shortcut

  1. Select text on a page
  2. Press the Keeper shortcut

Manage items

In the popup you can:

  • filter by All, To Learn, and Learned
  • sort items
  • open the saved page
  • jump to the saved text when available
  • copy the original URL
  • mark an item as learned
  • delete an item
  • export your data
  • import your data

Development notes

Why chrome.contextMenus.removeAll() is used

During development reloads, context menu items can become stale or conflict with old IDs.

Keeper clears old menu items before recreating them so:

  • duplicate IDs are avoided
  • the menu is recreated cleanly after reload
  • the right-click feature stays more reliable

Why the popup listens for storage changes

The popup re-renders when storage changes so that saves coming from:

  • the popup
  • the context menu
  • the keyboard shortcut
  • imports

all appear consistently.

Troubleshooting

If a feature does not seem to work, check these first:

Right-click menu not showing

  • make sure text is actually selected
  • make sure the page is a normal webpage
  • reload the extension in chrome://extensions
  • try again on a regular https site

Keyboard shortcut not working

  • check chrome://extensions/shortcuts
  • make sure the shortcut is not conflicting with another shortcut
  • make sure text is selected
  • avoid testing on restricted Chrome pages

Jump to text not working

  • some sites ignore text fragments
  • some pages change after load and the selected text cannot be found again
  • try on a static normal webpage first

Import not working

  • make sure the file is valid JSON
  • make sure it is either an array of items or an object with an items array
  • make sure the items contain non-empty text fields

Possible future improvements

  • search saved items
  • stronger duplicate detection
  • multi-tag support
  • edit saved items
  • pin or favorite items
  • confirm before delete
  • optional backup reminders

About

Keeper is a small Chrome extension built with Manifest V3, plain HTML, plain CSS, and plain JavaScript. It is designed to help you quickly save terms, concepts, tools, and topics while browsing, then come back to them later in a simple popup list.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors