Skip to content

feat(share): re-add Add-to-RoadFlare button on driver shares (roadflared:)#10

Merged
variablefate merged 3 commits into
mainfrom
feat/add-roadflared-driver-button
May 12, 2026
Merged

feat(share): re-add Add-to-RoadFlare button on driver shares (roadflared:)#10
variablefate merged 3 commits into
mainfrom
feat/add-roadflared-driver-button

Conversation

@variablefate
Copy link
Copy Markdown
Owner

Closes #2. Supersedes draft #4 (which can be closed — same intent, rebased onto current main with rationale updated for the post-Universal-Links world).

Summary

Re-introduces the in-page "Add to RoadFlare" CTA on /share/d/<npub> driver share pages, deleted in #6 for being non-functional pre-iOS-1.0. With variablefate/roadflare-ios#66 (custom roadflared: scheme) and #113 (Universal Links) both merged, this button is now a functional one-tap dispatch into the Add Driver flow.

Why roadflared: and not https://

The https:// Universal Link path looks tempting (and was the original "revert" intent in the Universal Links PR's followup list), but a button with href="https://roadflare.app/share/d/<npub>" ON the /share/d/<npub> page itself does nothing — Safari treats same-URL clicks as no-ops, so no Universal Link handoff happens. The custom roadflared: scheme is the deterministic way to invoke the app from this surface, and matches the rationale PR #66 originally noted for keeping the scheme for in-app QR/clipboard flows.

Why a button at all (vs. Smart App Banner only)

PR #8's Smart App Banner is the iOS-native one-tap surface but only renders in iOS Safari. This button covers the surfaces it doesn't:

  • Chrome / Firefox / DuckDuckGo on iOS (Smart App Banner is a Safari-specific meta tag)
  • Any browser on Android
  • Desktop browsers when the page is shared cross-device
  • Other Nostr-aware clients (drivestr, ridestr) where the user has RoadFlare installed but isn't on Safari

roadflared: is registered system-wide on iOS once RoadFlare is installed, so the dispatch works regardless of which browser surfaces the share page. Browsers without a handler (desktop, Android-without-app) get the normal "no app to handle this" prompt — graceful enough since the App Store buttons below provide the install path. The Smart App Banner continues to surface independently on iOS Safari, so iPhone users get both the top-of-page native banner AND the in-content button.

Visibility

Driver shares only (/share/d/<npub>). Rider shares (/share/r/<npub>) remain untouched — no rider-side iOS app registers a handler yet, so showing the button there would dead-tap. Tracked in #3.

Diff

404.html — 14 insertions (1 HTML element + 11 lines JS in renderSharePage).

Interaction with the broader deep-link surface

Layer Where Status
In-page CTA — cross-browser one-tap this PR adds
Smart App Banner — iOS Safari top-banner #8 preserved (independent surface)
Custom roadflared: scheme — app-side handler roadflare-ios#66 merged
Universal Links — share-URL → app post-install roadflare-ios#113 merged
App Clip — pre-install context bridge roadflare-ios#75 tracked

