Commit graph

79 commits

Author SHA1 Message Date
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
5edf4d2a9d map: replace hardcoded Google Maps with universal directions picker (geo:, OSM, Google, Apple)
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 20:46:53 +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
ecf8e0967b fix: add missing SPOT_TYPE_LABELS import to MapPage (SpotBottomSheet crash)
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 20:24:59 +07:00
shakespeare.diy
54e135d976 fix: add missing MapPin import to MapPage (SpotBottomSheet crash)
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 20:23:20 +07:00
shakespeare.diy
f4cdafa145 card: full UX rebuild — hero preview, 3-tab nav, single-column layout, inline award form
- Logged-out state: proper hero with value prop copy instead of bare login form
- Hero card preview: full-width dark stage with theme-matched glow behind card
- Card slightly larger (360x227) with depth shadow
- Top tab bar: My Card / Badges (with count) / Award — replaces buried sections
- Single-column max-w-2xl layout — no more awkward 2-col grid on mobile
- Primary CTA: one big Share button, Print/Save/Copy as secondary 3-col row
- Card type as prominent 2-up tile choice, not a buried dropdown-style control
- Theme picker: 6-up square grid with emoji + label, ring on active
- Rides For + Sponsors side by side (saves vertical space)
- Stats as interactive tiles showing the actual numbers
- Skills as pill grid with live counter (X/6 selected)
- Badges tab: shows ReceivedBadgesPanel (was previously never rendered)
- Award tab: inline form, no dialog — cleaner flow, redirects to Badges on success
- AwardBadgeDialog kept for backward compat but Award tab uses AwardBadgeInline

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 20:20:26 +07:00
shakespeare.diy
2e32605948 map: consolidate right-side controls into single column (pills → divider → Quick Snap)
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 20:10:24 +07:00
shakespeare.diy
be4e0bc986 map: remove duplicate sasquatch, reposition original bubble to bottom-right below Quick Snap
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 20:05:46 +07:00
shakespeare.diy
cc2e3d3165 map: replace Vibed with Shakespeare with Sasquatch trigger button below Quick Snap
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 20:03:19 +07:00
shakespeare.diy
889eb922eb map: move attribution to top-right below Near Me, add Vibed with Shakespeare below Quick Snap
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 20:01:28 +07:00
shakespeare.diy
682e4d802b map: dark tiles, near me button, bottom sheet, floating filter pills
- Swap OSM tiles for CartoDB Dark Matter (near-black bg, neon markers pop)
- Add floating Near Me button (top-right, crosshair icon, flies to user location)
- Add SpotBottomSheet: tap a marker → drawer slides up from bottom with
  spot thumbnail, title, location, type badges, author, View Details + Directions CTAs
  (map stays fully visible behind the sheet)
- Add flyTo prop to SpotMap for programmatic map navigation
- Add floating layer filter pills (spots/shops/gear/tours) on map surface
  bottom-left, always visible, no toolbar required

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 19:57:06 +07:00
shakespeare.diy
1ce2837fef settings: replace 7-tab horizontal scroll with iOS-style vertical menu + sub-screens
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 19:32:38 +07:00
shakespeare.diy
f0eadf307b wallet: remove duplicate balance hero, single CashuWalletCard as source of truth
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 19:29:52 +07:00
shakespeare.diy
1876d14b0f wallet: mobile-first redesign - balance hero, compact status pills, collapsible educational content
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 19:27:14 +07:00
shakespeare.diy
456f42a262 events: apply same UX pattern as /lab — sticky toolbar, filter drawer, location filter, active chips
- Replace scattered filter controls (search + Select dropdowns + ScrollArea chips + TrustFilter dropdown + SortDropdown) with the same unified toolbar + filter drawer pattern used on /lab
- Sticky toolbar: Events/Tours tab toggle with live counts, Upcoming/Past sub-tabs (events only) with counts, inline search + city location inputs, filter button with active count badge
- Responsive filter drawer: bottom sheet on mobile, right side panel on desktop (md:)
- Filter drawer: Sort pills, Trust Level inline pills (no nested dropdowns), Event Type chips (events) or Tour Category + Skill Level chips (tours) — all in one place
- Active filter chips row: selected event types as dismissible pills, sort/trust badges, "Clear all" — only visible when filters are active
- CreateFAB: replaces plain Link button with a dropdown for both "Create Event" and "Create Tour" from any view
- Unified EmptyState component with context-aware "Clear Filters" vs. "Create" CTA
- Dedicated location filter input split from general search (City field)
- Results count shown below toolbar, no empty-height gaps while loading
- Removed: Input, ScrollArea, ScrollBar, Select, Tabs, TabsList, TabsContent, TabsTrigger, TrustFilter, SortDropdown imports (all replaced inline)

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 17:02:46 +07:00
shakespeare.diy
41ede8a122 lab: UX improvements — location filter, responsive drawer, inline trust pills, active filter chips
- Add dedicated City location input field in toolbar alongside search (splits "Name/bio" and "City" search into two focused inputs)
- Fix Filter drawer responsiveness: bottom sheet on mobile, right side panel on desktop (md:) 
- Replace TrustFilter compact dropdown in drawer with inline pill buttons (no nested dropdowns)
- Add active filter chips row in toolbar showing selected skills as dismissible pills, sort/trust badges, and "Clear all" button — only visible when filters are active
- Tab count badges now always show (including zero) to give clear feedback
- Fix results count row: remove empty min-h gap, now only renders when not loading
- Search now also matches against genUserName fallback for pubkey-derived names

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 16:57:49 +07:00
shakespeare.diy
0dc0d272e1 fix: filter panel overlap, Wallet & Stash rename, Sasquatch on all pages
Filter panel (MapPage):
- Sheet now h-[82vh] max-h-[680px] with flex-col layout
- Scrollable content area uses flex-1 min-h-0 (proper flex children)
- "Show Results" button is now flex-shrink-0 at bottom of column
- No more overlap between Show Results and Stash/Tour quick action buttons

