Commit graph

23 commits

Author SHA1 Message Date
SkateSpots
b2a6108eeb refactor: split non-component exports (react-refresh) into their own modules
Removes the last react-refresh disables by splitting exports instead:
- contexts/language.ts: Language/Translations types + LanguageContext +
  useTranslation/useT (LanguageProvider stays a component-only file); 12
  importers repointed.
- lib/sortOptions.ts: calculatePopularity + calculateDistance (out of SortDropdown)
- lib/trustFilter.ts: TrustFilterLevel + filterByTrustLevel (out of TrustFilter)
- EventCountdown: deleted the unused useEventStatus hook
- NewsletterPage: dropped the NEWSLETTER_ISSUES re-export shim
- AGENTS.md updated (lint stays clean with no blanket disables)

Gate: 101 tests, 0 errors/warnings, boot smoke green.
2026-09-26 23:29:42 +07:00
SkateSpots
c0aec3d912 chore(lint): reach zero warnings (react-refresh)
The last 7 react-refresh warnings are dev-only HMR DX from intentional
component+hook/helper colocations (EventCountdown, SortDropdown, TrustFilter,
LanguageContext, NewsletterPage). Splitting them into new files is broad import
churn for no runtime benefit, so each carries a justified file-level disable.

npm test: 0 errors, 0 warnings, 101 tests; boot smoke green.
2026-09-26 22:23:45 +07:00
SkateSpots
8cf35cf7db perf(bundle): entry chunk 1835 KB -> 724 KB
Data-driven pass (adds rollup-plugin-visualizer behind ANALYZE=1):
- MapPage was statically imported by the router, dragging the map route AND the
  IndexedDB offline-cache layer into the entry -> now lazy()
- NewsletterOverlay imported NEWSLETTER_ISSUES from the whole NewsletterPage
  module -> types + data moved to lib/newsletterIssues.ts
- SasquatchGuide (assistant overlay) lazy-loaded in Layout
- Cashu stack is now a separate chunk (useCashu), off the critical path

Net: entry down ~61%; first paint no longer parses the map, the newsletter
page, the assistant or the wallet stack.
2026-09-26 19:37:11 +07:00
shakespeare.diy
c9b0571de9 feat(ux): graceful image fallbacks for broken content images (1.2.18)
Added <ImageWithFallback> — a drop-in <img> that shows a subtle placeholder
(skate emoji or a caller-supplied icon) instead of the browser's broken-image
glyph when a user-supplied URL is missing or 404s. Fills the same layout box so
nothing shifts.

Swapped it into the content-image surfaces that display user-uploaded URLs:
- Marketplace item cards (grid + purchase dialog)
- Spot detail (hero + gallery thumbs) and map list/popup cards
- Shop detail (hero + gallery)
- Crew & Lab cross-link cards (icon fallback)
- Crew agent panel, newsletter issue view + notification bell newsletter thumb
- Stash gear cards (list + grid), profile banner (NIP19), newsletter spot cards

Left untouched: avatars (shadcn Avatar already has fallbacks), QR codes and
rider-card/print images (data URLs, never 404), and in-form upload previews
(local object URLs).

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-09-07 19:46:40 +07:00
shakespeare.diy
dc410106b3 Newsletter: subscriber count + admin archive backfill to Nostr
Two follow-ups to the Nostr-native newsletter (skipped auto-DM by design —
too spammy/fragile for now; the bell mailbox already covers the inbox feel).

Subscriber count (social proof):
- useNewsletterSubscriberCount tallies public NIP-78 subscription markers
  (deduped per author, counting current "true" state).
- Shown under the subscribe CTA as "Join N+ skaters getting the drops",
  hidden until it's meaningful (>=3) and rounded once it grows.

Archive backfill (consistency without losing the rich page):
- lib/newsletterArticle.ts converts a static NEWSLETTER_ISSUES entry into a
  NIP-23 (kind 30023) article — structured sections rendered to Markdown,
  stable slug `issue-N`, published_at from the issue date.
