6.7 KiB
Plan: Overhaul Content Detection + Add Apps Tab
Context
The content surfacing system misses many common AI response patterns. Example: AI responds about Nostr (mentioning damus.io, primal.net, snort.social) but the Nostr tab never surfaces. Query/response classifiers use narrow regexes that miss natural language variations. There's no "topic detection" layer, no app detection, and bare domains in AI text aren't extracted as websites.
Goals:
- Fix content detection to handle how AIs actually respond
- Add Nostr tab surfacing (currently only via
/nostrcommand) - Add Apps tab with curated Nostr + Bitcoin ecosystem apps (local DB + AI extraction fallback)
- Extract bare domains from AI text (e.g. "check out damus.io")
Part 1: Expand Query & Response Classifiers
File: packages/app/src/composables/contentFiltering.ts
1A. Add Nostr classifiers (new functions)
isNostrQuery(q)— matches: nostr, npub, nip-\d, damus, primal, snort, amethyst, coracle, zap, relay, note1, nevent, nprofile, fiatjaf, nostrich, "decentralized social"isNostrLikeResponse(text)— requires literal "nostr" OR 2+ Nostr-specific signals (npub, nip-, client names, relay+wss, zap+lightning)
1B. Add App classifiers (new functions)
isAppQuery(q)— matches: app, client, wallet, tool, software, download, install, "what app", "best app for", "recommend.*app"isAppLikeResponse(text)— matches: "you can use", "popular clients include", "I'd recommend", "available on", "download from"
1C. Expand existing classifiers with broader patterns
| Classifier | Add these patterns |
|---|---|
isNewsQuery |
"what happened today", "any updates on", "trending", "catch me up", "brief me", "current events" |
isMusicQuery |
"genre", "spotify", "bandcamp", "grammys", "billboard", "mixtape", "discography", "banger", "favorite jam" |
isBookQuery |
"what should I read", "favorite reads", "reading list", "book club", "memoir", "audiobook", "goodreads", "worth reading" |
isTVQuery |
"what's good on netflix", "anything to binge", "hbo", "disney+", "apple tv", "amazon prime", "docuseries", "limited series" |
isPlaceQuery |
"hungry", "food near me", "best brunch spot", "happy hour", "speakeasy", "rooftop bar", "food truck" |
isWebsitesQuery |
"point me to", "link me", "any good sites", "tools for", "platforms for" |
isWebsitesLikeResponse |
"here are some resources", "I'd recommend checking", "you can visit", "useful resources" |
isNewsLikeResponse |
"I can't access the web but", "having trouble reaching", "unable to browse but" |
1D. Update preferredFirstTab() — add nostr + app checks
1E. Update filterTabsByContext() — add hasNostr and hasApps params, integrate into tab ordering
Part 2: Bare Domain Extraction
File: packages/app/src/composables/contentExtraction.ts
Add extractBareDomainLinks(text):
- Detect plain-text domains like "damus.io", "primal.net" not inside markdown links or bold patterns
- Skip positions covered by existing extractors (markdown links, bold-domain, full URLs)
- Require known TLDs (.com, .org, .io, .net, .social, .app, etc.)
- Block file extensions (.js, .ts, .vue, .json, .css)
- Use existing
normUrl()for dedup
Part 3: Apps Tab — Curated Database + AI Extraction
3A. Create app database
New file: packages/app/src/data/apps.ts
interface AppEntry {
id: string
name: string
description: string // One-liner
longDescription: string // Why use this, how it works
category: 'nostr-client' | 'lightning-wallet' | 'bitcoin-wallet' | 'privacy' | 'node' | 'dev-tool' | 'relay'
platforms: ('ios' | 'android' | 'web' | 'desktop' | 'cli' | 'nodeos')[]
url: string
icon?: string
keywords: string[] // For matching AI responses
howTo?: string[] // Getting started steps
relatedApps?: string[] // IDs of related apps
}
Initial curated apps (~25-30):
- Nostr clients: Damus, Primal, Snort, Amethyst, Coracle, Iris, Nostrudel, nos.social
- Lightning wallets: Phoenix, Mutiny, Breez, Zeus, Alby, Wallet of Satoshi
- Bitcoin wallets: Sparrow, Blue Wallet, Nunchuk, Coldcard, Green
- Privacy tools: Tor, SimpleX Chat, Signal, Mullvad VPN
- Node software: Start9, Umbrel, RaspiBlitz, myNode
- Dev tools: NDK, nostr-tools, Nak
3B. Add app extraction
File: packages/app/src/composables/contentExtraction.ts
Add extractApps(text, userQuery):
- Match AI text against known app names/keywords from database
- If app query detected OR 2+ known apps mentioned → return matched apps
- For unknown apps, create basic entries from context (name + URL if bare domain found)
3C. Create UI components
New files:
packages/app/src/components/content/AppsGrid.vue— Grid of app cards (icon, name, category badge, one-liner)packages/app/src/components/content/AppDetail.vue— Detail: icon, name, platforms, long description, how-to steps, link, related apps
Follow existing grid/detail patterns (e.g. BookGrid.vue/BookDetail.vue).
3D. Register in ContentPanel.vue
Add rendering for activeTab === 'app', add 'app' to ContentTab type.
Part 4: Wire Everything Together
File: packages/app/src/composables/useContentPanel.ts
In updatePanelFromText():
- Call
extractBareDomainLinks(text), merge with website sources - Call
extractApps(text, userQuery) - Compute
hasNostr = isNostrQuery(userQuery) || isNostrLikeResponse(text) - Compute
hasApps = apps.length > 0 - Pass
hasNostrandhasAppstofilterTabsByContext() - Add
panelAppsref, title logic for apps/nostr tabs
Same changes in getContextualInlineContent().
Broaden magazine detection: add tech/protocol keywords, surface magazine for 3+ sections with no other structured content.
Part 5: PromptIndex badges
File: packages/app/src/components/chat/PromptIndex.vue
Add 'Nostr' and 'Apps' badge detection.
Implementation Order
contentFiltering.ts— classifiers + filterTabsByContext signaturecontentExtraction.ts—extractBareDomainLinks()+extractApps()data/apps.ts— curated app databaseuseContentPanel.ts— wire everythingAppsGrid.vue+AppDetail.vue— UI componentsContentPanel.vue— register tab + componentsPromptIndex.vue— badges- Typecheck + manual test
Verification
pnpm typecheckpasses- "tell me about Nostr" → Nostr + magazine tabs surface
- "best Nostr clients?" → Apps tab with Damus, Primal, Snort
- "recommend a bitcoin wallet" → Apps tab with Phoenix, Sparrow
- "what happened with BIP 110?" → Magazine tab (regression)
- "best movies of 2024" → Films tab (regression)
- Bare domains in AI text extracted as websites
- PromptIndex badges show Nostr/Apps