diff --git a/AGENTS.md b/AGENTS.md index 7d16ef9..d638863 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -345,7 +345,12 @@ session with **no other memory of this project**. So: aren't hard-coded**, so Marketplace/Mints (and any future section) are always reachable on mobile — don't re-hardcode only a subset. - **App Shop** (`/app-shop`, `src/pages/AppShopPage.tsx`): SkateSpots merch, to be - paid in **sats only (Lightning or Cashu)** — no cards/accounts. Registered in + paid in **sats only (Lightning or Cashu)** — no cards/accounts — sold + **locally, on request**: there is **no cart, no checkout, no shipping**. Buying + is a conversation: "Request an item" deep-links to a **DM with the owner** + (`/messages/`, owner = `PLATFORM_OWNER_PUBKEYS[0]`), the details + are agreed in chat, and sats change hands at handover. Don't add shipping + copy/rates or a cart without a decision to change that model. Registered in `NAV_CATALOG` as id `app-shop` (label "App Shop", `ShoppingBag`), which is what makes it appear in **both** the desktop "More" menu and the mobile burger menu (the mobile menu appends catalog items not in `MOBILE_MENU_LISTED_HREFS`). It is diff --git a/src/pages/AppShopPage.tsx b/src/pages/AppShopPage.tsx index 5d2d03c..d13290f 100644 --- a/src/pages/AppShopPage.tsx +++ b/src/pages/AppShopPage.tsx @@ -1,21 +1,27 @@ import { useSeoMeta } from '@unhead/react'; import { Link } from 'react-router-dom'; +import { nip19 } from 'nostr-tools'; import { ShoppingBag, Zap, Coins, - Truck, Shirt, Sticker, Package, Hammer, Sparkles, - BadgeCheck, + MapPin, + MessageCircle, ArrowRight, } from 'lucide-react'; import { PageHeader } from '@/components/PageHeader'; import { NewsletterSubscribeButton } from '@/components/NewsletterSubscribeButton'; import { Button } from '@/components/ui/button'; +import { PLATFORM_OWNER_PUBKEYS } from '@/hooks/useListingRestrictions'; + +/** Where "request an item" goes: an encrypted DM straight to the shop owner. */ +const SHOP_OWNER_NPUB = nip19.npubEncode(PLATFORM_OWNER_PUBKEYS[0]); +const REQUEST_HREF = `/messages/${SHOP_OWNER_NPUB}`; /** * App Shop — SkateSpots merch. @@ -38,8 +44,7 @@ const PLANNED = [ const PAY_CHIPS = [ { icon: Zap, label: 'Lightning' }, { icon: Coins, label: 'Cashu' }, - { icon: Truck, label: 'Shipped worldwide' }, - { icon: BadgeCheck, label: 'At cost, no markup theatre' }, + { icon: MapPin, label: 'Local handover' }, ]; export default function AppShopPage() { @@ -81,12 +86,30 @@ export default function AppShopPage() {

- Merch for the people who keep this thing rolling. Paid in{' '} - sats — Lightning or Cashu, - whichever you already keep. No cards, no accounts, no middleman skimming the drop. + Merch for the people who keep this thing rolling — sold{' '} + locally, on request. You message + me, we sort the details, and you pay in{' '} + sats — Lightning or Cashu — + when you collect it. No cards, no accounts, no checkout robot, no middleman + skimming the drop.

-
+
+ + + Opens a private, encrypted DM with me. + +
+ +
{PAY_CHIPS.map(({ icon: Icon, label }) => (

- How it'll work + How buying works

+ + it's a DM, not a cart +
    {[ - { n: '1', t: 'Pick your thing', d: 'One page, no logged-in pricing games, no fake urgency.' }, - { n: '2', t: 'Pay in sats', d: 'Lightning or Cashu. Straight to us — no processor in the middle.' }, - { n: '3', t: 'It ships', d: 'Posted to your door with an honest tracking number.' }, + { + n: '1', + t: 'Message me', + d: 'Send a DM with what you want — item, size, colour, whatever you are after.', + }, + { + n: '2', + t: 'We sort it out', + d: 'Price in sats, and where and when to meet. It is a conversation, not a checkout.', + }, + { + n: '3', + t: 'Pay in sats', + d: 'Lightning or Cashu at handover, then it is yours. No shipping, no waiting rooms.', + }, ].map((s) => (
  1. The honest bit: we hold no stock and - nothing here is for sale. There are no pre-orders, no countdown timers and no - fake scarcity — when there is something real to buy, this page will say so and - take your sats. Until then it is just an empty shop with good lighting. + nothing here is for sale. There are no pre-orders, no countdown timers and no fake + scarcity — and it is local handover only, + arranged by DM, so there is no shipping of any kind. When there is something real, + this page will say so and we will sort the details between us. Until then it is + just an empty shop with good lighting.