- NewsletterBackfillPanel (admin-only) diffs the static archive against what's
  already on-relay and publishes only the missing issues; safe to re-run,
  reports partial failures. The rich static page rendering is untouched.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-09-03 19:21:09 +07:00
shakespeare.diy
08f74d7991 Add Nostr-native newsletter: subscribe, mailbox & notifications
Turn the static newsletter into a live, Nostr-native marketing channel that
npubs can subscribe to and receive in-app.

Publishing (admins):
- Newsletter issues are published as NIP-23 long-form articles (kind 30023)
  tagged `skatespotsnews`, on the community relay.
- NewsletterComposer: admin-only dialog to write + publish an issue (title,
  slug, summary, cover image, Markdown body).

Subscribing (any npub):
- useNewsletterSubscription: per-user opt-in stored as a NIP-78 (kind 30078)
  marker, so it syncs across every device the user logs into.
- NewsletterSubscribeButton on the /newsletter page and issue reader.

Mailbox / notifications:
- New "News" tab in the NotificationBell showing all issues, with an unread
  badge for subscribers (tracked via a per-account last-read timestamp).
  Latest unread drop also surfaces in the "All" tab.
- Opening the bell or the /newsletter page clears the News badge.

Reading:
- useNewsletterIssues: queries admin-authored issues (author-scoped + tag +
  admin re-validation as the trust boundary against spam).
- LiveIssuesSection on /newsletter shows issue cards linking to a reader.
- NewsletterIssueView: naddr reader (wired into NIP19Page for kind 30023) with
  a small safe Markdown renderer, zap + subscribe CTAs.

Docs: NIP.md documents the 30023 issue schema, the 30078 subscription marker,
and the admin trust boundary.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-09-03 19:16:49 +07:00
shakespeare.diy
13934c0e74 Fix newsletter admin gating: use isAdminPubkey from lib/admins instead of undefined NEWSLETTER_ADMIN_PUBKEYS
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-08-20 16:16:09 +07:00
shakespeare.diy
8b080fb7f1 Spot detail: make mapper clickable + add Message Mapper button
The "Tip the Mapper" card now links the avatar/name to the mapper's profile
(/{npub} via the NIP-19 router) and adds a "Message Mapper" button that opens
an encrypted DM (/messages/{npub}). Makes it easy to contact whoever added a
spot — e.g. to ask them to add photos to a photoless submission. The message
button is hidden when you're viewing your own spot.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-08-15 10:03:58 +07:00
shakespeare.diy
aba79900e4 Newsletter Drop #005: OpenCrack roast, bigger Lab, Crews web-of-trust
Add issue #5 (2026-08-08) to NEWSLETTER_ISSUES with a Groucho-Marx satiric
tone. Highlights: the 3x-bigger Lab (10 crafts), the Lab mobile grid fix,
Crews covering every scene with opt-in visibility + web-of-trust vouching,
the redesigned CrewDetail page, and Music<->Events interconnect. Mocks
"OpenCrack" for volunteering to fix Bitcoin's crypto libraries, and owns
that the app has never been audited (one day it will be — and we'll shoot
ourselves in both feet). Includes matching nostrText teaser for kind 1.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-08-10 23:15:50 +07:00
shakespeare.diy
f4318a8b50 Add Newsletter Drop #004 (Sasquatch Pro, Crews, Angor, Coldcard PSA)
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-08-06 09:55:52 +07:00
shakespeare.diy
ef9bbea465 feat: replace Geyser with Angor across the entire app
Remove all Geyser.fund references and replace with the SkateSpots Angor
project (angor1qtunna00uqyx52rr0nvqa059z2gknhrmn7urd6z).

- SupportersPage: remove Geyser leaderboard + API calls entirely; replace
  Supporters section with an Angor CTA card including the on-chain wallet
  address (bc1q2hdfyqa7utrxrd95rlr27shsdr6gtk7dzdqres)
