Feature: Personalized developer activity and watchlist feed - #142
Merged
sajeetharan merged 13 commits intoAug 13, 2026
Merged
Conversation
Implement functions to save and list feed events with memory fallback.
|
@HereIsMuhammad is attempting to deploy a commit to the sajeetharan's projects Team on Vercel. A member of the Team first needs to authorize it. |
Contributor
There was a problem hiding this comment.
Pull request overview
Implements the backend and core logic for a personalized developer feed built from a signed-in user’s watchlists, with privacy/mute filtering, grouping/compaction, cursor pagination, and read-state support, plus an internal ingest endpoint and a PRD describing the contract.
Changes:
- Added feed event normalization + personalization pipeline (watchlist match → mute → sort/group → filter → cursor pagination + read state).
- Added Cosmos-backed storage for feed events and per-user watchlist/mute/read-state data (with in-memory fallbacks).
- Added API routes for listing/marking read, muting/unmuting, and internal ingestion; added unit tests for feed logic.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/feed.test.js | Adds unit coverage for feed normalization, matching, muting, grouping, sorting, read-state, and pagination. |
| lib/watchlist-store.js | Adds minimal watchlist storage for follows/mutes/read-state with Cosmos + in-memory fallback. |
| lib/feed.js | Implements feed event model + personalization pipeline utilities. |
| lib/feed-store.js | Adds Cosmos + in-memory feed event persistence and candidate listing. |
| docs/prd/personalized-developer-feed.md | Documents the PRD/spec and API contract for the personalized feed MVP. |
| app/api/feed/route.js | Adds authenticated GET feed endpoint and PATCH read-state updates. |
| app/api/feed/mute/route.js | Adds authenticated mute/unmute endpoint for entities and event types. |
| app/api/feed/ingest/route.js | Adds bearer-secret internal ingestion endpoint for publishing feed events. |
Suppressed comments (1)
lib/feed-store.js:51
- The Cosmos query in
listCandidateFeedEventsalso doesn't filtervisibility, even though the docstring says it returns public events. Addingc.visibility = "public"keeps the candidate pool smaller and makes the store-layer privacy boundary harder to accidentally bypass.
const { resources } = await container.items.query({
query: 'SELECT * FROM c WHERE c.documentType = "feed-event" AND c.createdAt >= @cutoff',
parameters: [{ name: '@cutoff', value: cutoff }],
}).fetchAll();
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+44
to
+46
| if (!container) { | ||
| return [...memoryEvents.values()].filter(event => event.createdAt >= cutoff); | ||
| } |
Comment on lines
+57
to
+62
| const candidates = await listCandidateFeedEvents(); | ||
| const now = new Date().toISOString(); | ||
| const latest = candidates.length ? candidates.reduce((max, e) => (e.createdAt > max.createdAt ? e : max)) : null; | ||
| const cursor = latest ? { createdAt: latest.createdAt, id: latest.id } : { createdAt: now, id: '' }; | ||
| const watchlist = await markAllRead(session.login, cursor); | ||
| return NextResponse.json({ readState: watchlist.readState }); |
Comment on lines
+65
to
+68
| if (Array.isArray(body.eventIds) && body.eventIds.length) { | ||
| const watchlist = await markRead(session.login, body.eventIds); | ||
| return NextResponse.json({ readState: watchlist.readState }); | ||
| } |
Comment on lines
+31
to
+33
| try { | ||
| const result = await saveFeedEvents(body.events, { isPublicDeveloper: body.isPublicDeveloper !== false }); | ||
| return NextResponse.json(result); |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #127
Summary
Adds a personalized, chronological feed built from a signed-in developer's watchlists (followed developers, projects, languages, countries) and DevGlobe's contribution snapshots. Surfaces meaningful changes — rank movement, milestones, new top projects, and profile updates — instead of a generic social stream.
See
docs/prd/personalized-developer-feed.mdfor the full spec and API contract.What's included
lib/feed.js— event normalization, watchlist matching, mute/privacy filtering, grouping/compaction, cursor pagination, read statelib/feed-store.js— Cosmos-backed feed event store with in-memory fallback (mirrorslib/activity-store.jsconventions)lib/watchlist-store.js— minimal follow/mute/read-state storage the feed reads from (full watchlist UI is Feature: Developer and project watchlists with update notifications #113)GET/PATCH /api/feed— list personalized feed, mark readPOST/DELETE /api/feed/mute— mute an entity or event typePOST /api/feed/ingest— internal bearer-secret endpoint for publishers to write feed eventstests/feed.test.js— authorization/privacy, ordering, deduplication, and pagination testsAcceptance criteria covered
Out of scope (documented in the PRD)