Skip to content

[Dashboard][Backend][SDK] - Adds sharable session replay ids.#1294

Merged
madster456 merged 19 commits into
devfrom
dashboard/share-replays
Apr 28, 2026
Merged

[Dashboard][Backend][SDK] - Adds sharable session replay ids.#1294
madster456 merged 19 commits into
devfrom
dashboard/share-replays

Conversation

@madster456
Copy link
Copy Markdown
Collaborator

@madster456 madster456 commented Mar 27, 2026

Shareable Session Replay Links

Adds the ability to share individual session replays via unique, direct URLs.

https://www.loom.com/share/1e3298a19b114fc38af4bc43dcd5ec48

What changed

  • New admin endpoint — GET /api/v1/internal/session-replays/:id
  • Fetches a single session replay by ID with user metadata (display name, primary email) and chunk/event counts
  • Returns 404 if the replay doesn't exist
  • Admin-only access, consistent with the existing list endpoint

New standalone replay page — /projects/:projectId/analytics/replays/:replayId

  • Thin server page wrapper that passes the replay ID to the existing PageClient
  • PageClient detects standalone mode via initialReplayId prop and fetches replay metadata directly instead of loading the full session list
  • Sidebar is hidden; the replay viewer takes the full width
  • "Back to all replays" link shown under the page title

Copy link button

  • Moved from per-session sidebar items to the replay viewer header (next to the settings gear)
  • Copies a direct URL to the currently selected replay

SDK plumbing

  • AdminGetSessionReplayResponse type in stack-shared
  • getSessionReplay() on StackAdminInterface, StackAdminApp interface, and _StackAdminAppImplIncomplete

Tests

  • Happy path: fetch single replay by ID with inline snapshot
  • 404 for nonexistent replay ID
  • 401 for non-admin access (client and server)

Test plan

  • Open /analytics/replays, select a replay, click the link icon in the header — verify URL is copied to clipboard
  • Paste that URL in a new tab — verify the standalone replay page loads and plays the correct replay
  • Verify "Back to all replays" link navigates back to the list page
  • Verify the original /analytics/replays list page still works as before (selecting, filtering, pagination)
  • Run pnpm test run session-replays

Summary by CodeRabbit

  • New Features

    • Backend: internal endpoint to fetch a single session replay with user info, millisecond timestamps, and chunk/event counts.
    • Admin SDK/App: added response type and admin method to retrieve a single session replay; admin app maps response into the app model.
    • Dashboard: standalone session-replay page, UI adjustments for standalone mode, and a “copy replay link” button.
  • Tests

    • Added end-to-end tests for retrieval, not-found, and access-control scenarios.

…ionReplayId) method to StackAdminInterface class that sends a GET to /internal/session-replays/{id}
…nReplayId): Promise<AdminSessionReplay> to the StackAdminApp type
…essionReplay() and maps the snake_case API response to camelCase ADminSessionReplay.
…. Uses raw SQL to join SessinoReplay with ProjectUser and ContactChannel, aggregates chunk/event counts via Prisma groupBy. Returns 303 ItemNotFound if not found.
…and isStandaloneReplayPage derived flag. Added standalone replay fetching via adminApp.getSessionReplay() with loading/error state. Conditionally hides sidebar panel on standalone page. Added "Back to all replays" link under page title via PageLayout description prop. Added copy-link button to the header bar next to settings button. Changed viewer gate from selectedRecording to selectedRecordingId so standalone page can render before metadata loads.
…in get session replay returns 404 for nonexistent id, and non-admin access cannot call single session replay endpoint.
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 27, 2026

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

Project Deployment Actions Updated (UTC)
stack-auth-hosted-components Ready Ready Preview, Comment Apr 28, 2026 11:04pm
stack-backend Ready Ready Preview, Comment Apr 28, 2026 11:04pm
stack-dashboard Ready Ready Preview, Comment Apr 28, 2026 11:04pm
stack-demo Ready Ready Preview, Comment Apr 28, 2026 11:04pm
stack-docs Ready Ready Preview, Comment Apr 28, 2026 11:04pm
stack-preview-backend Ready Ready Preview, Comment Apr 28, 2026 11:04pm
stack-preview-dashboard Ready Ready Preview, Comment Apr 28, 2026 11:04pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 27, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds an admin-only internal GET endpoint to fetch a single session replay by ID, new backend query/aggregation/mapping helpers, dashboard standalone replay page/client support, shared admin API types/methods, template admin-app wiring, and E2E tests for access control and responses.