Wallet & Stash rename:
- Settings tab renamed from "Wallet" to "Wallet & Stash"
- "Me" dropdown in mobile header shows "Wallet & Stash" for the wallet link

Sasquatch persistent button (all pages):
- Minimized bubble is now ALWAYS visible on every page (not just pages with a guide message)
- Tapping the bubble on any page opens Sasquatch with a generic helpful greeting
- Pages with specific context (/, /map, /lab, /onboarding) still show their custom message
- Pages without context (/wallet, /settings, /stash, /events, etc.) now show a generic "Ask me anything" greeting with common questions
- Removed the separate X close button (minimize was already the same) — bubble stays visible as entry point at all times
- onPointerUp now also sets isVisible=true so panel opens on pages without a message

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 16:45:11 +07:00
shakespeare.diy
340f6fd89f fix(mobile): redesign wallet page UI for mobile + global mobile polish
Wallet page (/wallet):
- Add BalanceHero banner at top showing Cashu balance + wallet status pills
- Cashu/Lightning tabs with colored active states (orange/yellow)
- Remove nested balance display in CashuWalletCard (now shown in hero)
- Compact balance row in CashuWalletCard
- Stacked full-width inputs on mobile (no side-by-side on small screens)
- h-11 touch targets on all inputs and buttons (44px min)
- inputMode="numeric" on number fields (prevents iOS zoom)
- Receive/Send tabs with green/red active colors for clear context
- History items now 52px min height with colored amount text
- WalletComparisonGuide stays collapsed by default
- Fix: add Nut icon import to CashuWalletCard (was crashing)
- All modals use w-[calc(100%-1rem)] for proper mobile sizing

Settings page (/settings):
- 7-tab bar now scrollable horizontally on mobile (no overflow/wrapping)
- -mx-3 bleed trick so scrollable area goes edge-to-edge
- Wallet tab buttons full-width on mobile
- Container max-w-3xl for better desktop centering

FAQ page (/faq):
- Compact hero on mobile (smaller icon, tighter padding)
- py-6 on mobile instead of py-12

CSS utilities:
- Add xs: breakpoint (375px) variants: flex, flex-row, px-4, -mx-4, gap-2, text-xs/sm, hidden

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 16:35:49 +07:00
shakespeare.diy
e8151bee17 revert: remove 3D globe, restore flat map as default
- Removed SkateGlobe component from view toggle
- ViewMode back to 'map' | 'list', defaulting to 'map'
- Removed Globe import, selectedGlobeMarker state, and all globe render blocks
- Flat Leaflet map loads as default again

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-23 16:18:24 +07:00
shakespeare.diy
6331a937f2 feat: map as homepage, 3D globe, camera fix, Sasquatch upgrades, UI/UX polish
## 1. Map as Homepage
- `/` now renders MapPage (the globe/map) — removed old Index homepage
- `/home` redirects to Index (legacy), `/map` alias still works
- Navbar: removed HOME link, SPOTS (MapPin) is now first nav item
- isActive() treats both `/` and `/map` as active for SPOTS tab

