Skip to content

feat: implement real-time dashboard sync via Pusher - #696

Merged
vishnukothakapu merged 1 commit into
vishnukothakapu:mainfrom
Dev1822:feat/real-time-sync
Aug 14, 2026
Merged

feat: implement real-time dashboard sync via Pusher#696
vishnukothakapu merged 1 commit into
vishnukothakapu:mainfrom
Dev1822:feat/real-time-sync

Conversation

@Dev1822

@Dev1822 Dev1822 commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Description

Integrates Pusher WebSockets to enable real-time synchronization across the LinkID dashboard. When a user updates, deletes, or adds their links on one device (e.g., their mobile phone), the dashboard UI automatically and seamlessly updates on all other active devices without requiring a manual page refresh.

Closes #692

Changes Made

  • Dependencies: Added pusher and pusher-js.
  • Backend Utilities: Created a server-side lib/pusher.ts instance to handle Pusher events.
  • API Routes:
    • Added a new secure endpoint /api/pusher/auth to authenticate NextAuth sessions and ensure users can only subscribe to their own private channels (private-user-[userId]).
    • Updated the links API endpoints (links/route.ts, links/[id]/route.ts, and links/reorder/route.ts) to broadcast a links-updated event to the user's private channel whenever links are mutated.
  • Frontend Dashboard:
    • Updated DashboardClient.tsx to instantiate the Pusher client and subscribe to the user's private channel.
    • Added a useEffect hook that triggers router.refresh() upon receiving a links-updated event, seamlessly fetching the latest state from the server.

Setup Instructions for Reviewers

To test this locally, you will need to create a free Pusher account, create an App channels instance, and add the following keys to your .env:

PUSHER_APP_ID=your_app_id
NEXT_PUBLIC_PUSHER_KEY=your_key
PUSHER_SECRET=your_secret
NEXT_PUBLIC_PUSHER_CLUSTER=your_cluster

Verification

  1. Login and open your dashboard in two separate browser windows (or devices).
  2. Add, edit, reorder, or delete a link in Window A.
  3. Observe Window B instantly sync the changes without a manual refresh.

Summary by CodeRabbit

  • New Features
    • Added workspace-aware link management, including creation, retrieval, reordering, and workspace-specific settings.
    • Added webhook configuration with signing secret display and HMAC-signed click notifications.
    • Added authenticated real-time channel support for live updates.
    • New accounts automatically receive a workspace with owner access.
  • Bug Fixes
    • Improved workspace validation and access handling across dashboard settings.
    • Webhook delivery failures no longer interrupt successful link-click responses.

@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

@Dev1822 is attempting to deploy a commit to the vishnukothakapu's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Dev1822, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 41 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 54712f4c-f66b-402b-b383-4030c59bd86f

📥 Commits

Reviewing files that changed from the base of the PR and between 601e023 and eb021b3.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • app/api/links/[id]/route.ts
  • app/api/links/reorder/route.ts
  • app/api/links/route.ts
  • app/api/pusher/auth/route.ts
  • app/dashboard/DashboardClient.tsx
  • app/dashboard/page.tsx
  • lib/pusher.ts
  • package.json
📝 Walkthrough

Walkthrough

User registration now creates a workspace and owner membership. Link and profile APIs use workspace context. The dashboard adds webhook configuration, and click events can trigger signed webhooks. Pusher server, client, and private-channel authentication support are added.

Changes

Workspace scoping

Layer / File(s) Summary
Workspace creation and resolution
app/api/auth/register/route.ts, lib/workspace.ts
Registration creates a workspace and owner membership. Shared utilities resolve active workspaces and verify membership.
Workspace-scoped link APIs
app/api/links/route.ts, app/api/links/reorder/route.ts
Link creation, retrieval, validation, ordering, and updates now use the resolved workspace.
Workspace profile settings
app/api/user/layout/route.ts, app/api/user/seo/route.ts, app/api/user/theme/route.ts
Layout, SEO, and theme updates now target the active workspace.

Webhook configuration and delivery

Layer / File(s) Summary
Webhook storage and settings
prisma/schema.prisma, app/api/settings/route.ts
User webhook URL and secret fields are added. Settings updates preserve, generate, or clear the signing secret.
Webhook dashboard configuration
app/dashboard/page.tsx, app/dashboard/DashboardClient.tsx, app/dashboard/WebhookSection.tsx
The dashboard adds a Webhooks tab with URL and signing secret controls.
Signed click dispatch
app/api/links/click/route.ts
Click events can send HMAC-SHA256-signed JSON POST requests to the configured webhook URL.

Pusher authentication infrastructure

Layer / File(s) Summary
Private channel authentication
lib/pusher.ts, app/api/pusher/auth/route.ts
Shared Pusher configuration and a session-protected private-channel authentication endpoint are added.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant LinkClickClient
  participant ClickRoute
  participant WebhookEndpoint
  LinkClickClient->>ClickRoute: Record link click
  ClickRoute->>ClickRoute: Create HMAC-SHA256 signature
  ClickRoute->>WebhookEndpoint: Send signed JSON POST
  WebhookEndpoint-->>ClickRoute: Return response or failure
  ClickRoute-->>LinkClickClient: Return click response
Loading

Possibly related PRs