Changes

Cohort / File(s) Summary
Backend: New single-replay route
apps/backend/src/app/api/latest/internal/session-replays/[session_replay_id]/route.tsx
Adds a hidden admin GET route using createSmartRouteHandler with yup validation; uses tenancy-scoped Prisma, calls helpers, returns typed JSON or ItemNotFound.
Backend: Query & aggregation helpers
apps/backend/src/app/api/latest/internal/session-replays/session-replay-admin-rows.ts
New module exporting SessionReplayAdminListRow, SessionReplayChunkAgg, querySessionReplayAdminRows, aggregateSessionReplayChunksByReplayIds, and sessionReplayAdminRowToApiItem to centralize SQL, aggregation, and mapping.
Backend: route refactor (helper usage)
apps/backend/src/app/api/latest/internal/session-replays/route.tsx
Refactored to replace inline SQL/groupBy/mapping with the new helper functions.
Frontend: Standalone replay page & client
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/replays/[replayId]/page.tsx, apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/replays/page-client.tsx
Adds page passing initialReplayId to PageClient; PageClient accepts initialReplayId, fetches standalone replay via getSessionReplay, disables list init in standalone mode, adjusts selection/loading and UI (hide left panel, back link, copy-link button, standalone error banner).
E2E tests
apps/e2e/tests/backend/endpoints/api/v1/session-replays.test.ts
Adds tests: admin happy path (200 + payload), 404 for unknown UUID, and 401 for non-admin access types; tests create a replay and exercise access types.
Shared interface & types
packages/stack-shared/src/interface/crud/session-replays.ts, packages/stack-shared/src/interface/admin-interface.ts
Adds AdminGetSessionReplayResponse type and StackAdminInterface.getSessionReplay(sessionReplayId) method calling /internal/session-replays/{id}.
Template: admin app interface & impl
packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts, packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts
Adds getSessionReplay(sessionReplayId): Promise<AdminSessionReplay> to StackAdminApp and implements it in admin-app impl, mapping timestamps → Date and project_userprojectUser.

Sequence Diagram

sequenceDiagram
    actor User
    participant Browser as Dashboard (Browser)
    participant PageClient as PageClient (client)
    participant API as Backend API (/internal/session-replays)
    participant DB as Database (Prisma)

    User->>Browser: navigate to /replays/{replayId}
    Browser->>PageClient: mount with initialReplayId
    PageClient->>API: GET /internal/session-replays/{replayId} (admin credentials)
    API->>API: validate auth & params (yup)
    API->>DB: querySessionReplayAdminRows(tenancy, replayId)
    DB-->>API: session replay row (incl. project_user)
    API->>DB: aggregateSessionReplayChunksByReplayIds([replayId])
    DB-->>API: chunk_count & event_count
    API->>API: sessionReplayAdminRowToApiItem -> JSON response
    API-->>PageClient: 200 + replay payload
    PageClient->>Browser: set standaloneReplay state and render standalone view
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • N2D4

Poem

🐇 I hopped to fetch a replay by name,
Admin-only path, a tiny new claim.
From DB to dashboard the bytes softly flow,
Chunks counted, timestamps set to show.
A rabbit-cheer for one-id replay fame! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title '[Dashboard][Backend][SDK] - Adds sharable session replay ids' accurately summarizes the main change: introducing shareable direct URLs for individual session replays with backend, frontend, and SDK support.
Description check ✅ Passed The pull request description is comprehensive, detailing all changes across backend, frontend, SDK, and tests with clear explanations, a video link, and a manual test plan checklist.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dashboard/share-replays

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 and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 27, 2026

Greptile Summary

