diff --git a/AGENTS.md b/AGENTS.md
index 256e0c2..11c7ac1 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1537,6 +1537,14 @@ session with **no other memory of this project**. So:
auto-opened welcome modal. ⚠️ `SignupDialog` is a **default-only** export, so
lazy-load it as
`lazy(() => import('…/SignupDialog'))`.
+ - **Pass the app on — Android only (2026-10-26):** the About page renders
+ `ShareAppCard` when `getPlatform() === 'android'` (APK/Zapstore; hidden on
+ web/iOS): a **QR of the Zapstore listing** (`APP_INSTALL_URL` in
+ `lib/platform.ts`, single-sourced), a **share-sheet** button (Nearby
+ Share/SMS/etc.), and `NfcWriteButton` to write the install URL to an NFC tag.
+ ⚠️ Deliberately **no peer-to-peer APK transfer** — that needs native Wi‑Fi
+ Direct/BLE + a `PackageInstaller` flow and real-device QA; Zapstore handles
+ installs/updates. (Not visually verified on-device yet.)
- **First-run checklist + backup-reminder gating (fixed 2026-10-12).** Two
onboarding prompts nagged returning users:
1. `FirstRunChecklist` (map) showed for **any logged-in user** until they
diff --git a/src/components/ShareAppCard.tsx b/src/components/ShareAppCard.tsx
new file mode 100644
index 0000000..314b429
--- /dev/null
+++ b/src/components/ShareAppCard.tsx
@@ -0,0 +1,78 @@
+import { useState } from 'react';
+import { Check, Share2 } from 'lucide-react';
+import { Card, CardContent } from '@/components/ui/card';
+import { Button } from '@/components/ui/button';
+import { QRCodeCanvas } from '@/components/ui/qrcode';
+import { NfcWriteButton } from '@/components/NfcWriteButton';
+import { useTranslation } from '@/contexts/language';
+import { useToast } from '@/hooks/useToast';
+import { APP_INSTALL_URL, getPlatform } from '@/lib/platform';
+
+/**
+ * "Pass the app on" — Android only (APK / Zapstore).
+ *
+ * The QR carries the **Zapstore listing** for this app; scanning it on another
+ * Android phone opens the store page and installs/updates via Zapstore. The
+ * share button hands the same link to Android's share sheet (Nearby Share,
+ * Bluetooth, messages…), and — where the device supports NFC writing — the link
+ * can be written to a tag for a genuine tap-to-open handoff.
+ *
+ * We deliberately do NOT move APK bytes peer-to-peer: that needs native
+ * Wi‑Fi Direct/BLE + a PackageInstaller flow and real-device QA, and Zapstore
+ * already handles installs/updates. Renders nothing off Android (iOS can't
+ * sideload; desktop has no use for it).
+ */
+export function ShareAppCard() {
+ const { t } = useTranslation();
+ const { toast } = useToast();
+ const [copied, setCopied] = useState(false);
+
+ if (getPlatform() !== 'android') return null;
+
+ const share = async () => {
+ try {
+ if (navigator.share) {
+ await navigator.share({
+ title: 'SkateSpots',
+ text: t('settingsUi.about.downloadAppDesc'),
+ url: APP_INSTALL_URL,
+ });
+ return;
+ }
+ await navigator.clipboard.writeText(APP_INSTALL_URL);
+ setCopied(true);
+ toast({ title: t('common.copied'), description: APP_INSTALL_URL });
+ window.setTimeout(() => setCopied(false), 1600);
+ } catch {
+ // Share sheet cancelled — nothing to report.
+ }
+ };
+
+ return (
+
+ {t('common.share')} SkateSpots
+ {t('settingsUi.about.downloadAppDesc')}