Skip to content

feat(js,react,nextjs): improved rendering architecture - #12591

Draft
LetItRock wants to merge 2 commits into
nextfrom
inbox-rendering-redesign
Draft

LetItRock wants to merge 2 commits into
nextfrom
inbox-rendering-redesign

Conversation

@LetItRock

@LetItRock LetItRock commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

What changed? Why was the change needed?

Inbox: improved rendering architecture

Screenshots

Expand for optional sections

Related enterprise PR

Special notes for your reviewer

Greptile Summary

The PR introduces a shared, framework-neutral Inbox UI core, changes the engine/host bridge to support in-place outlet updates, and adds composable React-native notification-item blocks while retaining Solid-rendered interactive islands.

  • Moves appearance, localization, inbox, count, styling, formatting, and item behavior into @novu/js/ui-core.
  • Adds stable outlet stores and update handles so host-rendered content retains state across notification updates.
  • Exposes a composable NotificationItem API through React and Next.js.
  • Migrates relevant JavaScript and React tests from Jest to Vitest and updates SDK documentation and playground examples.

Confidence Score: 3/5

The latest changes introduce no accepted new defect, but the PR is not yet safe to merge because two previously reported compatibility issues remain unresolved.

The declared Node range still permits Node 22 versions below the minimum required by jsdom 30.0.1, so supported contributors can be unable to run the migrated suites. The React server-condition NotificationItem stub is still inferred as a zero-argument component and NotificationItemProps is still not publicly re-exported there, so valid server-condition TypeScript usage remains rejected. The delivery-time display also remains stale because its memo excludes the minute tick that triggers surrounding renders.

Files Needing Attention: packages/js/package.json, packages/react/package.json, packages/react/src/server/index.tsx, packages/react/src/components/notification-item/parts/Date.tsx

Important Files Changed

Filename Overview
packages/js/src/ui/core/index.ts Defines the public entry point for the framework-neutral Inbox core shared by the engine and host.
packages/js/src/ui/components/ExternalElementRenderer.tsx Changes outlet rendering from repeated remounting to mount-once handles with in-place data updates.
packages/react/src/context/OutletStore.ts Introduces the external-store-backed outlet registry used for stable, keyed React portal rendering.
packages/react/src/components/notification-item/NotificationItem.tsx Adds the composable React-native notification-item root and its shared behavior/context.
packages/react/src/components/notification-item/parts/Date.tsx Implements native date rendering, but the previously reported memoized delivery timestamps remain stale.
packages/react/src/server/index.tsx Adds server-condition stubs, but the previously reported NotificationItem prop typing and missing public prop-type export remain unresolved.
packages/js/package.json Adds the UI-core export and Vitest dependencies, while the previously reported jsdom/declared Node support mismatch remains unresolved.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Data["@novu/js data and immutable notifications"]
  Core["@novu/js/ui-core<br/>stores, styles, formatting, controllers"]
  Engine["Solid Inbox engine<br/>shell and interactive islands"]
  Bridge["Bridge<br/>mount, update, unmount"]
  Host["React host<br/>outlets and NotificationItem blocks"]

  Data --> Core
  Core --> Engine
  Core --> Host
  Engine --> Bridge
  Bridge --> Host
  Host -->|mount islands| Bridge
Loading

Reviews (2): Last reviewed commit: "Merge branch 'next' into inbox-rendering..." | Re-trigger Greptile

@LetItRock LetItRock self-assigned this Sep 7, 2026
@mintlify

mintlify Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
novu 🟢 Ready View Preview Sep 14, 2026, 8:39 AM

@vercel

vercel Bot commented Sep 7, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated
human-md Ready Ready Preview Sep 14, 2026 8:37am UTC

Request Review

@netlify

netlify Bot commented Sep 7, 2026

Copy link
Copy Markdown

Deploy preview added

Name Link
🔨 Latest commit 78f2e15
🔍 Latest deploy log https://app.netlify.com/projects/dashboard-v2-novu-staging/deploys/6aa7b245b60e9e0008f32b23
😎 Deploy Preview https://deploy-preview-12591.dashboard-v2.novu-staging.co
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Hey there and thank you for opening this pull request! 👋

We require pull request titles to follow specific formatting rules and it looks like your proposed title needs to be adjusted.

Your PR title is: feat(js,react,nextjs): improved rendering architecture

Requirements:

  1. Follow the Conventional Commits specification
  2. As a team member, include Linear ticket ID at the end: fixes TICKET-ID or include it in your branch name

Expected format: feat(scope): Add fancy new feature fixes NOV-123

Details:

PR title must end with 'fixes TICKET-ID' (e.g., 'fixes NOV-123') or include ticket ID in branch name

