Server (Express + better-sqlite3 + FTS5, mirroring keep's stack): /api/capture (upsert-on-url, per PROPOSAL.md's dedup decision), /api/articles (list/search/mark-read/delete), plus a minimal server-rendered reading list and reader view at / and /read/:id (token passed as ?t= there since browser navigation can't set an Authorization header). Bearer-token auth generated via `npm run token` — no login flow, matching keep's one-time identity registration pattern. Extension (Manifest V3, sideloaded, no store distribution): toolbar click or context menu "Send to stash" runs @mozilla/readability (vendored into extension/lib/) against the current page, falling back to raw rendered HTML when extraction comes back too thin. Options page for one-time server URL + token entry. Verified end-to-end with the real extension loaded in a live Chromium instance (not just unit-tested extraction logic): capture against a real page, dedup-on-recapture, mark-read, FTS5 search, 401 on missing auth, and both server-rendered views all confirmed working. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
18 lines
616 B
JavaScript
18 lines
616 B
JavaScript
const serverUrlEl = document.getElementById('serverUrl');
|
|
const tokenEl = document.getElementById('token');
|
|
const statusEl = document.getElementById('status');
|
|
|
|
chrome.storage.local.get(['serverUrl', 'token']).then(({ serverUrl, token }) => {
|
|
if (serverUrl) serverUrlEl.value = serverUrl;
|
|
if (token) tokenEl.value = token;
|
|
});
|
|
|
|
document.getElementById('save').addEventListener('click', async () => {
|
|
await chrome.storage.local.set({
|
|
serverUrl: serverUrlEl.value.trim(),
|
|
token: tokenEl.value.trim(),
|
|
});
|
|
statusEl.textContent = 'Saved.';
|
|
setTimeout(() => { statusEl.textContent = ''; }, 2000);
|
|
});
|