- useGrowthStats: delete useGeyserStats hook + GEYSER_API_URL constant
- CommunityStatsPage: remove Geyser stats widget, replace with Angor CTA
- SasquatchGuide: update system prompt + FAQ (is it free, supporters)
- NewsletterPage: update both Geyser links (body + footer) to Angor
- AboutPage: remove Geyser row, update Angor entry with real project URL
- README.md: update crowdfunding section + credits

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-30 13:23:55 +07:00
shakespeare.diy
f938a6c900 Newsletter #003: harder tone, extensive coverage of the full session
Expanded Drop #003 from 7 to 16 update cards covering everything actually
shipped this session (per git log), grouped: the geolocation war (crash
fix, parallel first-fix GPS, progress UI, you-are-here pin, crash-proofing,
no-provider messaging), Spot Status Reports (reporting, trust/recency
consensus, badges, gone-spot hiding), Quick Snap camera-first + snap→Add
Spot, Amber signing timeout + plugin fix, crew/Lab DELETION via NIP-09
(framed as the new deletion capability, not the existing features), and
native build plumbing.

Cranked the tone harder throughout and leaned fully into the "weekly
newsletter, shipped whenever the f*** we want" bit in both the vibe line
and masthead. Updated nostrText to match.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-25 01:10:54 +07:00
shakespeare.diy
35c7283970 Newsletter: add Drop #003 (geolocation saga + Spot Status Reports)
New issue covering everything shipped this session, written funny:
- Near Me crash fix (Kotlin 2.1 alignment)
- Parallel first-fix GPS strategy that works on GrapheneOS / no Play Services
- "Locating you…" / "Found you" progress feedback
- "You are here" user-location pin
- Community Spot Status Reports (active/bust/skate-stopped/closed/gone)
- Gone spots hidden from map markers
- Defensive native geolocation hardening

