import { useState } from 'react'; import { useSeoMeta } from '@unhead/react'; import { Link } from 'react-router-dom'; import { Layout } from '@/components/Layout'; import { Card, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Progress } from '@/components/ui/progress'; import { Dialog, DialogContent } from '@/components/ui/dialog'; import { useCurrentUser } from '@/hooks/useCurrentUser'; import { useCashu } from '@/hooks/wallet/useCashu'; import { useLocalStorage } from '@/hooks/useLocalStorage'; import { LoginArea } from '@/components/auth/LoginArea'; import { WalletModal } from '@/components/WalletModal'; import { RelayEducation } from '@/components/onboarding/RelayEducation'; import { useToast } from '@/hooks/useToast'; import { cn } from '@/lib/utils'; import { CheckCircle2, Globe, DollarSign, Shield, Video, Zap, MapPin, Calendar, GraduationCap, AlertCircle, ShoppingBag, ExternalLink, Wallet, ChevronRight, Nut, BookOpen, Crown, } from 'lucide-react'; import { FounderFollow } from '@/components/FounderFollow'; // Progress tracker component function OnboardingProgress({ currentStep, totalSteps, completedSteps }: { currentStep: number; totalSteps: number; completedSteps: number[]; }) { const progressPercent = (completedSteps.length / totalSteps) * 100; return (
Your Progress {completedSteps.length} of {totalSteps} complete
{[1, 2, 3, 4].map((step) => (
{completedSteps.includes(step) ? : step}
{step === 1 && "Login"} {step === 2 && "Explore"} {step === 3 && "Wallet"} {step === 4 && "Go Skate"}
))}
); } export default function OnboardingPage() { useSeoMeta({ title: 'Get Started - SkateSpots', description: 'Learn how to use SkateSpots and join the skateboarding community on Nostr.', }); const { user } = useCurrentUser(); const { isInitialized: hasCashu, totalBalance: cashuBalance } = useCashu(); const { toast } = useToast(); const [showRelayEducation, setShowRelayEducation] = useState(false); const [hasSeenRelayEducation, setHasSeenRelayEducation] = useLocalStorage('seen-relay-education', false); const handleRelayEducationComplete = () => { setShowRelayEducation(false); setHasSeenRelayEducation(true); toast({ title: '🎉 Nice!', description: 'You now understand how Nostr works. Let\'s go skate!', }); }; const copyNpub = () => { navigator.clipboard.writeText('npub1yrnuj56rnen08zp2h9h7p74ghgjx6ma39spmpj6w9hzxywutevsst7k5cx'); toast({ title: 'Copied!', description: 'npub copied to clipboard. Paste it in your favorite Nostr client to send a DM.', }); }; // Bug report template for DM const bugReportTemplate = `🐛 Bug Report What happened: What I expected: Steps to reproduce: Device/Browser: ${navigator.userAgent.includes('Mobile') ? 'Mobile' : 'Desktop'} - ${navigator.userAgent.split(' ').slice(-2).join(' ')} Version: v0.1.0`; const bugReportUrl = `/messages/npub1yrnuj56rnen08zp2h9h7p74ghgjx6ma39spmpj6w9hzxywutevsst7k5cx?message=${encodeURIComponent(bugReportTemplate)}`; // Calculate completed steps const completedSteps: number[] = []; if (user) completedSteps.push(1); if (user) completedSteps.push(2); // Exploration is available once logged in if (hasCashu || (user && cashuBalance > 0)) completedSteps.push(3); // Wallet setup // Step 4 is always the final action step const currentStep = user ? (hasCashu ? 4 : 3) : 1; return (
{/* Hero Section with Progress */}

GET ROLLING

Connect with your local scene. Share spots. Find sessions. It's that simple.

{/* Progress Tracker */} {/* Login/Signup Section - Step 1 */} {!user ? ( {/* Step indicator */}
1

CREATE YOUR ACCOUNT

Log in with your Nostr account or create a new one. Your identity works across all Nostr apps - no company controls it.

) : (

Step 1 Complete!

You're logged in and ready to explore.

{/* Founder Follow - hold for 3s */}
)}
{/* Quick Info Banner with Learn More */}
⚡

SkateSpots uses Nostr - a decentralized protocol where YOU own your data. No company can delete your spots or ban your account.

{/* Step 2: Explore - What You Can Do */}
2

EXPLORE THE COMMUNITY

Everything is free! Browse spots, find coaches, join events - no Bitcoin required.

{[ { icon: MapPin, label: "Spots & Shops", desc: "Find skate spots worldwide", href: "/map", color: "red" }, { icon: GraduationCap, label: "The Lab", desc: "Connect with coaches & filmers", href: "/lab", color: "orange" }, { icon: Calendar, label: "Events", desc: "Join sessions & competitions", href: "/events", color: "lime" }, ].map((item) => (

{item.label}

{item.desc}

))}
{user && (
)}
{/* Step 3: Wallet Setup */}
3

OPTIONAL: SET UP WALLET

Optional

Want to tip skaters who share awesome spots? Set up a wallet to send zaps (Bitcoin tips). Totally optional!

{/* Cashu Wallet - Built-in */}

Cashu Wallet

Built into SkateSpots

No setup needed! Receive Lightning payments directly in the app.

{hasCashu && cashuBalance > 0 ? (
Balance: {cashuBalance.toLocaleString()} sats
) : ( )}
{/* External Wallet - NWC */}

External Wallet

Connect via NWC

Already have a Lightning wallet? Connect it with Nostr Wallet Connect.

{user ? ( ) : ( )}

💡 Tip: $5 in Bitcoin = hundreds of zaps to share with the community

{/* Step 4: Go Skate! */}
4

GO SKATE! 🛹

Real skateboarding happens offline. Use SkateSpots to discover spots, then get out there and shred!

{user ? (
) : (

Complete the steps above to get started

)}
{/* 100% Free Banner */}

100% FREE TO USE

You don't need any Bitcoin to use SkateSpots. Browse spots, add locations, connect with pros, join events - all free. Zaps are completely optional for those who want to support creators.

{/* Why Nostr - Compact Version */}

WHY NOSTR FOR SKATERS?

YOUR SPOTS ARE PERMANENT

No company can delete the spots you share. Your contributions live on multiple servers.

DIRECT TIPS TO CREATORS

Zap skaters directly - no platform taking 30%. Money goes straight to them.

OWN YOUR IDENTITY

Your Nostr profile works everywhere. Build your rep once, take it to any app.

Show real appreciation with real value - not just likes that mean nothing.

{/* Common Questions */}

COMMON QUESTIONS

{[ { q: 'DO I NEED BITCOIN TO USE THIS APP?', a: 'No! SkateSpots is 100% free. You can browse spots, add locations, find pros at The Lab, create events, and connect with the community without any Bitcoin. Zaps are optional for those who want to tip creators.' }, { q: 'WHAT\'S AN NSEC AND WHY IS IT IMPORTANT?', a: 'Your nsec (secret key) is like a password that proves you own your account. Unlike regular passwords, there\'s no "forgot password" option. If you lose it, you lose your account forever. That\'s why you download a backup when you sign up.' }, { q: 'IS THIS FREE?', a: 'Yes! Creating a Nostr account and using SkateSpots is 100% free. You only need Bitcoin if you want to send zaps (tips), and even then you can receive zaps without having any Bitcoin yourself.' }, { q: 'WHY CAN\'T I RESET MY PASSWORD?', a: 'Nostr doesn\'t have passwords - it has cryptographic keys. This means no company (including us) can access your account, but it also means no one can reset it for you. Your nsec IS your account. Keep it safe!' }, { q: 'CAN I USE THIS ON MY PHONE?', a: 'Yes! SkateSpots works on any device with a web browser. On mobile, you can add it to your home screen for an app-like experience. Just visit the site and use the "Add to Home Screen" option in your browser menu.' } ].map((faq, i) => (

{faq.q}

{faq.a}

))}
{/* CTA */}

READY TO SHRED?

Start exploring spots, connecting with skaters, and building the community.

{/* Beta Testing Notice */}

Beta Testing

Thanks for testing SkateSpots! This app is under active development – you may encounter bugs or security issues. Your feedback helps us improve.

Report bugs or share feedback:

npub1yrnuj56rnen08zp2h9h7p74ghgjx6ma39spmpj6w9hzxywutevsst7k5cx
{user ? ( ) : ( )}
{/* Relay Education Dialog */} setShowRelayEducation(false)} />
); }