This PR adds shareable session replay links by introducing a new GET /api/v1/internal/session-replays/:id admin endpoint, a standalone /projects/:projectId/analytics/replays/:replayId dashboard page, and a copy-link button in the replay viewer header. The SDK is plumbed end-to-end (AdminGetSessionReplayResponseStackAdminInterface.getSessionReplay()_StackAdminAppImplIncomplete.getSessionReplay()), and three e2e tests cover the happy path, 404, and 401 cases.\n\nKey changes:\n- New backend route (route.tsx) fetches a single replay by ID with user metadata and chunk/event counts, using createSmartRouteHandler and parameterized SQL — consistent with the existing list endpoint.\n- PageClient is extended with an initialReplayId prop; in standalone mode the sidebar is hidden, metadata is fetched independently, and chunk downloading starts on the ID alone.\n- Copy-link button added to the replay viewer header; builds a direct URL to the replay.\n- One style issue: the copy-link button's async onClick does not use runAsynchronouslyWithAlert, so a clipboard permission error would be silently dropped with no user feedback.

Confidence Score: 5/5

Safe to merge — the single remaining finding is a P2 style issue (missing runAsynchronouslyWithAlert) that doesn't block the primary feature path.

All P0/P1 concerns are absent: the backend uses SmartRouteHandler with admin-only auth, SQL params are properly interpolated (no injection risk), cross-tenant isolation is enforced via tenancyId, the SDK types align exactly with the wire format, and three e2e tests cover the critical paths. The only open finding is a P2 style violation where the async clipboard handler should use runAsynchronouslyWithAlert.

apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/replays/page-client.tsx — copy-link async handler at line 1825.

Important Files Changed

Filename Overview
apps/backend/src/app/api/latest/internal/session-replays/[session_replay_id]/route.tsx New GET endpoint for fetching a single session replay by ID; uses SmartRouteHandler, admin-only auth, parameterized SQL (no injection risk), and consistent with the existing list endpoint pattern.
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/replays/[replayId]/page.tsx Thin Next.js server page wrapper that extracts replayId from URL params and passes it to the existing PageClient as initialReplayId. Clean and minimal.
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/replays/page-client.tsx Adds standalone replay mode via initialReplayId prop; sidebar hidden, metadata fetched separately, chunk download starts on ID alone. Copy-link async onClick is missing runAsynchronouslyWithAlert, so clipboard errors are silently dropped.
apps/e2e/tests/backend/endpoints/api/v1/session-replays.test.ts Adds three new tests: happy path with inline snapshot, 404 for nonexistent ID, and 401 for client/server access. Tests are well-structured and consistent with existing patterns.
packages/stack-shared/src/interface/admin-interface.ts Adds getSessionReplay() method that calls the new endpoint with URL-encoded ID; follows the same pattern as the surrounding listSessionReplays method.
packages/stack-shared/src/interface/crud/session-replays.ts Adds AdminGetSessionReplayResponse type that mirrors the backend response shape exactly.
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts Adds getSessionReplay() on _StackAdminAppImplIncomplete; correctly maps snake_case API response to camelCase AdminSessionReplay SDK type.
packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts Adds getSessionReplay to StackAdminApp interface and re-exports AdminSessionReplay; consistent with adjacent method declarations.

Sequence Diagram

sequenceDiagram
    participant Browser
    participant DashboardPage as Dashboard<br/>/replays/:replayId
    participant PageClient as PageClient<br/>(standalone mode)
    participant AdminApp as _StackAdminAppImpl
    participant Interface as StackAdminInterface
    participant Backend as GET /api/v1/internal<br/>/session-replays/:id
    participant DB as Database

    Browser->>DashboardPage: Navigate to /replays/:replayId
    DashboardPage->>PageClient: render with initialReplayId
    PageClient->>PageClient: isStandaloneReplayPage=true<br/>skip list/filter load
    PageClient->>AdminApp: getSessionReplay(replayId)
    AdminApp->>Interface: getSessionReplay(replayId)
    Interface->>Backend: GET /internal/session-replays/:id (admin key)
    Backend->>DB: SELECT SessionReplay + ProjectUser<br/>+ ContactChannel WHERE id=:id AND tenancyId=:tid
    DB-->>Backend: row
    Backend->>DB: sessionReplayChunk.groupBy(sessionReplayId)
    DB-->>Backend: chunkAgg
    Backend-->>Interface: 200 {id, project_user, started_at_millis, ...}
    Interface-->>AdminApp: AdminGetSessionReplayResponse
    AdminApp-->>PageClient: AdminSessionReplay (camelCase)
    PageClient->>PageClient: setStandaloneReplay(replay)
    PageClient->>AdminApp: getSessionReplayEvents(replayId)
    AdminApp-->>PageClient: chunks + events
    PageClient-->>Browser: Render replay viewer (full width, no sidebar)

    note over Browser,PageClient: Copy-link button builds URL and writes to clipboard
