QuickNote is a lightweight browser extension for capturing and organizing notes while you browse. It also serves as a reference implementation for modern extension UI surfaces, with note-taking flows across the popup, side panel, context menu, omnibox, new tab, and DevTools.
QuickNote demonstrates the main UI surfaces a browser extension can use:
- Popup: a compact view opened from the extension toolbar icon.
- Options page: a dedicated settings or data-management page for the extension.
- Side panel: a persistent browser panel that stays available while browsing.
- Context menu: actions shown when the user right-clicks a page, link, or selection.
- Omnibox: commands and suggestions exposed through the browser address bar.
- New tab page: a custom page shown when the user opens a new tab.
- DevTools panel: an extension panel embedded inside browser developer tools.
Some of these surfaces are opened from browser chrome rather than from inside the app itself, so each one has its own entry point.
Open QuickNote from the browser toolbar by clicking the extension icon. The popup is the fastest capture flow: it includes a note field, category selector, an option to include the current page URL, a Save action, a shortcut to open the side panel, and a short list of recent notes.
Open the side panel by clicking Open side panel in the popup. Depending on the browser, you can also reopen it from the browser side panel UI after the extension enables it. This is the main note-management surface, with a new-note form, search, inline editing, and delete actions.
On any page, highlight text or right-click a page or link, then choose Save to QuickNote. If text is selected, QuickNote stores the selected text as a note. Otherwise it saves the current page or link target so the note keeps the browsing context.
Click the address bar and invoke the extension keyword qn. Use qn add Buy milk to create a note directly from the omnibox. When you type search text instead, QuickNote shows matching note suggestions and can reopen the saved page for a note that has a URL.
Open a new browser tab to view QuickNote's custom new-tab surface. It combines a quick note form on the left with a searchable notes list on the right, making it a larger dashboard-style capture view than the popup.
Open the extension's options page from the browser extension management UI. QuickNote uses this surface for data management rather than note capture: it shows the stored note count, lets you clear all notes, and exports your data as JSON or Markdown.
Open browser Developer Tools on any page and switch to the QuickNote Inspector tab. This panel is read-only and is meant to show how an extension can surface internal data inside DevTools; it lists stored notes and refreshes as local storage changes.
QuickNote stores notes locally in your browser. Every note must include note text, and every saved note gets a category. If you do not choose a category in a form, QuickNote uses General. Some save flows can also attach the current page title and URL so you can return to the page later.
When a note is saved, QuickNote adds it to local browser storage and shows it in the note lists across the extension. Depending on where you saved it, QuickNote may also keep the page title and URL with the note.
The available categories are:
GeneralWorkPersonalIdeas
The popup is the fastest way to capture a note while browsing.
- Click the QuickNote extension icon in the browser toolbar.
- In the
Notefield, type the text you want to save. - Choose a value from the
Categorylist. - Leave
Include current pagechecked if you want QuickNote to attach the current tab title and URL to the note. - Click
Save.
After saving, the popup shows Note saved., refreshes the Recent list, and then closes shortly after the save completes.
Use the popup when you want to save something quickly without leaving the page you are on.
The side panel is the main note-management view. It is the best place to save notes when you also want to search, edit, or delete them right away.
- Open the popup from the toolbar icon.
- Click
Open side panel. - In the
New notefield, type the note text. - Choose a
Category. - Click
Save.
After saving, the note stays visible in the side panel list. You can then:
- use
Searchto filter notes by text, category, URL, or title - click
Editto change the note text or category - click
Deleteto remove a note
Use the side panel when you are collecting several notes during a browsing session or cleaning up saved notes afterward.
The new tab page gives you a larger writing area than the popup and keeps the note list visible at the same time.
- Open a new browser tab that uses QuickNote's custom new-tab page.
- In the
Notefield, type the note text. - Choose a
Category. - Click
Save.
After saving, QuickNote clears the form, shows Note saved., and refreshes the notes list. Use the Search field on the right to find notes you have already saved.
Use the new tab page when you want more room to type or when you want a dashboard-style view of recent notes while you work.
The context menu is the quickest way to save content directly from a page without typing it manually.
- On any page, either highlight text or right-click without selecting text.
- Choose
Save to QuickNote.
QuickNote behaves differently depending on what you clicked:
- If text is selected, the selected text becomes the note text. QuickNote also keeps the current page URL and page title when available.
- If no text is selected, QuickNote saves the current page or clicked link. In that case, the page or link title becomes the note text.
Context menu saves use the General category automatically. This is the best option when you want to capture quotes, page references, or links while reading.
The omnibox is the most keyboard-driven way to save a note.
- Click the browser address bar.
- Invoke the QuickNote keyword
qn. - Type
qn addfollowed by the note text. Example:qn add Buy milk. - Press Enter.
QuickNote saves the note immediately using the General category. This flow is designed for fast text capture and does not ask for a category before saving.
The omnibox can also search existing notes, but to create a new note you must use the add form.
- Use the popup for the fastest manual note capture.
- Use the side panel when you want to save, review, search, edit, and delete notes in one place.
- Use the new tab page when you want a larger note-writing surface with a visible notes list.
- Use the context menu when you want to save selected text, a page, or a link directly from the current site.
- Use the omnibox when you prefer keyboard-only capture.
After saving, your notes are available throughout the extension:
- The popup shows a short
Recentlist. - The side panel shows the main searchable note list.
- The new tab page shows a searchable notes list beside the note form.
- The options page does not create notes, but it lets you export notes as JSON or Markdown and use
Clear all noteswhen needed.
All notes stay in local QuickNote storage in this browser unless you export or delete them.
QuickNote is developed as a browser extension, so the normal workflow is to install dependencies, run the WXT development server, and then load the generated extension into the browser profile used for development.
Run:
npm install
This installs the project dependencies and runs WXT preparation through the postinstall script.
For Chrome-targeted development, run:
npm run dev
For Firefox-targeted development, run:
npm run dev:firefox
WXT handles the extension build pipeline, serves the extension entrypoints, and prepares the generated development output that the browser loads.
To create a production build for Chrome, run:
npm run build
To create a production build for Firefox, run:
npm run build:firefox
Production builds are written to the generated output directory used by WXT.
When you need a distributable archive, run:
npm run zipnpm run zip:firefox
These commands package an already built extension for distribution or manual installation workflows.
QuickNote is built as a modern browser extension using a small TypeScript and React application layer on top of WXT.
WXT is the extension framework that ties the project together. It manages extension entrypoints, build output, browser-specific packaging, manifest generation, and the development workflow. In this project it is also configured to use the React module, which lets each extension surface behave like a small React application while still compiling into a Manifest V3 browser extension.
React powers the interactive UI surfaces in the extension, including the popup, side panel, new tab page, options page, and DevTools panel. Each surface has its own entrypoint and React root, which keeps the browser-specific pages isolated while still allowing them to share components, note rendering, and form controls.
TypeScript is used throughout the project to define the note model, message contracts, form inputs, and storage helpers. That matters in an extension because multiple isolated contexts need to agree on the same data shape. QuickNote uses shared types so the popup, side panel, background worker, and other surfaces all exchange note data in a consistent format.
QuickNote uses the browser APIs through wxt/browser, which provides the extension-facing interfaces used by the codebase. That includes local storage, tabs, runtime messaging, context menus, the side panel API, and omnibox integration.
QuickNote is structured around one shared note system and several separate browser extension surfaces that talk to it.
The project has separate entrypoints for:
- popup
- side panel
- options page
- new tab page
- DevTools integration
- background service worker
Each UI surface runs independently, but they all reuse the same shared note logic and UI helpers from lib/. This keeps the extension consistent without turning the whole project into one large coupled app.
The background logic in entrypoints/background.ts acts as the central coordinator for extension-only features. It is responsible for:
- creating the
Save to QuickNotecontext menu - enabling the side panel entrypoint
- handling omnibox input and note suggestions
- receiving runtime messages from the UI surfaces
- performing note create, list, update, delete, and clear operations
This design keeps privileged extension behavior in one place instead of duplicating browser API logic in every UI surface.
The shared note model lives in lib/notes.ts. That file defines:
- the note structure
- supported categories
- allowed note sources such as popup, context menu, omnibox, new tab, and side panel
- runtime message shapes used to request note operations
- helper functions for filtering, sorting, category normalization, and date formatting
Because every surface imports the same definitions, the extension can pass note data between contexts without each screen inventing its own schema.
QuickNote stores its notes in browser.storage.local. The persistence layer in lib/noteStore.ts is responsible for reading, validating, creating, updating, deleting, and clearing notes. It also sorts notes and rejects malformed stored values before the rest of the app uses them.
This validation step is important because browser storage is just serialized data. QuickNote does not assume stored values are valid; it checks that saved notes have the required fields before treating them as usable notes.
When a user saves or edits a note, the UI surface does not write directly to storage. Instead, it sends a typed runtime message to the background worker. The background worker validates the message type, calls the storage helper, and returns a structured success or error response.
In practice, the flow works like this:
- A user interacts with a form in the popup, side panel, new tab page, or another extension surface.
- The UI sends a note message such as
notes:createornotes:list. - The background service worker receives the message and routes it to the correct note operation.
- The note store reads or writes
browser.storage.local. - The background sends the result back so the UI can refresh the visible note list or show an error.
This separation makes the UI components simpler and keeps the data handling logic centralized.
The reusable React UI pieces live in lib/ui.tsx. Shared controls such as text inputs, textareas, selects, status messages, and note list rendering are defined once and reused across the extension surfaces. That reduces duplication and helps the popup, side panel, and other pages behave consistently.
Although QuickNote shares most of its core logic, each surface still has its own job:
- the popup focuses on fast capture
- the side panel is the main note-management surface
- the new tab page provides a larger dashboard-style capture view
- the options page handles data-management tasks such as export and clearing notes
- the DevTools panel exposes stored notes in a developer-oriented view
- the background worker integrates with browser features like context menus and the omnibox
That split is the main architectural idea behind the app: one note system, many specialized extension surfaces.
npm test: run Vitest unit tests.npm run test:e2e: build the Chrome MV3 extension and run the Playwright E2E suite.npm run test:e2e:headed: run the same E2E suite in headed mode for debugging.






