Skip to content

Product Hunt launch notice, with the launch date from the update check - #2386

Merged
nadaverell merged 17 commits into
mainfrom
feat/product-hunt-launch-notice
Oct 28, 2026
Merged

nadaverell merged 17 commits into
mainfrom
feat/product-hunt-launch-notice

Conversation

@nadaverell

@nadaverell nadaverell commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Radar launches on Product Hunt on Thursday, Oct 29. This adds a one-off corner card so users hear about it, timed to the launch and gone after it. The date, link and on/off switch come from the update check, so the launch can move or be called off without a release. It should ship today (1.18.3), since only installs on this version will see it.

What users see

Before the day On the day
Pre-launch card beside its sidebar item Launch-day card beside its sidebar item
Sidebar item, expanded Collapsed
Product Hunt item tagged TODAY Rocket tagged with the date

Title Radar â™Ĩ Agents (lucide heart, not an emoji), a green status line, then:

When Accent line Body Links
Before the launch day Launching on Product Hunt Oct 29 We're launching Radar's newly upgraded MCP server and AI investigations on Product Hunt. If Radar has made Kubernetes a little easier for you, follow the launch and come say hi on the day. It helps other engineers find Radar. Follow on Product Hunt → · How it works
Launch day, 00:00-24:00 PT Live on Product Hunt today We're on Product Hunt today with Radar's newly upgraded MCP server and AI investigations. If Radar has made Kubernetes a little easier for you, a comment on the launch would mean a lot. It helps other engineers find Radar. Comment on Product Hunt → · How it works
After Nothing. The component returns null and stops its timers.

The date in the status line is the launch start on Pacific time. Before the day the page only offers Follow, so that card asks for a follow; the launch-day card asks for a comment. "How it works" goes to radarhq.io/product/ai-investigations. The copy asks for a comment, never a vote, which Product Hunt's guidelines allow.

Where the launch comes from