Loading

Reviews (1): Last reviewed commit: "update lock" | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
apps/backend/src/app/api/latest/internal/session-replays/[session_replay_id]/route.tsx (1)

47-70: Consider adding UUID validation for session_replay_id parameter.

The sessionReplayId parameter is passed directly to the SQL query without UUID format validation. While Postgres will reject invalid UUIDs, the resulting error would be a database-level error rather than a clean ITEM_NOT_FOUND response. The tenancyId is explicitly cast with ::UUID, but sessionReplayId is not.

This is a minor consistency issue since invalid UUIDs are an edge case, but adding a .uuid() validation to the yup schema or explicit casting in the query would improve error handling.

💡 Optional: Add UUID validation
   request: yupObject({
     auth: yupObject({
       type: adminAuthTypeSchema.defined(),
       tenancy: adaptSchema.defined(),
     }).defined(),
     params: yupObject({
-      session_replay_id: yupString().defined(),
+      session_replay_id: yupString().uuid().defined(),
     }).defined(),
   }),

Or alternatively, add explicit UUID cast in the query:

       WHERE sr."tenancyId" = ${auth.tenancy.id}::UUID
-        AND sr."id" = ${sessionReplayId}
+        AND sr."id" = ${sessionReplayId}::UUID
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/backend/src/app/api/latest/internal/session-replays/`[session_replay_id]/route.tsx
around lines 47 - 70, Validate the session_replay_id as a UUID before using it
in the query: update the parsing/validation logic that produces sessionReplayId
(the yup schema or request param validator used in route.tsx) to include .uuid()
so invalid IDs are rejected with a controlled error, or alternately change the
prisma.$queryRaw call (the query that uses sessionReplayId) to explicitly cast
the parameter to UUID (e.g. ${sessionReplayId}::UUID) so Postgres rejects
invalid input in a consistent way; ensure you reference the sessionReplayId
variable used in the SELECT and keep the rest of the query (including tenancyId
casting) unchanged.
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/replays/[replayId]/page.tsx (1)

3-9: Prefer a client-side param reader for this wrapper.

This page only forwards replayId into PageClient, so await props.params is avoidable here. A tiny client wrapper using useParams() would keep this route aligned with the repo’s Next.js guidance and avoid using a dynamic request API just to pass one string.

As per coding guidelines, "NEVER use Next.js dynamic functions if you can avoid them. Instead, prefer using a client component."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/dashboard/src/app/`(main)/(protected)/projects/[projectId]/analytics/replays/[replayId]/page.tsx
around lines 3 - 9, The Page component currently awaits props.params to forward
replayId to PageClient; replace this server-side async wrapper with a client
component that uses Next.js' useParams() to read replayId and render PageClient.
Create a simple client wrapper (export default) that calls useParams(), extracts
replayId, and passes it as initialReplayId to PageClient, remove the
async/Page-level awaiting of props.params and any related server-only signatures
so the route no longer uses dynamic server params.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@apps/backend/src/app/api/latest/internal/session-replays/`[session_replay_id]/route.tsx:
- Around line 47-70: Validate the session_replay_id as a UUID before using it in
the query: update the parsing/validation logic that produces sessionReplayId
(the yup schema or request param validator used in route.tsx) to include .uuid()
so invalid IDs are rejected with a controlled error, or alternately change the
prisma.$queryRaw call (the query that uses sessionReplayId) to explicitly cast
the parameter to UUID (e.g. ${sessionReplayId}::UUID) so Postgres rejects
invalid input in a consistent way; ensure you reference the sessionReplayId
variable used in the SELECT and keep the rest of the query (including tenancyId
casting) unchanged.

In
`@apps/dashboard/src/app/`(main)/(protected)/projects/[projectId]/analytics/replays/[replayId]/page.tsx:
- Around line 3-9: The Page component currently awaits props.params to forward
replayId to PageClient; replace this server-side async wrapper with a client
component that uses Next.js' useParams() to read replayId and render PageClient.
Create a simple client wrapper (export default) that calls useParams(), extracts
replayId, and passes it as initialReplayId to PageClient, remove the
async/Page-level awaiting of props.params and any related server-only signatures
so the route no longer uses dynamic server params.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8fd1e171-15dc-4571-9009-168dc87f6830

📥 Commits

Reviewing files that changed from the base of the PR and between 9cf0d43 and fa22972.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (8)
  • apps/backend/src/app/api/latest/internal/session-replays/[session_replay_id]/route.tsx
  • apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/replays/[replayId]/page.tsx
  • apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/replays/page-client.tsx
  • apps/e2e/tests/backend/endpoints/api/v1/session-replays.test.ts
  • packages/stack-shared/src/interface/admin-interface.ts
  • packages/stack-shared/src/interface/crud/session-replays.ts
  • packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts
  • packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts

@madster456 madster456 requested a review from N2D4 March 27, 2026 18:41
@madster456 madster456 requested a review from BilalG1 March 27, 2026 18:41
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/replays/page-client.tsx (1)

1830-1850: Drop the redundant runAsynchronouslyWithAlert wrapper.

Button from @stackframe/stack-ui already wraps async onClick handlers with runAsynchronouslyWithAlert internally and manages the loading state, so the explicit wrapping here duplicates that behavior. Passing the async function directly is simpler and gets the built-in loading indicator.

♻️ Proposed simplification
-                      onClick={() => runAsynchronouslyWithAlert(async () => {
+                      onClick={async () => {
                         await navigator.clipboard.writeText(
                           `${window.location.origin}/projects/${encodeURIComponent(adminApp.projectId)}/analytics/replays/${encodeURIComponent(selectedRecordingId)}`,
                         );
                         setReplayShareLinkCopied(true);
-                      })}
+                      }}

Based on learnings: "Button components from stackframe/stack-ui wrap onClick handlers with runAsynchronouslyWithAlert internally, so async onClick functions that throw will automatically surface an alert to the user. There is no need to manually wrap async onClick handlers with runAsynchronously or runAsynchronouslyWithAlert when passing them to a Button's onClick prop."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/dashboard/src/app/`(main)/(protected)/projects/[projectId]/analytics/replays/page-client.tsx
around lines 1830 - 1850, Remove the redundant runAsynchronouslyWithAlert
wrapper around the Button onClick; instead pass the async handler directly to
the Button's onClick prop (keep the same logic that calls
navigator.clipboard.writeText with the constructed URL using adminApp.projectId
and selectedRecordingId, then setReplayShareLinkCopied(true)), and leave the
conditional rendering based on selectedRecordingId and the replayShareLinkCopied
UI states intact so the Button's built-in loading/alert behavior is used.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/dashboard/src/app/`(main)/(protected)/projects/[projectId]/analytics/replays/page-client.tsx:
- Around line 489-495: selectedRecordingId is only initialized from
initialReplayId and never updated when initialReplayId changes during soft
navigations; add a useEffect that watches initialReplayId (and standaloneReplay
if present) and calls setSelectedRecordingId(initialReplayId ?? null) when
initialReplayId changes in standalone mode so the component,
loadChunksAndDownload calls, and copy-link use the current replay id; reference
selectedRecordingId, setSelectedRecordingId, initialReplayId, and
standaloneReplay when adding the effect.

---

Nitpick comments:
In
`@apps/dashboard/src/app/`(main)/(protected)/projects/[projectId]/analytics/replays/page-client.tsx:
- Around line 1830-1850: Remove the redundant runAsynchronouslyWithAlert wrapper
around the Button onClick; instead pass the async handler directly to the
Button's onClick prop (keep the same logic that calls
navigator.clipboard.writeText with the constructed URL using adminApp.projectId
and selectedRecordingId, then setReplayShareLinkCopied(true)), and leave the
conditional rendering based on selectedRecordingId and the replayShareLinkCopied
UI states intact so the Button's built-in loading/alert behavior is used.
🪄 Autofix (Beta)

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

Run ID: 9f4f6efb-9f7e-4adb-88c9-0f33d1df24b0

📥 Commits

Reviewing files that changed from the base of the PR and between fd9fe69 and bc5784d.

📒 Files selected for processing (1)
  • apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/replays/page-client.tsx

…nitialReplayId, while accounting for standaloneReplay, so soft navigations update chunk loading and copy-link behavior.
@madster456 madster456 merged commit 5e5cfde into dev Apr 28, 2026
16 of 24 checks passed
@madster456 madster456 deleted the dashboard/share-replays branch April 28, 2026 22:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants