Skip to content

refactor(announcements): use StorageApi instead of WebStorage - #10328

Open
fredericoferreiracosta wants to merge 2 commits into
backstage:mainfrom
fredericoferreiracosta:feat/announcements-use-storage-api
Open

refactor(announcements): use StorageApi instead of WebStorage#10328
fredericoferreiracosta wants to merge 2 commits into
backstage:mainfrom
fredericoferreiracosta:feat/announcements-use-storage-api

Conversation

@fredericoferreiracosta

Copy link
Copy Markdown

Hey, I just made a Pull Request!

This PR replaces direct WebStorage instantiation with the Backstage StorageApi interface for announcement dismiss state persistence.

Problem

The AnnouncementsClient directly instantiates WebStorage (from @backstage/core-app-api), bypassing the Backstage StorageApi abstraction. This means even if a Backstage instance has the User Settings Backend deployed (which persists state server-side per user), the announcements plugin always uses raw browser localStorage.

This causes dismissed announcements to reappear on new devices, incognito mode, or after clearing browser data.

Solution

  • Replace WebStorage import with StorageApi from @backstage/core-plugin-api
  • Add storageApi: StorageApi to AnnouncementsClientOptions
  • Use StorageApi.snapshot() instead of the non-standard WebStorage.get()
  • Use storageApi.forBucket("announcements") instead of new WebStorage("announcements", errorApi)
  • Update both legacy plugin.ts and alpha apis.ts factories to inject storageApiRef
  • Remove @backstage/core-app-api dependency from announcements-react (no longer needed)

Benefits

  • Respects instance configuration: If the Backstage admin deploys user-settings-backend, dismiss state is automatically persisted server-side per user
  • Cross-device consistency: Users won't see already-dismissed announcements on new devices
  • Proper abstraction: Uses the Backstage contract instead of the concrete implementation
  • Smaller dependency footprint: Removes @backstage/core-app-api from the react package

Testing

  • All 112 unit tests pass (announcements plugin)
  • All 12 unit tests pass (announcements-react plugin)
  • TypeScript compilation passes cleanly
  • Full workspace build succeeds
  • Manually tested: dismiss announcements, reload page, verify persistence
  • Manually tested: new browser session shows all announcements (localStorage starts fresh)

Note

This PR is based on #10316 (per-announcement dismiss tracking) which must be merged first.

✔️ Checklist

  • A changeset describing the change and affected packages.
  • Added or updated documentation (API reports regenerated)
  • Tests for new functionality and regression tests for bug fixes
  • Screenshots attached (for UI changes)
  • All your commits have a Signed-off-by line in the message.

Related: #9118

fredericoferreiracosta and others added 2 commits August 13, 2026 18:36
Replace the single-timestamp lastSeenDate dismiss mechanism with
per-announcement ID tracking. Each banner can now be dismissed
independently without affecting the visibility of other announcements.

Changes:
- Add dismissAnnouncement(id) and isAnnouncementDismissed(id) to
  the AnnouncementsApi interface
- Implement dismissed ID storage in AnnouncementsClient with a
  cap of 50 IDs to prevent localStorage bloat
- Update NewAnnouncementBanner to use per-ID dismiss instead of
  markLastSeenDate
- Update AnnouncementsCard to check per-ID dismiss for the New icon
- Keep lastSeenDate as backward-compatible fallback for pre-existing
  state and overflow scenarios
- Update test mocks for both components

Fixes: backstage#9118
Signed-off-by: Frederico Ferreira Costa <fredericoferreiracosta@users.noreply.github.com>
Replace direct WebStorage instantiation with the StorageApi interface
for announcement dismiss state persistence. This decouples the plugin
from the concrete localStorage implementation and allows Backstage
instances with a user-settings backend to automatically persist state
server-side.

Changes:
- Replace WebStorage import with StorageApi from core-plugin-api
- Add storageApi to AnnouncementsClientOptions
- Use StorageApi.snapshot() instead of WebStorage.get()
- Update both legacy plugin.ts and alpha apis.ts factories to pass
  storageApiRef
- Remove @backstage/core-app-api dependency from announcements-react

Signed-off-by: Frederico Costa (EXT) <frederico.costa.ext@ericsson.com>
@backstage-service backstage-service added the workspace/announcements Used to tag announcements workspace isses and pull requests label Aug 14, 2026
@backstage-goalie

Copy link
Copy Markdown
Contributor

Changed Packages

Package Name Package Path Changeset Bump Current Version
@backstage-community/plugin-announcements-react workspaces/announcements/plugins/announcements-react minor v0.27.0
@backstage-community/plugin-announcements workspaces/announcements/plugins/announcements minor v2.11.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

workspace/announcements Used to tag announcements workspace isses and pull requests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants