Skip to content

Conversation

@west-david
Copy link
Contributor

Summary

This PR fixes a UX issue in the entity-feedback-backend plugin where notifications about new feedback don't include a clickable link to navigate to the entity.

Changes

  • Added link field to notification payload in /responses/:entityRef(*) endpoint
  • Link format: /catalog/{namespace}/{kind}/{name}/feedback
  • Parses entityRef (format: kind:namespace/name) to construct proper Backstage entity URL

Motivation

When entity owners receive notifications about new feedback on their entities, the notification currently shows the entity name and comments but doesn't provide a way to navigate to the feedback. This PR adds a clickable link that takes users directly to the entity's feedback page.

Implementation

// Construct entity URL from entityRef (format: "kind:namespace/name")
const [kind, namespaceName] = req.params.entityRef.split(":");
const [namespace, name] = namespaceName.split("/");
const entityUrl = `/catalog/${namespace}/${kind}/${name}/feedback`;

const payload: NotificationPayload = {
  title: `New feedback for ${req.params.entityRef}`,
  description: `Comments: ${JSON.parse(comments).additionalComments}`,
  link: entityUrl,
};

Testing

Tested in a production Backstage instance with entity-feedback plugin enabled:

  1. Submitted feedback on a test entity
  2. Verified notification was sent to entity owner
  3. Confirmed notification includes clickable link
  4. Verified link navigates correctly to entity's feedback page

The notification link successfully takes users to the correct entity feedback page in the format /catalog/{namespace}/{kind}/{name}/feedback.

@west-david west-david requested review from a team and kuangp as code owners December 23, 2025 17:45
@west-david west-david requested review from BethGriggs and removed request for a team December 23, 2025 17:45
@backstage-goalie
Copy link
Contributor

backstage-goalie bot commented Dec 23, 2025

Changed Packages

Package Name Package Path Changeset Bump Current Version
@backstage-community/plugin-entity-feedback-backend workspaces/entity-feedback/plugins/entity-feedback-backend patch v0.16.0
@backstage-community/plugin-entity-feedback-common workspaces/entity-feedback/plugins/entity-feedback-common patch v0.12.0
@backstage-community/plugin-entity-feedback workspaces/entity-feedback/plugins/entity-feedback patch v0.14.0

@backstage-goalie
Copy link
Contributor

Thanks for the contribution!
All commits need to be DCO signed before they are reviewed. Please refer to the the DCO section in CONTRIBUTING.md or the DCO status for more info.

Add link field to notification payload so users can navigate directly
to the entity's feedback page when they receive a notification about
new feedback on their owned entities.

Notifications now include a clickable link in the format:
/catalog/{namespace}/{kind}/{name}/feedback

Signed-off-by: David <[email protected]>
@west-david west-david force-pushed the fix/entity-feedback-notification-links branch from 074a3aa to 92b7cd7 Compare December 23, 2025 17:49
// Construct entity URL from entityRef (format: "kind:namespace/name")
const [kind, namespaceName] = req.params.entityRef.split(':');
const [namespace, name] = namespaceName.split('/');
const entityUrl = `/catalog/${namespace}/${kind}/${name}/feedback`;
Copy link
Member

Choose a reason for hiding this comment

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

Thanks for suggesting this change however it is not guaranteed that this is always the entity URL - consumers are free to attach the catalog plugin and "feedback" tab to any custom route name of their choosing even though this is the default. Therefore we probably need a more configurable way to construct this url that is consistent with how the frontend plugin is setup

Comment on lines 232 to 233
const [kind, namespaceName] = req.params.entityRef.split(':');
const [namespace, name] = namespaceName.split('/');
Copy link
Member

Choose a reason for hiding this comment

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

FYI you can use parseEntityRef to parse entity refs

Address review feedback:
- Use parseEntityRef utility instead of manual string parsing
- Make notification link URL configurable via entityFeedback.feedbackUrlPattern
- Default pattern: /catalog/:namespace/:kind/:name
- Allows customization for non-standard routes

Users can now configure custom URL patterns in app-config.yaml:
```yaml
entityFeedback:
  feedbackUrlPattern: '/catalog/:namespace/:kind/:name/feedback'
```

This addresses the concern that the /feedback route suffix may be
customized in different Backstage installations.

Signed-off-by: David <[email protected]>
@west-david
Copy link
Contributor Author

Thanks for the review! I've addressed both comments:

1. Using parseEntityRef: ✅
Replaced manual string parsing with the parseEntityRef utility from @backstage/catalog-model.

2. Configurable URL pattern: ✅
Made the notification link URL configurable via app-config to support custom routes:

const feedbackUrlPattern =
  config.getOptionalString('entityFeedback.feedbackUrlPattern') ||
  '/catalog/:namespace/:kind/:name';

const entityUrl = feedbackUrlPattern
  .replace(':kind', kind)
  .replace(':namespace', namespace)
  .replace(':name', name);

Default behavior: Links to /catalog/:namespace/:kind/:name (without /feedback suffix)

Custom configuration example:

entityFeedback:
  feedbackUrlPattern: '/catalog/:namespace/:kind/:name/feedback'

This allows users to configure the exact pattern that matches their frontend routing setup.

Tests have been updated to reflect the new default pattern.

// Allow customization of the feedback URL pattern via config
// Default: /catalog/:namespace/:kind/:name
const feedbackUrlPattern =
config.getOptionalString('entityFeedback.feedbackUrlPattern') ||
Copy link
Member

@kuangp kuangp Dec 23, 2025

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

actually another option which may be more robust is to send this info from the frontend plugin since the routing can be derived there automatically:

if you can emulate what's done here to derive the route of the entity: https://github.com/backstage/backstage/blob/fea3e3972daf42fc75c107568a693eeb14a4d672/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.tsx#L84-L88, then pass it along in the request to the backend here:

, it would be available in this express route for it to be included in the notification payload

The benefit of the above is that it will always consistently construct the appropriate entity url (including custom ones) without any additional configuration from the consumer

…cations

Changes the implementation to derive entity URLs from the frontend routing
configuration instead of using backend configuration. This ensures notification
links always match the actual routes configured in the app.

**Frontend changes:**
- Use entityRouteRef and entityRouteParams (same as EntityRefLink) to derive URL
- Pass entity URL in feedback request

**Backend changes:**
- Accept link from request instead of constructing it
- Remove config-based URL pattern logic
- Add database migration for link field
- Update tests to include link field

This approach is more robust as it uses a single source of truth (frontend router)
and requires no additional configuration.

Signed-off-by: David <[email protected]>
@west-david west-david requested a review from kuangp December 24, 2025 01:13
Copy link
Member

@kuangp kuangp left a comment

Choose a reason for hiding this comment

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

Looks great! Thanks !

@kuangp kuangp merged commit c92a717 into backstage:main Dec 24, 2025
13 checks passed
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.

3 participants