A compact Chrome Manifest V3 extension for saving the current browser tab into a selected Coda table through the coda-express bookmark backend.
The extension reads the active tab URL, lets you choose a Coda doc and table, and sends the bookmark to:
POST /api/save-bookmark
The backend remains responsible for scraping, extraction, workflow handling, schema inference, and inserting the row into Coda.
- Saves the current active tab URL to a selected Coda table.
- Sends both required backend credentials:
x-api-key: <bookmark-api-key>Authorization: Bearer <coda-token>
- Keeps the Coda token behavior unchanged from the backend contract.
- Stores settings in Chrome extension storage.
- Loads accessible Coda docs and tables from the Coda API.
- Caches discovered docs and tables locally.
- Refreshes Coda docs/tables only when you click Refresh.
- Lets you save named doc/table destinations for quick reuse.
- Auto-closes the popup after a successful save.
- Truncates very long active-tab URLs in the popup while preserving the full URL for submission.
- Includes extension and toolbar icons from the
web/folder.
.
├── manifest.json
├── popup.html
├── popup.css
├── popup.js
├── README.md
├── extension.md
└── web/
├── icons8-panda-glassmorphism-16.png
├── icons8-panda-glassmorphism-32.png
├── icons8-panda-glassmorphism-72.png
├── icons8-panda-glassmorphism-96.png
├── icons8-panda-glassmorphism-120.png
├── icons8-panda-glassmorphism-144.png
├── icons8-panda-glassmorphism-192.png
└── icons8-panda-glassmorphism-512.png
This is a plain JavaScript Manifest V3 extension. There is no build step required.
-
Google Chrome or another Chromium browser that supports Manifest V3 extensions.
-
A running
rheactdev/coda-expressbookmark backend that exposes:POST /api/save-bookmark -
A private bookmark API key accepted by that backend.
-
A Coda API token with access to the docs and tables you want to save into.
-
Start your backend.
For a local backend, this is commonly:
pnpm run dev
-
Open Chrome.
-
Go to:
chrome://extensions -
Enable Developer mode.
-
Click Load unpacked.
-
Select this extension folder:
/Users/donut/Desktop/Programs/tutorial.hello-world -
Pin the extension from the Chrome extensions menu if you want quick toolbar access.
Open the popup and click Settings next to the Save to Coda title.
Enter:
-
Backend URL: the base URL for your bookmark backend, for example:
http://localhost:3000 -
Bookmark API key: your private backend API key. This is sent as the
x-api-keyheader. -
Coda API token: your Coda API token. This is sent as the
Authorization: Bearer ...header.
The Settings panel opens automatically if you try to save or refresh without the required backend settings.
After entering a Coda API token:
- Click Locations next to the Save to Coda title.
- Click Refresh beside the Coda doc dropdown.
- The extension fetches every Coda doc available to the token.
- For each doc, it also fetches the tables in that doc.
- The discovered docs and tables are cached locally.
- Select the desired Coda doc.
- Select the desired Coda table.
- Enter a friendly name under Save current location.
- Click Save.
Opening the popup later uses the local cache. The extension does not call the Coda docs/tables APIs again unless you click Refresh in the Locations panel.
- Open a normal webpage tab.
- Open the extension popup.
- Confirm the displayed active URL.
- Choose a named destination from Saved location.
- Click Save bookmark.
On success, the popup closes automatically.
The main popup only exposes saved locations. Create or update destinations from the Locations panel to keep the day-to-day save flow uncluttered.
The extension sends this JSON body to the backend:
{
"url": "https://example.com/page",
"docId": "coda-doc-id",
"tableId": "grid-table-id",
"properties": {
"name": "Example title",
"url": "https://example.com/reference",
"date": "2026-05-28",
"tags": ["research", "wishlist"]
}
}The save request is sent to:
POST <backend-url>/api/save-bookmark
Headers:
Content-Type: application/json
x-api-key: <bookmark-api-key>
Authorization: Bearer <coda-token>Body:
{
"url": "https://example.com/page",
"docId": "coda-doc-id",
"tableId": "grid-table-id",
"properties": {
"name": "Example title",
"url": "https://example.com/reference",
"date": "2026-05-28",
"tags": ["research", "wishlist"]
}
}properties contains the manual values entered in the popup for the selected saved location. Only the properties configured for that saved location are included. Multi-select and multi-relation properties are entered as chip/token inputs and sent as arrays.
The bookmark API key is never placed in the request body or query string. The Coda token is never placed in the request body or query string.
Saved locations let you reuse common Coda destinations without keeping raw doc and table selectors on the main popup.
To create one:
-
Open Locations.
-
Click Refresh if docs and tables have not been loaded yet, or if you need to update the local cache.
-
Select the desired Coda doc.
-
Select the desired Coda table.
-
Enter a name under Save current location, for example:
Wishlist -
Click Save.
To use one:
- Return to the main popup.
- Open the Saved location dropdown.
- Choose the saved destination.
- Click Save bookmark.
Saved locations are tied to the current Coda token fingerprint, so locations from one token are not shown for another token.
The extension uses Chrome extension storage:
-
chrome.storage.syncbackendBaseUrlbookmarkApiKeycodaTokendocIdsavedLocationIdtableId
-
chrome.storage.localcodaDiscoveryCache: cached Coda docs and tables.codaSavedLocations: named doc/table destinations.codaSelectedDatabaseProperties: draft selected database properties while creating or editing a location.codaManualPropertyValues: manual property values keyed by saved location.
Sensitive values are stored only in Chrome extension storage and are sent only as request headers.
The manifest requests:
{
"permissions": ["activeTab", "storage", "tabs"],
"host_permissions": ["<all_urls>"]
}Why:
activeTabandtabs: read the current active tab URL.storage: persist settings, cache, and saved locations.<all_urls>: allow fetches to the configured backend and Coda API.
Because this is a plain JavaScript extension, edit the source files directly:
popup.htmlpopup.csspopup.jsmanifest.json
After changes:
- Open
chrome://extensions. - Click the refresh/reload button for the extension.
- Open the popup again.
You can run a quick JavaScript syntax check with:
node --check popup.jsYou can validate the manifest JSON with:
node -e "JSON.parse(require('fs').readFileSync('manifest.json', 'utf8')); console.log('manifest ok')"If you see:
Bookmark API key is required.
Open Settings and enter the private backend API key.
If you see:
Coda API token is required.
Open Settings and enter a Coda API token.
Click Refresh after entering or changing the Coda token. The extension uses its local cache until Refresh is clicked.
If the saved doc or table is not in the current cache, click Refresh. The doc or table may have been renamed, deleted, moved, or the token may no longer have access.
Confirm:
- The backend URL is correct.
- The backend is running.
- The bookmark API key matches the backend.
- The Coda token is valid.
- The selected doc and table are still accessible.
The extension sends one request to /api/save-bookmark per successful click. If you see multiple /api/workflow/save-bookmark logs, that is usually the backend workflow runner retrying a failed workflow request.
- The bookmark API key is sent only in the
x-api-keyheader. - The Coda token is sent only in the
Authorizationheader. - Neither secret is sent in the JSON body.
- Neither secret is sent in the query string.
- Secrets are not written to popup status messages.