releases.skyhook.io adds a productHuntLaunch field (enabled, url, start, end) to the update-check response (skyhook-dev/marketing#359). No new request: it rides on the hourly check installs already make, and RADAR_DISABLE_VERSION_CHECK still turns it off.

  • Field present: it wins. enabled: false hides the card and stops suppressing the star prompt.
  • Field missing, or no answer (offline, version checks off, GitHub fallback): the built-in Oct 29 window in internal/launchday applies.
  • A server value is kept until a later check replaces it, so one failed check doesn't bring back the old date. The URL must be an https:// Product Hunt link and the window must be ordered; anything else is ignored and logged.
  • /api/version-check and Desktop's manual "Check for updates" result both carry the effective launch, and the frontend waits for the version check before deciding. If the request fails, it uses the same built-in window.
  • A card on screen keeps what it showed through its exit fade, so the launch being called off, or the day ending, while it is visible just fades it out.
  • Dismissals are keyed by launch day, so a moved launch is announced again.
  • Changes reach running installs within the hour the check is cached.

Rules it follows

  • Not a modal. A non-blocking card as wide as the update notice, shown 10 s after load.
  • It lives in the sidebar. For the launch window a green rocket labelled Product Hunt sits above What's new, tagged with a tilted TODAY on the day (the date before it), so it reads as a one-off. The card grows out of that item, sits beside it (following the sidebar as it expands or collapses), and shrinks back into it when closed; clicking the item opens it again. It is capped to the space above the item and scrolls inside in a short window. Where the sidebar isn't on screen it uses the bottom-right corner.
  • Radar green, for this card only. The app's accent is blue; the card uses radarhq.io's emerald so it stands apart from the page: a green wash, a solid green icon and button, and a green light that travels around the border with a soft glow, fading on a cycle longer than the lap so its brightest point moves. The rocket drifts gently while the card is open. Both stop under prefers-reduced-motion; browsers without @property show the light standing still.
  • Each phase is dismissed on its own (the sidebar item stays). Closing the pre-launch card (or clicking its Product Hunt link) hides it; the launch-day card still shows once. localStorage, like the update notice; if storage refuses, the dismissal holds for the page and still frees the corner.
  • Before the day, it waits its turn behind the update notice and the first-run usage prompt; opening it from the sidebar shows it at once.
  • On the day, the others wait for it:
    • the GitHub star prompt is skipped, CLI and UI;
    • the update notice and the first-run usage prompt wait until the launch card is dismissed or the day ends.
  • Local installs get both cards; in-cluster gets only the launch-day card, since an in-cluster Radar is often shared by people who didn't install it. Never in Cloud or embedded (Hub).
  • No tracking. No usage event; nothing changes in what the update check sends. The Product Hunt link and "How it works" carry the same fixed tag for every install (utm_source=radar-oss&utm_medium=app&utm_campaign=ph-launch-2026-10), so visits from the card can be counted without knowing who clicked.

Not in What's New

The 1.19 What's New entry stays about the release. Adding a promo card there would either drive the auto-open dialog (a modal) or sit in the notes after the launch is over.

Tests

  • ProductHuntNotice.test.ts: the Pacific-day window, a moved and a cancelled launch from the server, the day label and link tags, the show rules (including in-cluster on the day only), per-phase dismissal keyed by launch day, and who holds the corner on the day.
  • internal/launchday: the built-in window, a moved and a cancelled launch, rejected bad launches.
  • useProductHuntRailEntry.test.tsx: the sidebar item's audience, window, day tag, waiting for the version check, and reopening.
  • UpdateNotification.test.tsx pins the launch off so it passes on launch day; a newer release shows the update notice again after an older one was dismissed, and an update found while the usage prompt is open waits for it.
  • ProductHuntNotice.render.test.tsx (mounted, fake timers): reopening from the sidebar after closing; the card appears after the delay with the tagged link; calling the launch off while it is on screen fades it out instead of throwing; the day's end keeps the launch-day wording during the fade; in-cluster shows nothing before the day.
  • internal/version: an update-check response that turns the launch off reaches launchday.
  • cmd/desktop: the manual-check event carries the launch.
  • vitest run for product-hunt, usage-data and UpdateNotification; tsc --noEmit; go test -race ./internal/launchday ./internal/version ./cmd/desktop and go test ./internal/app ./internal/server all pass.
  • Visual test against radar-test-nonprod with Playwright's clock faked and the version-check response rewritten:
    • Oct 28, local: pre-launch card. Oct 29, local: launch-day card.
    • Oct 29 with enabled: false: no card.
    • Oct 29 with the launch moved to Nov 5: pre-launch card reading "Nov 5".
    • In-cluster: no card on Oct 28, launch-day card on Oct 29.
    • The Product Hunt link carries the UTM tag.
    • Update-notice ordering, dismissal persistence, and both themes were checked on the previous revision; the card's layout and corner rules didn't change.

A corner card on local installs: before Oct 29 PT it says Radar launches
on Product Hunt that day; during the Pacific day of Oct 29 it links to the
launch and asks what Radar found for people. It waits behind the update
notice and the first-run usage prompt, a dismissal is final, and it never
shows in-cluster, in Cloud or when embedded. It turns itself off when
the Pacific day ends.
@nadaverell
nadaverell requested a review from hisco as a code owner October 27, 2026 22:25
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Show a local-only Product Hunt launch notice

âœĻ Enhancement 🧊 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

â€Ē Add a non-blocking corner card before and during the Oct 29 Pacific launch day.
â€Ē Show it only on local, non-embedded installs when other corner notices are clear.
â€Ē Persist dismissal across both messages and test the launch window and visibility rules.
Diagram

graph TD
  A["App shell"] --> B["Launch notice"] --> C{"Local install?"} --> D{"Launch window?"} --> E{"Corner free?"} --> F["Corner card"] --> G["Product Hunt"]
  B --> H["Browser storage"]
  F --> H
  H --> C
Loading
High-Level Assessment

A self-contained, hard-coded notice fits this one-off, time-limited launch better than a remote campaign or general notification system. Reusing the existing corner-priority helper keeps it consistent with current notices without adding tracking or release-note behavior.

Files changed (3) +187 / -0

Enhancement (2) +141 / -0
App.tsxMount the notice in non-embedded app views +2/-0

Mount the notice in non-embedded app views

â€Ē Adds the Product Hunt notice alongside the existing corner notices and passes it usage-data status. Embedded views do not mount it.

web/src/App.tsx

ProductHuntNotice.tsxAdd a timed, dismissible Product Hunt corner card +139/-0

Add a timed, dismissible Product Hunt corner card

â€Ē Introduces upcoming and launch-day copy with a shared Product Hunt link. Visibility depends on deployment mode, the launch window, a ten-second delay, competing notices, and a persistent dismissal key.

web/src/components/product-hunt/ProductHuntNotice.tsx

Tests (1) +46 / -0
ProductHuntNotice.test.tsTest launch timing and visibility gates +46/-0

Test launch timing and visibility gates

â€Ē Covers Pacific-time phase boundaries, including a non-Pacific local time, and checks local deployment, dismissal, delay, and occupied-corner eligibility.

web/src/components/product-hunt/ProductHuntNotice.test.ts

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) ðŸŽĻ UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Two corner cards appear at once ✓ Resolved
Description
ProductHuntNotice treats a cleared firstRunPrompt flag as a free corner, but UsageDataPrompt
clears that flag as soon as it latches itself for display. On a first-run local install, the usage
card remains visible while the Product Hunt card appears in the same bottom-right position.
Code

web/src/components/product-hunt/ProductHuntNotice.tsx[71]

+    cornerBusy: updateNoticeVisible(versionInfo?.latestVersion, versionInfo?.updateAvailable) || !!usageData?.firstRunPrompt,
Evidence
markUsagePromptShown immediately clears the query-cache flag, whereas the prompt's rendered state
depends on its separate latch and dismissal state. Both components are mounted together and use the
same fixed corner position.

web/src/components/usage-data/UsageDataPrompt.tsx[65-85]
web/src/api/usage-data.ts[96-105]
web/src/App.tsx[2580-2582]
web/src/components/product-hunt/ProductHuntNotice.tsx[66-95]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The first-run prompt clears `firstRunPrompt` when it appears but continues occupying the corner, allowing the Product Hunt card to overlap it.
## Fix Focus Areas
- web/src/components/product-hunt/ProductHuntNotice.tsx[65-73]
- web/src/components/usage-data/UsageDataPrompt.tsx[65-85]
- web/src/App.tsx[2579-2582]
## Recommended Fix
Share the usage card's actual visible or exiting state with the Product Hunt notice, and keep the Product Hunt card hidden until that state releases the corner. Cover the latched prompt and its answer/thank-you period in a component-level test.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Slow loading lets the promo go first ✓ Resolved
Description
ProductHuntNotice interprets an undefined usage-data status as firstRunPrompt being false, so
its ten-second timer can open the card before the first-run status is known. If the usage-data
request takes longer than ten seconds on a local install, the Product Hunt card takes the corner
ahead of the first-run prompt.
Code

web/src/components/product-hunt/ProductHuntNotice.tsx[71]

+    cornerBusy: updateNoticeVisible(versionInfo?.latestVersion, versionInfo?.updateAvailable) || !!usageData?.firstRunPrompt,
Evidence
App passes only query data, which is unavailable while the request is pending. The Product Hunt
timer runs independently, while the first-run timer starts only after the status offers that prompt.

web/src/api/usage-data.ts[48-61]
web/src/App.tsx[442-442]
web/src/components/product-hunt/ProductHuntNotice.tsx[53-72]
web/src/components/usage-data/UsageDataPrompt.tsx[52-63]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
An unresolved usage-data request is treated as a free corner, allowing the Product Hunt card to appear before first-run prompt eligibility is known.
## Fix Focus Areas
- web/src/App.tsx[2580-2582]
- web/src/components/product-hunt/ProductHuntNotice.tsx[46-72]
## Recommended Fix
Pass the usage query's pending state to the notice and withhold the card until the first-run status is known. Test a usage response that arrives after the Product Hunt delay.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Expired notices keep waking the app ✓ Resolved
Description
ProductHuntNotice creates a minute-by-minute interval whose cleanup runs only when the component
unmounts, not when launchPhase reaches null. If the app stays open past October 29 Pacific time,
the invisible notice continues updating React state every minute for the rest of that session.
Code

web/src/components/product-hunt/ProductHuntNotice.tsx[R58-61]

+    const poll = window.setInterval(() => setNow(Date.now()), 60_000)
+    return () => {
+      window.clearTimeout(delay)
+      window.clearInterval(poll)
Evidence
The effect has no phase-dependent cleanup: it clears its interval only on unmount. After the
deadline, the interval still calls setNow, even though the resulting phase prevents the notice
from showing.

web/src/components/product-hunt/ProductHuntNotice.tsx[20-23]
web/src/components/product-hunt/ProductHuntNotice.tsx[53-74]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The clock interval remains active after the notice's time window expires, causing needless state updates while the app stays open.
## Fix Focus Areas
- web/src/components/product-hunt/ProductHuntNotice.tsx[53-74]
## Recommended Fix
Clear the interval when a clock check reaches the launch end, while retaining unmount cleanup. Test that a mounted notice stops polling after the deadline.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
ðŸ’Ą Did you know, you can turn on the rule miner and Qodo learns your standards from review history

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread web/src/components/product-hunt/ProductHuntNotice.tsx Outdated
Comment thread web/src/components/product-hunt/ProductHuntNotice.tsx Outdated
Comment thread web/src/components/product-hunt/ProductHuntNotice.tsx
Product Hunt leads, the copy says the launch showcases MCP and AI
investigations, and a secondary link explains the feature on radarhq.io.
Investigations start from a resource, so there is no in-app place to
send someone to try one cold.
Each phase of the launch notice is dismissed on its own, so the launch-day
card still reaches someone who closed the one before it. On the Pacific
day of Oct 29 the GitHub star prompt (CLI and UI) is skipped, and the
update notice and first-run usage prompt wait until the launch card is
dismissed or the day ends.
The first-run usage prompt stays on screen after the server stops offering
it, so the launch notice reads whether it is showing directly, and before
launch day it also waits for the usage status to load. The update notice
keeps rechecking through the whole window, so one already on screen when
the day starts steps aside, and both notices stop their timers once the
window is over.
Same utm_source and utm_medium as Radar's Cloud links, so radarhq.io
analytics count visits from the notice. The tag is identical for every
install.
@roylibman

Copy link
Copy Markdown
Contributor

Two things:

  1. Copy: shorter, and a more direct ask. Suggested, keeping the Radar â™Ĩ Agents title:

    • Launch day: "We just launched AI investigations and the MCP server. If Radar has made Kubernetes a little easier for you, a comment on the launch would mean a lot. It helps other engineers find Radar." Link: Comment on Product Hunt → · How it works
    • Before: "We're launching AI investigations and the MCP server on Product Hunt. We'd love to see you there." Link: Follow on Product Hunt → · How it works

    Product Hunt explicitly allows asking people to visit and comment, so this stays within their rules (still no upvote ask).

  2. Why not show it to in-cluster and Cloud users? In-cluster is about 410 active installs a weekday next to ~1,270 local, and each can have several people behind it. It's one card, one day, non-blocking and dismissible. If the concern is promoting to teammates who didn't install Radar, we could show in-cluster only the launch-day card. Cloud would need its own change in the Cloud web app.

The launch date, link and on/off switch now come from the update-check
response, falling back to the built-in Oct 29 window when the check
doesn't answer, so the launch can move or be called off without a
release. In-cluster installs get the launch-day card. Launch-day copy
asks for a comment.
@nadaverell nadaverell changed the title Show a local-only notice for the Oct 29 Product Hunt launch Product Hunt launch notice, with the launch date from the update check Oct 28, 2026
The card keeps what it last showed through its exit fade, so calling
the launch off while it is visible no longer renders an empty link, and
the day's end no longer flashes the pre-launch copy. The version-check
handler adds the launch to a copy of the cached result, and Desktop's
manual check carries the launch too. A dismissal that localStorage
refuses still frees the corner for the page.
A page left open now picks up a launch moved or called off upstream,
and a launch switched back on no longer opens over a usage prompt that
appeared while it was off.
â€Ķand the pre-launch ask

Replaces the one-time sweep with a light that circles the border and
fades on a cycle longer than the lap, stronger on light surfaces; the
rocket drifts while the card is open; both stop under reduced motion.
The links stay on one row, and the pre-launch card gives the same
reason to help as the launch-day card, asking for a follow.
During the launch window, once someone closes the card, a green rocket
labelled Product Hunt sits above What's new; clicking it brings the
card back at once. It follows the card's audience and window, and goes
when the launch ends or is called off.
â€Ķprompt

With the version check now refetched hourly, a release found while the
page is open could stay hidden behind an earlier dismissal, or open on
top of the usage prompt. The update-notice test pins the launch off so
it passes on launch day too.
The card now sits beside the sidebar's Product Hunt item and grows out
of it, following the sidebar as it expands or collapses, and shrinks
back into it when closed. The item stays for the launch window as the
card's home. Where the sidebar isn't on screen the card keeps the
bottom-right corner.
@cursor

cursor Bot commented Oct 28, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

â€Ķn screen in short windows

A tilted green tag reads TODAY on launch day and the date before it, so
the item reads as a one-off. The anchored card is capped to the space
above its item and scrolls inside, keeping Close reachable.
@nadaverell
nadaverell merged commit b009863 into main Oct 28, 2026
11 checks passed
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.

2 participants