## 2. 3D Globe View
- New SkateGlobe component using pure Three.js (no h3-js/CDN issues)
- Earth night texture with atmospheric neon red glow
- Spot pins (red) + shop pins (lime) on globe surface
- Click pin → zoom camera in + show info card
- Drag to rotate, scroll/pinch to zoom, auto-rotation when idle
- Globe toggle button added to map/list view switcher
- Selected marker ring + info card with View Spot/Shop links
- Lazy-loaded with Suspense skeleton

## 3. Settings → Stash Link
- Added My Stash card in Settings > Wallet tab
- Links to /stash with Package icon and description
- Smooth hover animation with ChevronRight

## 4. Camera Fix (Capacitor Native)
- CameraCapture now detects native Capacitor platform at runtime
- On native Android/iOS: uses @capacitor/camera (OS-level camera, no WebView permission popup)
- On browser: falls back to getUserMedia stream (existing behaviour)
- Added Upload from Gallery fallback when camera permission denied
- Better error handling for user cancellation

## 5. Sasquatch Upgrades
- FAQ page: replaced static accordion wall with Sasquatch-powered UI
  - Quick question chips that pre-load questions into Sasquatch
  - "Open The Sasquatch" CTA button
  - Quick facts grid, clean modern design
- About page: added Sasquatch CTA card at bottom
- SasquatchGuide: listens for sasquatch:open and sasquatch:ask custom events
  - External pages can now trigger and pre-fill the Sasquatch
  - Sasquatch now shows even without a page-level message prop (for external triggers)

## 6. UI/UX Audit & Polish
- Focus rings: on-brand red (WCAG accessible)
- Card hover micro-interactions: subtle translateY + shadow
- Button/link transition consistency (150ms ease)
- Reduced motion support (@media prefers-reduced-motion)
- Modal backdrop blur improvement
- Skeleton shimmer animation utility
- Globe CSS utilities (touch-action: none for canvas)
- Typography helpers (text-balance, text-pretty)
- Improved map-full-height responsive calculation

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-22 22:47:39 +07:00
shakespeare.diy
dd650ee57c Show stored pubkey in Settings when profile not loaded (debug)
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-09 14:42:47 +07:00
shakespeare.diy
f73cb0ec8c Add SNT4EVER as partner on Supporters page
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-08 16:44:51 +07:00
shakespeare.diy
6ed5ac23cb Invert SNT4EVER logo for contrast on dark background
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-08 16:37:38 +07:00
shakespeare.diy
2904df4eab Update SNT4EVER logo to new version
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-08 16:35:51 +07:00
shakespeare.diy
81dd69679c Add SNT4EVER as friend on Supporters page
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-08 16:12:28 +07:00
shakespeare.diy
2c3697ba93 SupportersPage: use red transparent No Teeth logo
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-27 22:08:25 +07:00
shakespeare.diy
e03150c19f SupportersPage: remove Geyser from Friends, update No Teeth entry with white logo, Instagram link, and correct tagline
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-27 22:06:27 +07:00
shakespeare.diy
10b9d646fc SupportersPage: add No Teeth Skateboarding to Friends section with red logo
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-27 22:04:11 +07:00
shakespeare.diy
4aaa7007bf AboutPage: remove 'Learn About Nostr' card and nostr.com link
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-27 21:30:26 +07:00
shakespeare.diy
4ffa39ee95 Various UI cleanups: remove Nostr footer link, hide Map&Earn, update NostrHub links
- Index.tsx: remove Nostr.com button from homepage footer (next to FAQ/About)
- SupportersPage: change 'View on GitHub' → 'View on NostrHub' with correct naddr URL
- Layout: remove 'Map & Earn' (/bounties) from desktop More dropdown menu
- Layout: remove 'Map & Earn' (/bounties) from mobile slide-out nav
- Layout: clean up unused Gift icon import and stale isActive check

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-27 21:27:10 +07:00
shakespeare.diy
8633b38125 fix: friends CTA - only if you have the vibes
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-27 19:15:00 +07:00
shakespeare.diy
5c49946e5b fix: Geyser powered by emoji ⚡ -> 🧦
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-27 19:11:02 +07:00
shakespeare.diy
affe663291 fix: friends subtitle -> People we vibe with
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-27 18:26:52 +07:00
shakespeare.diy
80be48275e fix: update No Teeth tagline to Handmade Long Lasting Skateboards
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-27 18:02:26 +07:00
shakespeare.diy
089c6c234c feat: add No Teeth Skateboarding as first Friend, clear Partners
- Partners: removed all entries, now shows 4 placeholder slots
- Friends: added No Teeth Skateboarding with red transparent logo
  linking to instagram.com/noteethskateboarding