@socket-security

socket-security Bot commented Sep 7, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​testing-library/​dom@​10.4.19910010086100
Addednpm/​@​testing-library/​react@​16.3.310010010091100
Addednpm/​jsdom@​30.0.19810010093100
Addednpm/​vite-plugin-solid@​2.11.149910010098100

View full report

@socket-security

socket-security Bot commented Sep 7, 2026

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm data-urls is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: pnpm-lock.yamlnpm/jsdom@30.0.1npm/data-urls@7.0.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/data-urls@7.0.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm jsdom is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: packages/js/package.jsonnpm/jsdom@30.0.1

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/jsdom@30.0.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

Comment thread packages/js/package.json
"esbuild-plugin-solid": "^0.6.0",
"http-server": "^0.13.0",
"jest": "^29.3.1",
"jsdom": "^30.0.1",

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.

P1 Node support range mismatch

The new jsdom@30.0.1 test dependency requires Node 22.22.2 or newer, while the repository declares all Node 22 releases as supported. Developers using Node 22.0.0 through 22.22.1 therefore satisfy the repository's engine declaration but cannot reliably run the migrated Vitest suites. The same dependency was added to packages/react/package.json; either use a compatible jsdom release or raise the declared Node floor.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/js/package.json
Line: 127

Comment:
**Node support range mismatch**

The new `jsdom@30.0.1` test dependency requires Node 22.22.2 or newer, while the repository declares all Node 22 releases as supported. Developers using Node 22.0.0 through 22.22.1 therefore satisfy the repository's engine declaration but cannot reliably run the migrated Vitest suites. The same dependency was added to `packages/react/package.json`; either use a compatible jsdom release or raise the declared Node floor.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Cursor

Comment on lines +51 to +57
const deliveredAt = useMemo(
() =>
Array.isArray(notification.deliveredAt)
? notification.deliveredAt.map((date) => formatToRelativeTime({ fromDate: new globalThis.Date(date), locale }))
: null,
[notification.deliveredAt, locale]
);

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.

P2 Delivery times stay stale

The minute tick re-renders this block, but deliveredAt is memoized without a time-dependent value. Its relative timestamps therefore do not advance unless the notification snapshot or locale changes, while the other date variants continue updating. Notifications with multiple delivery times will show stale elapsed values.

Suggested change
const deliveredAt = useMemo(
() =>
Array.isArray(notification.deliveredAt)
? notification.deliveredAt.map((date) => formatToRelativeTime({ fromDate: new globalThis.Date(date), locale }))
: null,
[notification.deliveredAt, locale]
);
const deliveredAt = Array.isArray(notification.deliveredAt)
? notification.deliveredAt.map((date) => formatToRelativeTime({ fromDate: new globalThis.Date(date), locale }))
: null;
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/react/src/components/notification-item/parts/Date.tsx
Line: 51-57

Comment:
**Delivery times stay stale**

The minute tick re-renders this block, but `deliveredAt` is memoized without a time-dependent value. Its relative timestamps therefore do not advance unless the notification snapshot or locale changes, while the other date variants continue updating. Notifications with multiple delivery times will show stale elapsed values.

```suggestion
  const deliveredAt = Array.isArray(notification.deliveredAt)
    ? notification.deliveredAt.map((date) => formatToRelativeTime({ fromDate: new globalThis.Date(date), locale }))
    : null;
```

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Cursor

Comment on lines +40 to +52
const NotificationItemStub = () => null;

export const NotificationItem = Object.assign(NotificationItemStub, {
Avatar: NotificationItemStub,
Content: NotificationItemStub,
Text: NotificationItemStub,
Subject: NotificationItemStub,
Body: NotificationItemStub,
DefaultActions: NotificationItemStub,
CustomActions: NotificationItemStub,
Date: NotificationItemStub,
Dot: NotificationItemStub,
});

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.

P1 Server stub rejects props

The new server export types NotificationItem and all its static blocks as zero-argument functions, while the browser component requires a notification prop. It also omits NotificationItemProps from the server type exports. Code checked through the React or Next.js server conditions therefore rejects valid <NotificationItem notification={...}> usage and cannot import its public prop type. Type the stubs with their client props and re-export NotificationItemProps.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/react/src/server/index.tsx
Line: 40-52

Comment:
**Server stub rejects props**

The new server export types `NotificationItem` and all its static blocks as zero-argument functions, while the browser component requires a `notification` prop. It also omits `NotificationItemProps` from the server type exports. Code checked through the React or Next.js server conditions therefore rejects valid `<NotificationItem notification={...}>` usage and cannot import its public prop type. Type the stubs with their client props and re-export `NotificationItemProps`.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Cursor

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.

1 participant