Also updated the masthead tagline to lean into the "weekly newsletter,
shipped whenever the f*** we want" bit. Includes ready-to-post nostrText
for Drop #003.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-25 01:06:24 +07:00
shakespeare.diy
08e20b0f39 newsletter: fix hash-router URL (#/newsletter), add to desktop More dropdown
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 20:59:29 +07:00
shakespeare.diy
bb89a6d3a5 newsletter: expand #002 nostrText and add Lab/Events UX + Android build fix entries
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 20:43:20 +07:00
shakespeare.diy
4d2b27107a newsletter: fix Edit first button — opens inline textarea, Preview toggle, publish with edited text
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 20:35:59 +07:00
shakespeare.diy
05463eabb4 newsletter: add issue #002 — map redesign, settings iOS overhaul, wallet, rider card, v1.0.54
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 20:29:06 +07:00
shakespeare.diy
9ed2c12de1 fix: remove sponsor mention + add Nostr preview modal before publishing
- "Sponsors see the organic number" -> "Users can now see both numbers"
- PublishToNostrButton now opens a preview modal first (NostrPreviewModal):
  - Mock Nostr post card: avatar, display name, timestamp, post body
  - nostrText rendered with hashtags in blue and URL underlined
  - Fake engagement bar (replies/reposts/zaps at 0) for visual context
  - Character count shown below the card
  - Two actions: "Edit first" (closes modal) / "Publish" (confirms)
  - Full-width on mobile, correct safe-area handling via Dialog component
  - isPending state flows through so button shows "Publishing..." while signing

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-18 15:12:37 +07:00
shakespeare.diy
e4a9b454a4 fix: rename issue -> drop, fix hashtags, add 6 tags
- "Issue" replaced with "Drop" everywhere in UI and copy:
  Drop #001, Weekly Drops, Write Drop #002, next drop, etc.
- nostrText: hashtags consolidated to one line (some clients break
  each hashtag onto its own line when separated by newlines)
- nostrText: removed "Full issue:" prefix — bare URL unfurls cleaner
- 6 hashtags added: #skateboarding #nostr #skatespots #spotr
  #newsletter #skatespotsnews
- Publish button tags updated to include all 6 as t-tags
- Template comment updated to match new format

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-18 15:09:32 +07:00
shakespeare.diy
b5edb0ab52 fix: nostrText format — short teaser, URL as the star
Kind 1 notes render differently on every client (Damus, Primal, Amethyst,
Snort, etc). The fix: keep the kind 1 as a 5-line teaser that works as
plain text on any client, with the full formatted issue at the URL.

Issue #001 nostrText trimmed from 14 lines to 4.
Added template comment with rules for all future issues:
- Max 5 content lines before the URL
- No bullet lists
- URL always on its own line
- 3 hashtags max

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-18 15:00:26 +07:00
shakespeare.diy
4f7b741d77 fix: newsletter mobile layout — full phone support
- Page container: py-8 on mobile + pb-24 so content clears fixed bottom nav
- Masthead headline: single line (no br), text-4xl mobile / text-6xl sm+
- Issue header: vertical stack on all screens — date/badge row, large number,
  vibe text, then publish button full-width on mobile / auto on sm+
- Stats grid: always 3 cols (clean 2-row layout on phone), larger text-2xl
  numbers, text-[10px] labels readable on all Androids, shorter relay label
- Floating pill: max-w-[calc(100vw-1.5rem)] prevents overflow on narrow screens,
  right-3 tighter margin, whitespace-nowrap on text, touch-manipulation + 
  active:scale-95 for native tap feel, correct bottom offset for iOS safe area
- Monday admin banner: unchanged, already stacks correctly

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-18 14:56:30 +07:00
shakespeare.diy
248f5b5ff2 feat: newsletter v2 — structured issues, live stats, Nostr publish button
Structured issue schema (NewsletterIssue):
- updates[]: typed update items with icon/title/tag/body
- spotOfTheWeek?: optional typed spot block
- communityNote: free-text community section
- nostrText: plain-text ready to post as kind 1

Live community stats block (LiveStatsBlock):
- Pulls from useGrowthStats on every page load
- Shows spots, shops, events, mappers, coaches, tours
- Trusted/active account counts shown below spots + mappers
- "Live · pulled from goskatespots.nostr1.com" attribution

Publish to Nostr button (PublishToNostrButton):
- Only visible to 2 admin pubkeys — nobody else sees it
- Publishes kind 1 with nostrText + tags (skateboarding, skatespots, nostr)
- Includes relay URL tag pointing to /newsletter
- One-shot: button becomes "Published to Nostr" checkmark after success
- Full error handling with toast

Issue template now enforces consistent sections every week:
1. Community by the Numbers (live stats)
2. What's New (typed update cards)
3. Spot of the Week (optional — shows placeholder when omitted)
4. Community note
5. Support / Geyser

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-18 14:45:59 +07:00
shakespeare.diy
c146d94b9f feat: weekly newsletter system with Issue #001
- NewsletterPage (/newsletter) — zine aesthetic, dark bg, neon accents
  Issue #001 covers all 8 security measures shipped this week:
  geohash validation, URL sanitization, content limits, WoT defaults,
  trusted stats, OfficialBadge, marker clustering, DM phishing warning

- NewsletterOverlay — two overlays rendered globally via Layout:
  1. Floating "Latest Drop" pill — shows for 7 days after each issue,
     dismissible per-issue via localStorage, hides on /newsletter page
  2. Monday admin reminder — only visible to 2 authorized pubkeys
     (founder + second admin), shows every Monday, one-click opens
     Shakespeare AI with prompt pre-filled to write the next issue,
     dismisses for the rest of that Monday via localStorage

- Footer — Newsletter link added to desktop footer alongside License/Supporters

- AppRouter — /newsletter route added (lazy loaded)

To add Issue #002: prepend a new object to NEWSLETTER_ISSUES array
in NewsletterPage.tsx. The pill and Monday reminder auto-update.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-18 14:39:54 +07:00