- Friends grid: always shows real entries + fills remaining slots to 5
  with "Coming soon" placeholders

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-27 17:57:41 +07:00
shakespeare.diy
baf4c5e10d feat: redesign /supporters with 4 sections + footer label update
- Supporters: existing Geyser leaderboard (unchanged)
- Collaborators: new section, empty placeholder with GitHub CTA
- Partners: Geyser, Angor, Zapstore, ContextVM, MKStack
- Friends: placeholder grid (5 slots) + logo spec instructions
- Footer: "Supporters" → "Collaborators & Friends"
- Static COLLABORATORS/PARTNERS/FRIENDS arrays at top of file for easy editing

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-27 17:51:11 +07:00
shakespeare.diy
5dffa5cac3 feat: UX improvements - credits, draggable sasquatch, mobile fixes
1. AboutPage: add Credits section (Zapstore, ContextVM, Angor, Geyser, MKStack,
   Shakespeare, Nostr), add Zapstore download button, fix powered-by text overflow
   on mobile (wrap-friendly flex layout)

2. SasquatchGuide: make minimized bubble draggable on all devices
   - pointer events for mouse, touch, and stylus
   - saves position to localStorage, persists across sessions
   - tap still opens, drag moves (5px threshold to distinguish)

3. Layout (burger menu): add overflow-y-auto + pb-8 to SheetContent so
   mobile menu is scrollable when content exceeds screen height

4. CashuWalletCard (wallet): fix input+button rows overflowing on mobile
   - flex-col on small screens, flex-row on xs+ (stacked on phones)
   - whitespace-nowrap on buttons to prevent text wrapping

5. LabPage: compact action buttons on mobile (h-8, text-[10px], px-2)
   so all 4 buttons fit in 2x2 grid without overflow/truncation

