-
Notifications
You must be signed in to change notification settings - Fork 0
Remote Banners
JumpStart can show a dismissible announcement card (bottom-right) without shipping a new app build. Installed apps download a small JSON file from GitHub on launch.
This is how you “send a notification” to users.
social/banner.json (on branch main)
│
▼ GET raw.githubusercontent.com
internal/banner.Fetch() ← GetRemoteBanner()
│
▼
useRemoteBanner.js → first enabled, active, not-dismissed banner
│
▼
AdOverlay.jsx (promo / info / warning card + optional CTA)
Fetch URL (fixed in code):
https://raw.githubusercontent.com/canaryGrapher/JumpStart/main/social/banner.json
Defined as banner.DefaultURL in internal/banner/banner.go. There is no user-configurable URL.
- Edit
social/banner.jsonin the repo. - Prepend your banner (or place it above older ones you still want shown). The UI shows the first entry that is enabled, in schedule, and not already dismissed.
- Give it a new unique
id. Reusing an id that users already dismissed will never show again on those machines. - Commit and push to
main. Local-only or PR-branch edits are invisible to installed apps. - Ask users to restart JumpStart (or wait until next launch). The hook fetches once per session; it does not poll.
[
{
"id": "my-announcement-2026-08",
"enabled": true,
"title": "Short title",
"message": "One or two sentences. Keep it scannable.",
"linkUrl": "https://github.com/canaryGrapher/JumpStart/wiki",
"linkText": "Learn more",
"imageUrl": "",
"style": "promo",
"startsAt": "",
"endsAt": ""
}
]The file may be either a JSON array of banners or a single object. Prefer an array so you can keep history and order.
| Field | Required | Notes |
|---|---|---|
id |
Yes | Stable string; used for dismissals and analytics (banner_id). Empty ids are skipped. |
enabled |
Yes |
false hides it without deleting the entry. |
title |
No | Bold heading in the card. |
message |
No | Body text. |
linkUrl |
No | Opens in the system browser via BrowserOpenURL. |
linkText |
No | Button label; defaults to “Learn more” if linkUrl is set. |
imageUrl |
No | Optional image above the text (remote URL). |
style |
No |
info | promo | warning (unknown → info). |
startsAt |
No | RFC3339; hide until this time. Empty = already started. |
endsAt |
No | RFC3339; hide after this time. Empty = no end. |
"startsAt": "2026-08-10T00:00:00Z",
"endsAt": "2026-08-31T23:59:59Z"- Closing the card stores
idin frontendlocalStorageunderdismissedBannerIds(last 50 kept). - Dismissed ids never reappear for that install, even if you edit the message.
- To show something again to everyone who already dismissed an old banner: use a new
id. - Clearing localStorage (or that key) is the only local reset — not something users normally do.
useRemoteBanner picks the first list item where:
enabled === true-
idis non-empty -
startsAt/endsAtallow “now” (Go also filters this inFetch) -
idis not indismissedBannerIds
So: put the current campaign first. Leave older entries enabled further down as a fallback for users who already dismissed the newer ones — or set "enabled": false on retired campaigns.
- Set
"enabled": false, or - Set
endsAtto a past timestamp, or - Remove the object from the array
Then push to main. No app release required.
| Mechanism | Purpose |
|---|---|
Remote banner (AdOverlay) |
Marketing / docs / one-off announcements from banner.json
|
UpdateBanner |
New GitHub Release detected by the updater |
Toast in App.jsx
|
Local, ephemeral UI feedback for the current session |
Do not use banner.json for critical security alerts that must interrupt every user immediately — there is no push channel, only fetch-on-launch.
| Piece | Path |
|---|---|
| Config file | social/banner.json |
| Fetch + schedule filter | internal/banner/banner.go |
| Wails binding |
GetRemoteBanner in app.go
|
| Frontend fetch / dismiss | frontend/src/hooks/useRemoteBanner.js |
| UI card | frontend/src/components/AdOverlay.jsx |
| Styles |
frontend/src/styles/_banners.scss (shared banner area) |
| Analytics |
banner_shown / banner_clicked / banner_dismissed with banner_id
|
- New unique
id -
enabled: true - Entry is first (or intentionally ordered) among active banners
-
linkUrlis absolutehttps://… - Valid JSON (array or single object)
- Committed and pushed to
main - Verified live file:
https://raw.githubusercontent.com/canaryGrapher/JumpStart/main/social/banner.json
(CDN may lag a minute;git show origin/main:social/banner.jsonis authoritative) - Restarted a desktop build to confirm the card appears
-
Not on
main— PR or local-only edit (most common). -
Same
idalready dismissed on that machine. - Another banner earlier in the list still active and not dismissed — users only see one at a time.
- App not restarted since the fetch.
- Offline / fetch failure — hook fails quietly; no card.
-
enabled: falseor outsidestartsAt/endsAt. -
Stale CDN — wait briefly or confirm via the GitHub API /
git show.