A Tampermonkey userscript that captures articles from any website, extracts metadata, tags entities, identifies claims with evidence linking, and publishes to NOSTR relays. All cryptography β including secp256k1, BIP-340 Schnorr signing, NIP-44 v2 encryption, and bech32 encoding β is implemented from scratch with zero external crypto dependencies.
π Successor Project β X-Ray Browser Extension Multi-platform capture (social media, video, etc.) has moved to a dedicated browser extension: bryanmatthewsimonson/xray β Chrome/Firefox WebExtension (MV3), no userscript manager required. X-Ray covers article capture, URL-scoped metadata (annotations, fact-checks, ratings, comments, headline corrections), and is the active development target for platform-specific capture. This userscript remains the focused, stable article-capture tool.
Prerequisites: Tampermonkey browser extension.
The script auto-updates via @updateURL / @downloadURL in the userscript header. External dependencies are loaded via CDN @require tags:
| Dependency | Version | Purpose |
|---|---|---|
| @mozilla/readability | 0.5.0 | Article content extraction |
| Turndown | 7.2.0 | HTML β Markdown conversion |
| turndown-plugin-gfm | 1.0.2 | GitHub-Flavored Markdown tables & strikethrough |
- One-click capture via a floating action button (FAB) in a Shadow DOM container β immune to page CSS interference
- Mozilla Readability extracts title, author, date, and body from any article
- Smart date detection β JSON-LD, meta tags (
article:published_time,datePublished) - Trusted Types CSP compatibility β works on sites with strict Content Security Policy headers
- Editable URL β canonical URL displayed and editable; tracking parameter cleanup
- Full-page reader view with clean typography and optimal reading width
- WYSIWYG visual editor β
contentEditablerich-text editing directly in the reader view - Raw markdown editor β toggle between visual and markdown mode (auto-resizing textarea)
- Preview as Published β HTML β markdown β HTML roundtrip to see exactly what NOSTR will display
- Inline metadata editing β click author, publication, date, or URL to edit in place
- Dark mode support via
prefers-color-scheme - Mobile responsive β adaptive layout for mobile and tablet screens
- Four entity types: Person π€, Organization π’, Place π, Thing π·
- Text selection popover β select text in content, choose entity type from a floating popover
- Manual tagging β add entities by name via the "+ Tag Entity" button
- Auto-detection β author (Person) and publication (Organization) automatically tagged on capture
- Keypair per entity β each entity gets its own secp256k1 keypair (npub/nsec) for NOSTR identity
- Entity aliases (
canonical_id) β entities can be linked as aliases of a canonical entity - Auto-suggestion β automatically detects known entities from your registry in content text
- Entity browser with search and type filtering (All / π€ / π’ / π / π·)
- Entity detail view β rename, manage aliases, view keypair (npub/nsec with copy), articles list
- JSON export/import for full entity registry backup and restore
- π Claim button in the text selection popover β select any text and extract it as a claim
- Claim types β classify claims as Factual, Causal, Evaluative, or Predictive
- Crux marking β mark key claims as "crux" (the most important claims)
- Confidence slider β set confidence level (0β100%) on crux claims
- Structured claim triples β
[Subject] β [Predicate] β [Object]with entity references or freetext - Attribution types β direct quote, paraphrase, editorial assertion, or article thesis
- Quote date β when the statement was made (distinct from article publish date)
- Claims bar β displays extracted claims with type badges, claimant labels, and crux indicators
- Per-URL persistence β claims stored per article URL and reloaded on revisit
- π button on each claim opens the evidence linker modal
- Cross-content linking β link claims across different articles as supporting, contradicting, or contextualizing evidence
- Relationship types β supports β , contradicts β, contextualizes π
- Evidence indicators β claims with evidence links show a π badge with link count
- π button in the claims bar fetches kind 30040 claim events from relays for the current URL
- Grouped by publisher β remote claims organized by npub, filtering out your own
- Cross-user claim discovery β see what claims others have extracted from the same content
Six event kinds are published:
| Kind | Purpose |
|---|---|
| 0 | Entity profiles (with refers_to for aliases) |
| 30023 | Long-form content (articles in Markdown) |
| 30040 | Claims (structured triples, crux, confidence) |
| 30043 | Evidence links (supports/contradicts/contextualizes) |
| 30078 | Entity sync (NIP-44 encrypted) |
| 32125 | Entity relationships (author, mentioned, claimant, subject) |
Two signing methods:
| Method | Description |
|---|---|
| NIP-07 Extension | Browser extensions like nos2x or Alby β keys never leave the extension |
| Local Keypair | BIP-340 Schnorr signing with a locally generated or imported key |
- Parallel relay publishing via
Promise.allSettled()β events sent to all selected relays concurrently - Event preview β inspect the full event JSON before publishing
All cryptographic operations implemented in pure JavaScript:
| Primitive | Implementation |
|---|---|
| secp256k1 | Key generation, public key derivation (BigInt field arithmetic) |
| BIP-340 Schnorr | Signing and verification |
| Bech32 | Encoding/decoding (npub/nsec) via BIP-173 |
| ECDH | Shared secret derivation for NIP-44 conversation keys |
| ChaCha20 | Stream cipher (RFC 7539 quarter-round) |
| HKDF-SHA256 | Key derivation (extract + expand) |
| HMAC-SHA256 | Message authentication with constant-time comparison |
| NIP-44 v2 | Padded encryption (ChaCha20 + HMAC-SHA256 encrypt-then-MAC) |
| NIP-04 | AES-256-CBC encrypt/decrypt (legacy, via Web Crypto SubtleCrypto) |
| SHA-256 | Hashing via Web Crypto API |
GM_setValue/GM_getValuefor persistent Tampermonkey storage withlocalStoragefallback (iOS)- Storage quota monitoring β color-coded display in settings (green β orange at 1 MB β red at 5 MB)
- Size breakdown β entities, identity, relays, claims shown separately
- Compression fallback β
_compressForSave()strips optional fields when writes fail - Graceful error handling β storage save failures show user-facing toasts
- Responsive design β mobile-friendly FAB positioning and layout
- Dark mode β full
prefers-color-schemesupport - Shadow DOM FAB β floating action button isolated from page CSS via closed shadow root (with regular DOM fallback)
- ARIA labels on interactive elements
- Focus trap within the reader view β Tab / Shift+Tab cycles through focusable elements
- Panel stack Escape handling β Escape closes the topmost overlay in order
:focus-visiblestyling for clear keyboard focus indicators
- Navigate to any article
- Click the floating action button (π° bottom-right corner)
- Read the content in the clean reader view
- Edit metadata β click author, publication, date, or URL to edit inline
- Toggle Edit mode for content editing (visual WYSIWYG or raw markdown)
- Tag entities β select text to tag people, orgs, places, or things
- Extract claims β select text and click π Claim with type classification and crux marking
- Preview as Published β check the final markdown roundtrip format
- Publish β click Publish β select relays and signing method β publish to NOSTR
- Settings β manage identity (generate, import nsec, NIP-07), relays, entities, sync
| Kind | Name | Usage |
|---|---|---|
| 0 | Profile Metadata (NIP-01) | Optional public identity for entities; alias entities include ["refers_to", canonical_npub] |
| 30023 | Long-form Content (NIP-23) | Articles in Markdown with entity p tags and claim summary tags |
| 30040 | Claim Event | Individual claim with claimant/subject/object p tags, predicate, quote-date, attribution type, confidence, crux flag |
| 30043 | Evidence Link | Cross-content claim relationship: supports, contradicts, or contextualizes |
| 30078 | Application Data (NIP-78) | Encrypted entity sync (NIP-44 v2 encrypt-to-self; NIP-04 fallback on read) |
| 32125 | Entity Relationship | Links an entity to content with a typed relationship (author, mentioned, claimant, subject) |
{
"kind": 30040,
"tags": [
["d", "claim_abc123"],
["r", "https://example.com/article"],
["claim-text", "The unemployment rate dropped to 3.4%"],
["claim-type", "factual"],
["attribution", "direct_quote"],
["confidence", "85"],
["crux", "true"],
["p", "<claimant-pubkey>", "", "claimant"],
["claimant", "Larry Summers"],
["predicate", "dropped to"],
["quote-date", "2024-01-15"],
["client", "nostr-article-capture"]
],
"content": "surrounding context text"
}{
"kind": 30043,
"tags": [
["d", "evidence_link_id"],
["source-claim", "claim_abc123"],
["target-claim", "claim_def456"],
["relationship", "supports"],
["r", "https://example.com/article-1"],
["r", "https://example.com/article-2"],
["client", "nostr-article-capture"]
],
"content": "optional explanation note"
}{
"kind": 32125,
"tags": [
["d", "<entity-id>:<article-url>:<relationship>"],
["r", "https://example.com/article"],
["p", "<entity-pubkey>", "", "author"],
["entity-name", "Helen Andrews"],
["entity-type", "person"],
["relationship", "author"],
["client", "nostr-article-capture"]
],
"content": ""
}| NIP | Name | Usage |
|---|---|---|
| NIP-01 | Basic Protocol | Event structure, relay communication (EVENT, OK, NOTICE, REQ, CLOSE) |
| NIP-04 | Encrypted Direct Messages | Legacy AES-256-CBC encryption (fallback for reading older entity sync events) |
| NIP-07 | Browser Extension Signing | window.nostr.signEvent() and window.nostr.getPublicKey() integration |
| NIP-19 | Bech32 Encoding | npub / nsec key encoding and decoding |
| NIP-23 | Long-form Content | Kind 30023 events for articles |
| NIP-32 | Labels | L/l label tags on entity sync events for app-specific categorization |
| NIP-33 | Parameterized Replaceable | Kinds 30023, 30040, 30043, 30078, 32125 β all replaceable by d tag |
| NIP-44 | Versioned Encryption | v2 padded encryption (ChaCha20 + HMAC-SHA256) for entity sync |
| NIP-78 | Application-specific Data | Kind 30078 events for storing encrypted entity data on relays |
Pre-configured with 10 public relays:
wss://nos.lol Β· wss://relay.primal.net Β· wss://relay.nostr.net Β· wss://nostr.mom Β· wss://relay.nostr.bg Β· wss://nostr.oxtr.dev Β· wss://relay.snort.social Β· wss://offchain.pub Β· wss://nostr-pub.wellorder.net Β· wss://nostr.fmt.wiz.biz
| File | Tests | Coverage |
|---|---|---|
tests/crypto-tests.js |
65 | secp256k1 key generation, BIP-340 Schnorr vectors, bech32 encode/decode, SHA-256, ECDH, NIP-04, event signing |
tests/nip44-test.js |
5 | ChaCha20 RFC 7539 vectors, NIP-44 padding, pad/unpad roundtrip, encrypt/decrypt roundtrip, HMAC tamper detection |
node tests/crypto-tests.js && node tests/nip44-test.jsnostr-article-capture/
βββ nostr-article-capture.user.js # Single-file userscript (monolith)
βββ tests/
β βββ crypto-tests.js # 65 crypto tests
β βββ nip44-test.js # 5 NIP-44 tests
βββ docs/
β βββ project-history-and-migration.md # Complete project history & X-Ray migration guide
β βββ data-model.md # Entity, claim, evidence data structures
β βββ entity-hierarchy-design.md # Entity alias system design
β βββ entity-sync-design.md # NIP-78 encrypted sync protocol
β βββ archive-reader-design.md # Archive reader design (reference)
β βββ nostr-nips-analysis.md # NIP usage and rationale
β βββ article-data-collection.md # Article capture field reference
β βββ article-complete-inventory.md # Full inventory of captured data
β βββ tampermonkey-article-capture-plan.md # Original v1 plan
βββ README.md
| Document | Description |
|---|---|
| Project History & Migration Guide | Complete project history (v1βv4), data model reference, and X-Ray browser extension migration guide |
| Data Model | Entity, claim, and evidence data structures |
| Entity Hierarchy Design | Entity alias system and canonical_id design |
| Entity Sync Design | NIP-78 encrypted sync protocol (NIP-44 + NIP-04 fallback) |
| NOSTR NIPs Analysis | NIP usage and rationale |
X-Ray Browser Extension β A Chrome/Firefox WebExtension (MV3) that extends article capture with multi-platform support (social media, video, etc.), URL-scoped metadata, and the platform-specific capture features that were explored in v3/v4 of this userscript. See docs/project-history-and-migration.md for the full migration story.
- Readability β Article content extraction
- Turndown β HTML to Markdown conversion
MIT License