[Draft] feat(nostr-feed): Reddit-style link aggregator #9

Open
padreug wants to merge 19 commits from feature/link-aggregator into main
Owner

Summary

Transform the nostr-feed module into a Reddit/Lemmy-style link aggregator with:

  • Link posts - External URLs with Open Graph previews
  • Media posts - Images/videos with inline display
  • Self posts - Text/markdown content
  • Threaded comments - Recursive comment trees with colored threading lines
  • Voting - Upvote/downvote with NIP-25 reactions (+/-)
  • Sorting - Hot, new, top (with time range), controversial

NIP Compliance

  • NIP-72: Moderated Communities (kind 34550)
  • NIP-22: Comments (kind 1111)
  • NIP-92: Media Attachments (imeta tags)
  • NIP-25: Reactions (upvote/downvote)

Phases Completed

  • Phase 1: Core Data Model
  • Phase 2: Post Creation (except pictrs integration)
  • Phase 3: Feed Display
  • Phase 4: Detail View

Future Work

  • Pictrs media upload integration
  • Phase 5: Communities (CommunityService, browser, moderation)

Test plan

  • Verify feed displays submissions with voting controls
  • Test upvote/downvote persistence across page refresh
  • Test comment creation and threading
  • Test inline reply forms
  • Verify theme-aware styling (light/dark mode)
  • Test sort options (hot, new, top with time range, controversial)

🤖 Generated with Claude Code

## Summary Transform the nostr-feed module into a Reddit/Lemmy-style link aggregator with: - **Link posts** - External URLs with Open Graph previews - **Media posts** - Images/videos with inline display - **Self posts** - Text/markdown content - **Threaded comments** - Recursive comment trees with colored threading lines - **Voting** - Upvote/downvote with NIP-25 reactions (`+`/`-`) - **Sorting** - Hot, new, top (with time range), controversial ### NIP Compliance - NIP-72: Moderated Communities (kind 34550) - NIP-22: Comments (kind 1111) - NIP-92: Media Attachments (imeta tags) - NIP-25: Reactions (upvote/downvote) ### Phases Completed - ✅ Phase 1: Core Data Model - ✅ Phase 2: Post Creation (except pictrs integration) - ✅ Phase 3: Feed Display - ✅ Phase 4: Detail View ### Future Work - [ ] Pictrs media upload integration - [ ] Phase 5: Communities (CommunityService, browser, moderation) ## Test plan - [ ] Verify feed displays submissions with voting controls - [ ] Test upvote/downvote persistence across page refresh - [ ] Test comment creation and threading - [ ] Test inline reply forms - [ ] Verify theme-aware styling (light/dark mode) - [ ] Test sort options (hot, new, top with time range, controversial) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
padreug added 13 commits 2026-01-01 20:03:39 +00:00
Implement Reddit-style link aggregator foundation using NIP-72 (Moderated
Communities) and NIP-22 (Comments) specifications.

New files:
- types/submission.ts: Complete type definitions for submissions, voting,
  communities, link previews, and ranking algorithms
- services/SubmissionService.ts: Core service for kind 1111 submission
  events with parsing, creation, voting, and comment threading
- services/LinkPreviewService.ts: Open Graph metadata fetching with
  caching, CORS proxy support, and oEmbed fallbacks
- composables/useSubmissions.ts: Vue composable for reactive submission
  state management
- LINK_AGGREGATOR_PLAN.md: Implementation roadmap

Features:
- Three post types: link, media, self (text)
- NIP-22 compliant community-scoped posts
- NIP-92 media attachments with imeta tags
- Hot/Top/New/Controversial ranking algorithms
- Threaded comment support
- Upvote/downvote via NIP-25 reactions

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Implement minimal, information-dense submission feed UI inspired by
old Reddit and Lemmy designs.

New components:
- VoteControls.vue: Compact vertical upvote/downvote arrows with score
- SubmissionThumbnail.vue: Small square thumbnail with fallback icons
- SubmissionRow.vue: Single submission row with title, metadata, actions
- SortTabs.vue: Sort tabs (hot, new, top, controversial) with time range
- SubmissionList.vue: Main container composing all components

