Skip to content

feat(boost): clickable lane cards with hover, live click counts, compact mobile rows - #99

Merged
kevincodex1 merged 3 commits into
mainfrom
feat/boost-clicks
Oct 16, 2026
Merged

kevincodex1 merged 3 commits into
mainfrom
feat/boost-clicks

Conversation

@kevincodex1

@kevincodex1 kevincodex1 commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

What

Makes the Boosted lane worth paying for: the whole card opens the token, cards react on hover, each card shows how many clicks it got from the lane, and phones see all five places at once.

Lane cards

  • Whole card is clickable. Uses the same pattern as LaunchCard (the name link covers the card). "Latest burn" stays its own link above it. Keyboard focus rings the whole card.
  • Hover: warm tint, a still warm edge, an arrow, a slightly larger avatar, a brighter fuse. Only with a mouse (no stuck hover on phones; a tap shows a pressed shade). Reduced motion keeps only the colours. Nothing loops.
  • Click count on each card: pointer icon + clicks from the lane in the last 24 h (the same window as the TWIG figure). Hidden at 0, so a fresh boost never reads "0". It rolls up when the live poll brings more, and has a screen-reader label.
  • Phones (< 640px): each card is a compact two-line row (name left; TWIG, clicks and time left on the right). That's about 62px a card instead of about 110px, so all five places fit on one screen. "Latest burn" shows from 640px up; on phones it's on the token page. The 640px+ layout is unchanged.

Tracking (only while boosted)

  • POST /api/boost/seen (sendBeacon, never delays the click):
    • View: one per page load when the lane is on screen.
    • Click: a click, Cmd/Ctrl-click or middle click on a card.
  • A click counts only while the token is in the lane, at the place the server's lane gives it (never taken from the request). One per visitor, per token, per 30 minutes.
  • Same-origin only (Sec-Fetch-Site / Origin): another site cannot raise a card's count from its own visitors' browsers. Bots skipped, 60/min per IP, 512-byte body.
  • Privacy: the visitor is the daily presence hash mixed with the token. No IP, user agent or wallet is stored. Click rows are pruned after 90 days.
  • Tables: bb_boost_clicks, and bb_boost_views (hourly counts, added up in memory and written every 10 s per machine).
  • The ranking never reads either table (guard test extended).

/admin

  • New "Views and clicks" table under the Boosted lane (24h / 7d / 30d): views, clicks, rate, visitors, TWIG burned, clicks per 100K TWIG. Totals cover every token.
  • Served by GET /api/boost/stats?wallet=<admin>.

Deploy notes

  • Schema: two new tables + indexes, applied by the release command (idempotent, ran twice locally).
  • Set PRESENCE_SALT with this deploy: fly secrets set PRESENCE_SALT=$(openssl rand -hex 32) -a basebid. It isn't set today, so each machine salts visitors differently and a repeat click landing on the other machine counts again. This also fixes the same gap in the site's visit counter.

Testing

  • 1,295 tests pass, tsc and lint clean, production build passes.
  • Real Postgres: beacons, the 30-minute dedupe, not-in-lane, bot and cross-site refusals, the batched view flush, and the stats totals.
  • Headless Chrome: a click on the TWIG figure opens the token and is counted. Screenshots of hover and the click count on desktop, tablet and phone, in light and dark.
  • /code-review high: 9 of 10 findings fixed. Declined: signing the stats read (same ?wallet= pattern as the reported-posts queue; it only holds counts that name nobody).

Summary by CodeRabbit

  • New Features
    • Boosted-lane cards now show recent click counts, and lane views and clicks are tracked on the Home and Base pages.
    • Admins can review views, clicks, click rates, visitors, and TWIG metrics by token and time period.
    • Boosted-lane cards use a more compact layout on small screens.
  • Documentation
    • Added guidance on Boosted-lane engagement metrics and a query for reviewing them.

…sted

- The whole Boosted card opens the token (stretched link, LaunchCard's pattern); "Latest burn" stays its own link
  above it. Keyboard focus rings the whole card.
- Hover: warm tint, a still warm edge, an arrow, a slightly larger avatar, a brighter fuse. Only under a pointer
  that hovers; reduced motion keeps the colours. Nothing loops.
- POST /api/boost/seen (sendBeacon): one view per page when the lane is on screen, and each card click. A click
  counts only while the token is in the lane, at the place the server's lane gives it, once per visitor, token and
  30 minutes. Bots skipped, 60/min per IP, 512-byte body. The visitor is the daily presence hash mixed with the
  token: no IP, user agent or wallet stored.
- bb_boost_views (hourly counts) and bb_boost_clicks; /admin gets a "Views and clicks" table (24h/7d/30d) via
  GET /api/boost/stats for admin wallets. The ranking never reads either table (guard extended).
- Each Boosted card shows its clicks from the lane in the last 24 hours (the window its TWIG is counted in) with a
  pointer icon: nothing at 0, rolls up when a poll brings more, a screen-reader label, and the count in the card's
  tooltip. A pointer, not an eye: one page load is a view for every card, so views would read the same on all five.
- The lane read carries `clicks` (one indexed query per lane build; a failed read shows no counts, never no lane).
- Under 640px a card is a compact two-line row (name left; TWIG, clicks, time left right): all five places fit on a
  phone screen, about 62px a card instead of 110px. "Latest burn" from 640px (the token page has it on a phone).
  One set of parts placed by grid areas, so the stacked card from 640px is unchanged.
- The beacon takes only the site's own pages (Sec-Fetch-Site same-origin, or a matching Origin): another site can no
  longer raise a card's public count from its visitors' browsers (a text/plain beacon needs no CORS preflight).
- Views are tallied in memory and written once every 10 s per machine, not one upsert on the same hot rows per page.
- Click rows are pruned after 90 days (hourly, off the request path); view rows are hourly counts and stay.
- /admin: views, clicks and burns start at the same whole hour; totals are window sums over every token, not the 100
  listed; visitors have no total (counted per token); a period never shows another period's error.
- The lane sends no view for its empty line; the hover arrow is hidden under 640px (it covered the TWIG figure).
- The expiry filter runs once, where the cached lane is read, for pages, polls and beacons alike.
@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: b277b14e-2133-4cef-b022-ddef6b509a3a
📥 Commits

Reviewing files that changed from the base of the PR and between 5287f93 and 67eac37.

📒 Files selected for processing: 14
  • app/db/schema.sql
  • app/src/app/(home)/page.tsx
  • app/src/app/api/boost/seen/route.ts
  • app/src/app/api/boost/stats/route.ts
  • app/src/app/api/write-limits.test.ts
  • app/src/app/llms.txt/route.ts
  • app/src/components/launchpad/BoostAdmin.tsx
  • app/src/components/launchpad/BoostedLane.tsx
  • app/src/components/launchpad/ChainLanding.tsx
  • app/src/components/launchpad/boost-ui.test.ts
  • app/src/lib/launchpad/boost.test.ts
  • app/src/lib/launchpad/boost.ts
  • app/src/lib/launchpad/boostServer.ts
  • docs/boost.md

Included review availability: This review used your included allowance. 2 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 3 reviews per hour.

📝 Walkthrough

Adds view and click tracking for the Boosted lane, stores and aggregates those events, displays click counts on lane cards, and provides boost statistics to admins.

Changes: Boosted lane engagement

Layer / File(s) Summary
Beacon contracts and persistence
app/db/schema.sql, app/src/lib/launchpad/boost.ts, app/src/lib/launchpad/boost.test.ts
Adds beacon validation and bucketing helpers, metric calculations, and database tables for hourly views and deduplicated clicks.
Lane event reporting and click display
app/src/components/launchpad/BoostedLane.tsx, app/src/components/launchpad/ChainLanding.tsx, app/src/app/(home)/page.tsx, app/src/lib/launchpad/boostServer.ts, app/src/components/launchpad/boost-ui.test.ts, docs/boost.md
Reports lane views and regular or middle-clicks from Home and Base. Includes click counts in lane data and displays nonzero counts on cards.
Beacon validation and event recording
app/src/app/api/boost/seen/route.ts, app/src/lib/launchpad/boostServer.ts, app/src/app/api/write-limits.test.ts, app/src/components/launchpad/boost-ui.test.ts
Validates and rate-limits beacon requests. Queues view counts, records eligible deduplicated clicks, and prunes old click records.
Admin statistics and reporting
app/src/app/api/boost/stats/route.ts, app/src/components/launchpad/BoostAdmin.tsx, app/src/lib/launchpad/boostServer.ts, app/src/components/launchpad/boost-ui.test.ts, app/src/app/llms.txt/route.ts, docs/boost.md
Adds admin statistics for views, clicks, visitors, and qualifying boosts. Documents the statistics and updates the lane endpoint description to include clicks.

Priority: ⬇️ Low

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant BoostedLane
  participant SeenRoute as /api/boost/seen
  participant BoostServer as recordBoostSeen
  participant Database
  BoostedLane->>SeenRoute: POST view or click beacon
  SeenRoute->>BoostServer: validated event and visitor hash
  BoostServer->>Database: insert click or queue view count
  Database-->>BoostServer: click insert result
  BoostServer-->>SeenRoute: recording result
  SeenRoute-->>BoostedLane: HTTP 204 response
Loading
Merge Risk: ⚪ Minimal · up to 67eac

No blocking issue is established; the change is ready to merge after normal checks.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly describes the main user-facing changes: clickable Boosted lane cards, hover behavior, live click counts, and compact mobile rows. These changes are present in the pull request.
Docstring Coverage Passed Docstring coverage is 86.21% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 29 functions across 12 files. (2 skipped: 2…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@kevincodex1
kevincodex1 merged commit a2b9404 into main Oct 16, 2026
10 checks passed
@kevincodex1
kevincodex1 deleted the feat/boost-clicks branch October 16, 2026 06:38
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