1. Near Me "location blocked" on the APK:
- navigator.geolocation returns PERMISSION_DENIED inside the Android WebView
because the WebView never gets the OS location permission, so the app
showed a bogus "your browser blocked location" help sheet.
- New src/lib/geolocation.ts: platform-aware getCurrentPosition(). On native
it uses Capacitor's Geolocation plugin via registerPlugin('Geolocation')
from bundled @capacitor/core (same runtime pattern as the camera/Amber
fixes) and calls requestPermissions() to trigger the real Android prompt;
on web it falls back to navigator.geolocation.
- MapPage handleNearMe, proximity sort, and quick-snap location now use it.
On native, a denied permission shows an OS-permission toast instead of the
browser help sheet.
- Added @capacitor/geolocation dependency (native side picked up via cap sync;
no bare import in the JS bundle).
2. Desktop map didn't fit the viewport (had to scroll to see footer):
- Map wrapper was md:h-[calc(100vh-4rem)] — full height minus header only,
leaving no room for the footer.
- Added --footer-desktop token (5rem) and changed the desktop height to
calc(100vh-4rem-var(--footer-desktop)) so map + footer fit without scroll.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
|
||
|---|---|---|
| .agents/skills | ||
| .github | ||
| .nsite | ||
| .vscode | ||
| cvm-server | ||
| eslint-rules | ||
| public | ||
| skills | ||
| src | ||
| .gitignore | ||
| .gitlab-ci.yml | ||
| .mcp.json | ||
| AGENTS.md | ||
| BOUNTY-SYSTEM-PLAN.md | ||
| BUDGET_IMPLEMENTATION.md | ||
| capacitor.config.ts | ||
| components.json | ||
| CONTEXTVM_INTEGRATION.md | ||
| DEPLOYMENT_COMPARISON.md | ||
| EMERGENCY_FIX.md | ||
| eslint.config.js | ||
| FINAL_POLISH_BREAKDOWN.md | ||
| FINAL_SCOPE.md | ||
| FIXES_BREAKDOWN.md | ||
| FOLLOW_MANAGEMENT_BRIEFING.md | ||
| HOW_TO_ENABLE_RELATR.md | ||
| IMPLEMENTATION_COMPLETE.md | ||
| IMPLEMENTATION_PLAN.md | ||
| index.html | ||
| INTEGRATION_BRIEFING.md | ||
| LIVE_MUSIC_PROPOSAL.md | ||
| LOGO_USAGE.md | ||
| MCP_SERVER_SPEC.md | ||
| netlify.toml | ||
| NIP-06-IMPLEMENTATION.md | ||
| NIP.md | ||
| NOGOOD_RADIO_PROPOSAL.md | ||
| opencode.json | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.js | ||
| RADIO_PLAYER_GUIDE.md | ||
| README.md | ||
| RELATR_INTEGRATION.md | ||
| RELAY_FIX.md | ||
| RELAY_SETUP.md | ||
| release-notes.txt | ||
| SHOP_VERIFICATION_ANALYSIS.md | ||
| stack.json | ||
| tailwind.config.ts | ||
| tsconfig.json | ||
| vite.config.ts | ||
| WEATHER_FEATURE.md | ||
| ZAP_INTEGRATION_PROPOSAL.md | ||
| ZAP_QUICK_WINS.md | ||
| ZAP_SIMPLE_PLAN.md | ||
| ZAPSTORE.md | ||
| zapstore.yaml | ||
SkateSpots - Decentralized Skate Map & Community
A decentralized skateboarding community platform built on Nostr. Discover skate spots, find coaches, join events, and connect with skaters worldwide.
🌐 Live App
- Deployed URL: https://skate-spots.org
- Nostr Git: nostr://npub1yrnuj56rnen08zp2h9h7p74ghgjx6ma39spmpj6w9hzxywutevsst7k5cx/git.shakespeare.diy/SkateSpots
✨ Features
- 🗺️ Interactive Skate Map - Discover skate spots worldwide with geolocation
- 🛹 Spot Database - Browse, create, and review skate parks and street spots
- 📅 Events Calendar - Find and create skateboarding events and competitions
- 👨🏫 The Lab - Connect with coaches, filmers, and video editors in your area
- 🎬 Video Editors - Find editors who list their software, hardware, and portfolio
- 🛍️ Skate Shops - Discover local skate shops and support the community
- 🔄 Buy/Sell Gear - Marketplace for used skate gear (NIP-99 classified listings)
- 🎒 My Stash - Private encrypted gear inventory with location tracking
- 🎵 NoGood Radio - 24/7 vibing music (lofi, synthwave, electronica)
- ⚡ Lightning Zaps - Send Bitcoin tips to content creators
- 🌤️ Weather Integration - Check conditions before you skate
- 🔐 Nostr Authentication - Decentralized login with your Nostr keys
- 📱 PWA Support - Install as a native app on any device
- ❤️ Supporters - Community funding via Geyser (Bitcoin Lightning)
🛠️ Technology Stack
- React 18 - Modern UI with hooks and concurrent rendering
- Nostr Protocol - Decentralized data storage and communication
- TailwindCSS 3 - Utility-first CSS framework
- Vite - Lightning-fast build tool and dev server
- shadcn/ui - Beautiful, accessible UI components
- Nostrify - Nostr framework for web applications
- TanStack Query - Data fetching and caching
- OpenStreetMap - Interactive maps
- TypeScript - Type-safe development
🚀 Getting Started
Prerequisites
- Node.js 18+
- npm or yarn
Installation
# Clone the repository
git clone nostr://npub1yrnuj56rnen08zp2h9h7p74ghgjx6ma39spmpj6w9hzxywutevsst7k5cx/git.shakespeare.diy/SkateSpots
# Install dependencies
npm install
# Start development server
npm run dev
Building
# Build for production
npm run build
# Run tests
npm test
🌍 Deployment
The app is configured for deployment via:
- Shakespeare Deploy - Nostr-native deployment (configured)
- Netlify - Static site hosting
- Vercel - Edge deployment
- nsite - Nostr-native sites
Deploy command:
npm run deploy
📱 PWA Installation
SkateSpots works as a Progressive Web App (PWA) and can be installed on:
- Desktop: Chrome, Edge, Safari - Look for install icon in address bar
- Android: Chrome - "Add to Home Screen" from menu
- iOS: Safari - "Add to Home Screen" from share menu
🔌 Nostr Integration
Custom Event Kinds
This app uses custom Nostr event kinds defined in NIP.md:
| Kind | Type | Description |
|---|---|---|
| 30017 | Addressable | Skate Shops (NIP-15 Stall) |
| 30402 | Addressable | Gear Listings (NIP-99 Classified) |
| 30818 | Addressable | Skate Spots |
| 30823 | Addressable | Skate Tours |
| 31923 | Addressable | Skate Events (NIP-52 Calendar) |
| 35001 | Addressable | Skate Coaches |
| 35002 | Addressable | Skate Filmers / Photographers |
| 35003 | Addressable | Skate Video Editors |
Relay Configuration
Default relay: wss://goskatespots.nostr1.com
Users can manage relays in Settings following NIP-65.
🎒 My Stash
The Stash is a private, encrypted gear inventory (NIP-51 kind 30001). Users can track their equipment with:
- Categories: Decks, trucks, wheels, bearings, shoes, apparel, protective gear, and more
- Storage locations: Home, car, backpack, wardrobe, van, skatepark, friend's, parents', warehouse, storage unit, sponsor, or other
- Condition rating (1–5 stars), rarity tier, and optional price
- Visibility control: Private (encrypted), friends-only, or public
- Filter & search by category, storage location, or keyword
🧪 The Lab
The Lab connects skaters with service providers in three categories:
- Coaches - Skateboarding instructors with skill specializations
- Filmers - Videographers and photographers with equipment/style details
- Video Editors - Editors who list their software (Premiere, DaVinci, After Effects, etc.), hardware setup, portfolio, and contact details
📦 Dependencies Overview
Core Dependencies
@nostrify/nostrify- Nostr protocol implementation@nostrify/react- React integration for Nostrreact&react-dom- UI frameworkreact-router-dom- Client-side routing@tanstack/react-query- Data fetching and statenostr-tools- Nostr utilities and cryptography
UI & Styling
tailwindcss- Utility-first CSS@radix-ui/*- Accessible UI primitiveslucide-react- Icon libraryclass-variance-authority- Component variantstailwind-merge- Class name merging
Maps & Location
- OpenStreetMap - Interactive maps
ngeohash- Geohash encoding/decoding
Bitcoin & Lightning
@getalby/sdk- Alby wallet integration@cashu/cashu-ts- Cashu ecash protocolnpubcash-sdk- npub.cash integrationbitcoinjs-lib- Bitcoin utilities@noble/curves&@noble/hashes- Cryptography
Media & Streaming
hls.js- HLS streaming supportqrcode- QR code generationhtml5-qrcode- QR code scanning
Utilities
date-fns- Date formattingzod- Schema validationreact-hook-form- Form handlingbuffer- Node.js buffer polyfillidb&dexie- IndexedDB wrappers
🏗️ Project Structure
/src
├── components/ # React components
│ ├── ui/ # shadcn/ui components (48+)
│ ├── auth/ # Authentication components
│ └── ... # Feature components
├── hooks/ # Custom React hooks
├── pages/ # Route pages
├── lib/ # Utilities and helpers
├── contexts/ # React context providers
└── test/ # Testing utilities
/public
├── images/ # Static images and icons
├── manifest.webmanifest
└── robots.txt
/skills # Implementation guides for features
🧪 Testing
# Run all tests (TypeScript, ESLint, Vitest, Build)
npm test
# Type checking only
npx tsc --noEmit
# Linting only
npx eslint
🤝 Contributing
This is a Nostr-based open source project. Contributions are welcome!
- Fork/clone the repository via Shakespeare or git
- Create your feature branch
- Make your changes
- Run tests (
npm test) - Commit your changes
- Push and create a pull request
📄 License
YOU ARE FREE TO SKATEBOARD
This project is open. Share it, fork it, build on it, skate it. The streets belong to everyone. So does this code. Just keep skating and don't be a kook.
Copyright © 2025–∞ SkateSpots contributors & the community
See /license in the app for the full license page.
❤️ Support the Project
SkateSpots is 100% free, open-source, and community-funded. No ads, no data selling, no investors.
- Geyser: https://geyser.fund/project/skatespots
- Supporters page: https://skate-spots.org/supporters
🙏 Credits
- Built with: MKStack - Nostr client framework
- Vibed with: Shakespeare - AI-powered development
- Powered by: Nostr - Decentralized protocol
- Funded by: Geyser - Bitcoin Lightning crowdfunding
🔗 Links
📞 Support
For issues or questions:
- Open an issue on the repository
- Contact via Nostr: npub1yrnuj56rnen08zp2h9h7p74ghgjx6ma39spmpj6w9hzxywutevsst7k5cx
Made with ❤️ for the skateboarding community