6. LoginDialog (Amber): improve visibility-change handler - use fresh
   SimplePool subscription on each foreground return instead of querySync
   (which doesn't exist in nostr-tools v2.13)

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-23 09:33:46 +07:00
shakespeare.diy
a677e8687d fix: Amber Capacitor APK + mobile UI improvements
Amber login (critical):
- Replace window.location.href with window.open(_system) in Capacitor WebViews
- Capacitor's WebView throws "malformed nostrsigner request" on href navigation
- New openAmberUrl() helper detects Capacitor via window.Capacitor.isNativePlatform()
- Add openAmberForLoginNoCallback() for PWA/Capacitor clipboard flow
- Fix all 6 Amber URL opens in amber.ts + LoginDialog.tsx

Mobile nav:
- Newsletter and Sasquatch AI (/pyramid) added to hamburger menu
- Sasquatch floating guide now shows on mobile (removed hidden md:block)

Lab page mobile:
- Action buttons (Offer Coaching/Filming/Editing/Get Card) now 2-col grid on mobile
- Service type filter (Coaches/Filmers/Editors) now 3-col grid, full width
- Reduced top padding on mobile (py-6 → py-12 on md+)
- Text truncates cleanly, icons don't overflow

Wallet page mobile:
- Reduced padding (py-6 md:py-8)
- Tab triggers use h-auto + py-2.5 to avoid overflow
- Smaller header text on mobile

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-18 20:48:11 +07:00
shakespeare.diy
576df73a6b fix: restore original SkateSpots logo (icon-1024.png) everywhere
Replace all icon.svg references with icon-1024.png across:
- index.html (favicon, apple-touch-icon, og:image, twitter:image)
- src/components/Layout.tsx (desktop header + mobile header)
- src/pages/Index.tsx (footer)
- public/manifest.webmanifest (PWA icon entry)

Also fix og:url and og:image/twitter:image to use correct domain
skate-spots.org instead of skate-spots.com

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-18 20:02:27 +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
shakespeare.diy
f19851da92 security: implement all 8 protection measures
## 1. sanitizeUrl() (already existed, verified applied)
- Applied to ShopDetailPage, CoachDetailPage with urlDomain() tooltip hints
- Blocks javascript:, data:, vbscript: and all non-http(s) schemes
- Returns null for invalid URLs — link simply doesn't render

## 2. Geohash validation in parsers
- Added isValidGeohash() in types.ts using ngeohash.decode()
- Min 4 chars (country-level precision rejected), max 12 chars
- Rejects lat/lng outside Earth bounds
- Rejects 0,0 "null island" — classic bot artifact
- VPN/Tor unaffected: geohash comes from map pin, not user IP

## 3. Content length limits in all parsers
- MAX_TITLE_LEN=100, MAX_DESCRIPTION_LEN=3000, MAX_LOCATION_LEN=200
- MIN_TITLE_LEN=2, MIN_GEOHASH_LEN=4
- Applied to parseSkateSpot, parseSkateShop, parseSkateCoach,
  parseSkateFilmer, parseSkateEditor, parseSkateEvent

## 4. Smart WoT default (already in codebase, verified correct)
- Logged out / <5 follows → 'all' (don't punish new/anon users)
- Logged in with ≥5 follows → 'trusted' (sort trusted first)
- Soft mode: trusted content floats to top, nothing hidden
- Active in MapPage and EventsPage

## 5. Trusted count stats in useGrowthStats
- Added trustedSpots and trustedMappers to GrowthStats type
- Heuristic: pubkeys with ≥2 published items = organic community member
- CommunityStatsPage now shows "🛡 X from active accounts" below spot count
- Purely additive — both numbers always visible

## 6. OfficialBadge component (already existed, wired up)
- Added to SpotCard, EventCard, ShopDetailPage, CoachDetailPage
- Only renders for FOUNDER_PUBKEY (20e7c953...)
- Zero-friction: invisible for all other pubkeys
- Impersonation attempts immediately visible

## 7. Leaflet marker clustering
- Installed leaflet.markercluster v1.5.3 + @types
- MarkerClusterGroup replaces direct marker.addTo(map)
- Custom cluster icon: red/orange gradient circle with count
- maxClusterRadius: 60px, spiderfyOnMaxZoom: true
- MarkerCluster CSS loaded from CDN in index.html

## 8. DM phishing warning banner
- PhishingWarningBanner component in DirectMessagesPage
- One-time dismissible (localStorage key: dm-phishing-warning-dismissed)
- Message: SkateSpots will never DM you asking for keys/payments
- Uses useLocalStorage hook, Shield icon, X dismiss button

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-18 14:03:15 +07:00
shakespeare.diy
0451887a17 feat: extended community stats page with Nostr growth data
New useGrowthStats hook:
- Queries wss://goskatespots.nostr1.com directly (authoritative source)
- Fetches all 7 content types in parallel: spots, shops, events,
  coaches, filmers, editors, tours
- Deduplicates addressable events (keep newest per pubkey+kind+d)
- Buckets events by month with gap-filling for continuous X axis
- Computes cumulative spots line chart data
- Extracts top 10 mappers by spot count
- 15 min stale time — stats don't need to be live

New useGeyserStats hook:
- Queries Geyser GraphQL for supporter count + total sats raised
- Reuses same API already used in SupportersPage

Rewritten CommunityStatsPage:
- Section 1: 8 hero stat cards (spots, shops, events, coaches,
  filmers, editors, tours, mappers) with per-type accent colours
- Section 2: 4 charts (cumulative spots area, monthly stacked bar,
  active mappers bar, content mix donut)
- Section 3: Top 10 mappers leaderboard with avatars + 🥇🥈🥉
- Section 4: Supporters banner with live Geyser count + sats raised
- Footer: data source + verifiability note
- Full skeleton loading for each section independently
- Error state for relay connectivity issues

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-18 12:54:32 +07:00
shakespeare.diy
bd3e4bee4e perf: lazy loading, faster timeouts, better caching, chunk splitting
- AppRouter: lazy load all 40+ pages (only Index is eager)
  → initial JS bundle no longer includes code for pages never visited

- MapPage: lazy load SpotMap/Leaflet (~150KB) behind Suspense
  → Leaflet only downloads when user navigates to /map

- useSkateSpots/useShops/useMarketplace/useTours:
  → timeout: 30s → 8s (fail fast, show error sooner)
  → staleTime: 30s → 5min (trust cache, fewer relay round-trips)
  → gcTime: 5min → 30min (keep data in memory longer)
  → refetchOnMount: 'always' → true (use cache when data is fresh)

- Remove console.log/warn/debug spam from production hooks

- vite.config: manual chunk splitting for leaflet, nostr-tools, bitcoin
  libs, radix-ui, react-router — each chunk cached independently
  by browser, only re-downloaded when that library updates

- vite.config: esbuild drops console.log/warn/debug in prod build

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-18 11:32:24 +07:00