Test plan

  • Visit /share/d/<real-npub-with-display-name> → button visible above the store buttons, href is roadflared:npub1...?name=... with the display name URL-encoded correctly
  • Visit /share/d/<npub-without-display-name>href is roadflared:npub1... (no ?name= param)
  • Visit /share/r/<npub> → button NOT visible (rider share)
  • Tap on iPhone with RoadFlare installed → Add Driver sheet opens pre-filled
  • Tap on iPhone WITHOUT RoadFlare → system "no app to handle" dialog → user can install via App Store button below
  • Tap on Android / desktop → graceful no-app dialog → App Store / Play Store buttons remain available below
  • iOS Safari: Smart App Banner from Add Smart App Banner to driver share pages #8 still surfaces at the top independently
  • Cross-browser on iOS: button works in Chrome/Firefox/DuckDuckGo (these browsers don't show the Smart App Banner but the roadflared: link still dispatches to the iOS handler)

🤖 Generated with Claude Code

Closes #2. Supersedes draft #4.

Re-introduces the in-page "Add to RoadFlare" CTA on `/share/d/<npub>`,
deleted in #6 for being non-functional pre-iOS-1.0. With variablefate/roadflare-ios#66
(roadflared: URL scheme) and #113 (Universal Links) both shipped, the
button is now functional via the custom scheme.

## Why roadflared: and not https://

A button with `href="https://roadflare.app/share/d/<npub>"` on the share
page itself wouldn't fire — Safari treats same-URL clicks as no-ops, so
no Universal Link handoff happens. The custom scheme is the deterministic
way to invoke the app from this surface.

## Why a button at all (vs. Smart App Banner only)

The Smart App Banner from #8 only renders in iOS Safari. This button
covers the surfaces it doesn't:

- Chrome / Firefox / DuckDuckGo on iOS
- Any browser on Android
- Desktop browsers when the page is shared cross-device
- Other Nostr-aware clients (drivestr, ridestr) where the user has the
  RoadFlare app installed but isn't on Safari

`roadflared:` is registered system-wide on iOS once RoadFlare is installed,
so the dispatch works regardless of browser. Browsers without a handler
(desktop, Android-without-app) get the normal "no app to handle this"
behavior — graceful, since the App Store buttons below provide install.

## Visibility

Driver shares only (`/share/d/<npub>`). Rider shares (`/share/r/<npub>`)
remain untouched — no rider-side iOS app registers a handler yet, so
showing the button there would dead-tap. Tracked in #3.

## Test plan

- [ ] Visit `/share/d/<real-npub>` → button visible above store buttons, href is `roadflared:npub1...?name=...` with display name URL-encoded correctly
- [ ] Visit `/share/d/<npub-without-display-name>` → href is `roadflared:npub1...` (no name param)
- [ ] Visit `/share/r/<npub>` → button NOT visible
- [ ] Tap on iPhone with RoadFlare installed → Add Driver sheet opens pre-filled
- [ ] Tap on Android / desktop → graceful no-app dialog (App Store buttons still available below)
- [ ] Smart App Banner from #8 still surfaces independently on iOS Safari

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Several minor fixes to make the share page sit cleanly on a single
mobile viewport without any horizontal scrolling. No layout / design
changes — same vertical order, same components, same colors.

## Horizontal scroll fix

The `.account-id-btn .npub-text` flex item had `white-space: nowrap` +
`text-overflow: ellipsis` but no `min-width: 0`. The flex default of
`min-width: auto` won't shrink a child below its intrinsic content
width — and the npub is 63 characters of unbreakable monospace, so
the button refused to truncate and pushed past the viewport.

`min-width: 0` lets the flex child shrink and the ellipsis kick in.
Pairs with `overflow-x: hidden` on `body` as a safety net so any
future stray-wide element won't reintroduce sideways scroll.

## QR widening

`generateQR` was called with size 160 — visibly tiny on a 390px+
viewport. Bumped to 240 (the canvas `width`/`height` attributes
matched, so initial layout doesn't shift). The canvas now also has
`max-width: 100%; height: auto;` so it scales down gracefully on
iPhone SE (320px viewport, ~272px content area).

## Container padding on very small screens

Container padding stays at `2rem 1.5rem` on all "normal" phones.
For ≤360px viewports (iPhone SE / Mini), reduce horizontal padding
to `1rem` — gains 16px of usable width without visibly changing
margins on larger devices.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@variablefate
Copy link
Copy Markdown
Owner Author

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

Three pass-2 findings on top of the original PR:

## 1. Driver button visible on rider shares (high)

The `<a class="btn btn-primary" hidden>` element used the HTML `hidden`
attribute, which CSS `display: flex` on `.btn` overrides — so the button
was rendered visible on every share page, including rider shares where
the JS never sets the `roadflared:` href. Result: riders saw a primary
"Add to RoadFlare" CTA pointing at `#`.

Switched to the file's existing `.hidden` class convention (used at lines
329, 340, 347, 375, 384) — which lives later in the stylesheet than
`.btn` so source-order wins. JS now toggles via `classList.remove('hidden')`
instead of the broken `.hidden = false` property.

## 2. Long Nostr display names re-trigger horizontal scroll (medium)

`.profile-name` and `.vehicle-text` had no `overflow-wrap` rule. A long
unbroken display_name or vehicle string from a kind-0 event would push
the card past the viewport — defeating the npub-truncation fix from the
previous commit. Added `overflow-wrap: break-word` to both (broader
browser compat than `anywhere`, same behavior for our use case).

## 3. `min-width: 0` looked deletable (low)

Added an inline comment explaining the flex-shrink invariant so a future
maintainer doesn't strip it during a "remove unused rules" pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@variablefate variablefate merged commit bc53444 into main May 12, 2026
@variablefate variablefate deleted the feat/add-roadflared-driver-button branch May 12, 2026 01:32
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.

Restore driver-share "Add to RoadFlare" button with roadflared: deep link

1 participant