Suggested labels: feature, type:feature

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR adds Pusher setup and authentication, but the summaries do not show link-mutation broadcasts or dashboard subscription handling. Add broadcasts for every link mutation and subscribe DashboardClient.tsx to the private channel with refresh handling.
Out of Scope Changes check ⚠️ Warning The PR includes extensive workspace scoping and webhook configuration changes that are unrelated to real-time dashboard synchronization. Move workspace and webhook changes to separate PRs, or document linked requirements that justify them.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the intended Pusher-based real-time dashboard synchronization feature.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/api/auth/register/route.ts`:
- Around line 49-73: Add Workspace and WorkspaceMember models, their user/link
relations, and Link.workspaceId to prisma/schema.prisma so the registration
transaction and workspace-scoped link queries work. Add a migration that creates
the workspace and membership tables, creates a workspace and OWNER membership
for every existing user, assigns each user’s links to that workspace, and copies
the existing layout, SEO, and theme values into the workspace records. Update
app/api/auth/register/route.ts, app/api/links/route.ts,
app/api/user/layout/route.ts, app/api/user/seo/route.ts, and
app/api/user/theme/route.ts as needed to use the new schema consistently.

In `@app/api/links/click/route.ts`:
- Around line 70-78: Update the webhook dispatch in the click route to run
through the supported after() background mechanism instead of an unawaited fetch
before returning. Await the POST request within the after() callback, add a
short request timeout, and retain the existing payload, headers, and error
logging.

In `@app/api/pusher/auth/route.ts`:
- Around line 14-24: Update the parameter parsing in the Pusher auth route to
use URLSearchParams, retrieving values by the socket_id and channel_name keys
with URL decoding handled automatically. Validate both values before the
private-channel authorization check and return a 400 Bad Request response when
either is missing; preserve the existing session ownership check and
authorization flow for valid requests.

In `@app/api/settings/route.ts`:
- Around line 24-35: Restrict webhook destinations in app/api/settings/route.ts
lines 24-35 by validating and normalizing the URL before assigning
updateData.webhookUrl: require a valid URL with an HTTPS scheme, resolve its
hostname, and reject loopback, private, link-local, metadata, and other reserved
addresses. In app/api/links/click/route.ts lines 71-78, apply the same egress
validation immediately before dispatch and configure the request to reject
redirects.
- Around line 16-34: Fix the ESLint issues in the settings update handler by
declaring updateData as const with an explicit appropriate type, and replace the
inline require('crypto') call with a module-scope randomBytes import. Keep the
existing webhookSecret generation behavior in the webhookUrl update path
unchanged.

In `@lib/pusher.ts`:
- Around line 1-2: Add pusher and pusher-js to the project's dependencies, then
regenerate package-lock.json so both packages and their resolved dependency
metadata are recorded. Keep the existing imports in lib/pusher.ts unchanged.

In `@lib/workspace.ts`:
- Around line 4-24: Update getActiveWorkspace in lib/workspace.ts so a supplied
workspace ID that lacks membership returns null instead of falling back to the
earliest workspace; use the default workspace only when no ID was supplied. In
app/api/links/route.ts lines 51-57 and 303-307, app/api/links/reorder/route.ts
lines 26-29, app/api/user/layout/route.ts lines 27-28, app/api/user/seo/route.ts
lines 36-37, and app/api/user/theme/route.ts lines 24-25, preserve the existing
failure behavior when the workspace lookup returns null and prevent reads or
updates against the default workspace.

In `@prisma/schema.prisma`:
- Around line 65-66: Add and deploy a Prisma migration for the `webhookUrl` and
`webhookSecret` fields in the relevant model, ensuring existing databases
receive both nullable columns queried by the routes. Keep the schema and
generated migration aligned.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 54de3406-2bf4-4b33-a541-4dc76ba1bfb9

📥 Commits

Reviewing files that changed from the base of the PR and between 2b9548d and 601e023.

📒 Files selected for processing (15)
  • app/api/auth/register/route.ts
  • app/api/links/click/route.ts
  • app/api/links/reorder/route.ts
  • app/api/links/route.ts
  • app/api/pusher/auth/route.ts
  • app/api/settings/route.ts
  • app/api/user/layout/route.ts
  • app/api/user/seo/route.ts
  • app/api/user/theme/route.ts
  • app/dashboard/DashboardClient.tsx
  • app/dashboard/WebhookSection.tsx
  • app/dashboard/page.tsx
  • lib/pusher.ts
  • lib/workspace.ts
  • prisma/schema.prisma

Comment thread app/api/auth/register/route.ts Outdated
Comment thread app/api/links/click/route.ts Outdated
Comment thread app/api/pusher/auth/route.ts
Comment thread app/api/settings/route.ts Outdated
Comment thread app/api/settings/route.ts Outdated
Comment thread lib/pusher.ts
Comment thread lib/workspace.ts Outdated
Comment thread prisma/schema.prisma Outdated
@vercel

vercel Bot commented Aug 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
linkid Ready Ready Preview Aug 14, 2026 3:51pm

@vishnukothakapu

Copy link
Copy Markdown
Owner

pls resolve the merge conflicts @Dev1822

@vishnukothakapu

Copy link
Copy Markdown
Owner

also, the Vercel build is failing on feat/real-time-sync.

It’s the same Prisma issue as before — workspaceId is being added as a required field to existing tables (ClickEvent, DailyLinkAnalytics, Link, and ProfileVersion), but those tables already have data.

Could you take a look at the migration/backfill for the existing rows? Using --force-reset would wipe the database, so we should avoid that.

@Dev1822

@vishnukothakapu

Copy link
Copy Markdown
Owner

@Dev1822 , the Vercel build is still failing on feat/real-time-sync.

The only errors now are that pusher and pusher-js can’t be resolved from lib/pusher.ts. It’s being imported by both the links API and DashboardClient.

Looks like the two packages are missing from the branch’s dependencies. Could you check package.json/package-lock.json and add them if needed?

@Dev1822
Dev1822 force-pushed the feat/real-time-sync branch 2 times, most recently from b4fff2d to b868ece Compare August 14, 2026 14:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] Real-Time Dashboard Sync (WebSockets)

3 participants