UI features:
- Dense layout showing many items at once
- Hover-reveal secondary actions (share, save, hide, report)
- Domain display for link posts
- NSFW blur/badge support
- Rank numbers (optional)
- Time-ago formatting
- Score formatting (e.g., 1.2k)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add LinkAggregatorTest.vue with mock data and live submission views
- Include direct relay connection for testing kind 1111 events
- Add submission composer with self/link post types
- Add route at /link-aggregator-test

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add SubmissionDetail.vue for full post view with content display
- Add SubmissionComment.vue for recursive threaded comments
- Add SubmissionDetailPage.vue route wrapper
- Add /submission/:id route to module
- Update SubmissionList share URL to use correct route
- Update test page to navigate to detail view on click
- Update plan document with Phase 4 completion

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create SubmitComposer.vue with post type selector (text/link/media)
- Add debounced link preview fetching on URL input
- Wire up submission publishing via SubmissionService.createSubmission()
- Add /submit route with SubmitPage.vue wrapper
- Support community query param for pre-selection
- Include NSFW toggle and form validation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add createComment() method to SubmissionService for posting comments
- Add getSortedComments() with sort options: best, new, old, controversial
- Wire up comment submission in SubmissionDetail.vue
- Add comment sort dropdown in detail view
- Support replying to specific comments or root submission
- Display comment submission errors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add subscribeToSubmission() to fetch submission + comments by ID
- Fix isComment check order - check before parseSubmission (which fails for comments)
- Update comment count on submission when comments are added
- Add duplicate comment detection to prevent double-display
- Update useSubmission composable to auto-subscribe on mount

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add fetchCommentReactions() to load reactions for all comments after EOSE
- Add updateCommentVotes() to refresh comment votes from ReactionService
- Add dislikeEvent() and undislikeEvent() to ReactionService for downvotes
- Update downvoteComment() to use ReactionService for persistence
- Fix vote button styling in SubmissionComment to properly show active state
- Wire up comment vote handlers in SubmissionDetail

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Implement downvote() for submissions using dislikeEvent
- Add refreshAllSubmissionVotes() to update all votes after EOSE
- Refresh submission votes after loading reactions in both subscribe methods
- Fixes vote state not displaying correctly on page load

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change border-* to bg-* classes so threading lines actually display
- Tighten spacing to match Lemmy-style threading (ml-0.5, pl-2, py-1)
- Rename borderColor to depthColor for accuracy

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add inline reply form that appears below the comment being replied to
- Pass replyingToId and isSubmittingReply props through comment tree
- Add cancel-reply and submit-reply events for inline form handling
- Top composer now only shows for new top-level comments
- Better UX: no need to scroll to top to reply to nested comments

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace hardcoded Tailwind colors with semantic chart-* colors that
adapt to light/dark theme.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace native HTML select with themed Select component for proper
dark mode support.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
padreug added 5 commits 2026-01-01 20:31:55 +00:00
Remove test page with mock data and test relay connection UI.
The link aggregator is now ready for production use.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add watchers to fetch profiles when submissions and comments load,
ensuring display names are shown instead of pubkeys.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The link aggregator is now the main feed, replacing the old NostrFeed
component. FAB button navigates to /submit for creating posts.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change SubmissionWithMeta from interface to type intersection
- Fix UseSubmissionsReturn types to use proper Ref/ComputedRef
- Remove unused imports across components and services

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Constrain feed content to max-w-4xl (896px) and center it, matching
the layout style of sites like programming.dev.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
padreug added 1 commit 2026-01-01 20:33:07 +00:00
Add spacing between header border and sort tabs for better visual
separation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
padreug force-pushed feature/link-aggregator from c4a62552cc to 7f4b1f1e9e 2026-01-03 07:55:18 +00:00 Compare
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feature/link-aggregator:feature/link-aggregator
git checkout feature/link-aggregator

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git checkout main
git merge --no-ff feature/link-aggregator
git checkout feature/link-aggregator
git rebase main
git checkout main
git merge --ff-only feature/link-aggregator
git checkout feature/link-aggregator
git rebase main
git checkout main
git merge --no-ff feature/link-aggregator
git checkout main
git merge --squash feature/link-aggregator
git checkout main
git merge --ff-only feature/link-aggregator
git checkout main
git merge feature/link-aggregator
git push origin main
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: aiolabs/webapp#9
No description provided.