# ExposedGays 100% free gay cruising map + chat + spots directory + sex shop. No subscriptions ever. **Domain:** exposedgays.com ## Quick Start ```bash npm install cp .env.example .env.local # Edit .env.local with your Supabase keys (optional for local demo — mock data works offline) npm run dev ``` Open [http://localhost:3000](http://localhost:3000) ## Features | Feature | Status | |---------|--------| | Real-time cruising map (Leaflet + OSM) | ✅ Mock data + Supabase-ready | | User clustering + position badges | ✅ | | Map filters (age, position, kinks, PrEP) | ✅ | | Cruiser Cards + Profile popup | ✅ | | Instant chat + city chat + DMs + groups | ✅ Mock + Supabase schema | | Cruising spot directory | ✅ | | **Shop** (affiliate links, local cart) | ✅ | | Age verification gate (Florida-compliant) | ✅ | | Vanilla mode blur toggle | ✅ | | Dark mode, mobile-first, PWA manifest | ✅ | | Anonymous browsing + optional profile | ✅ | ## Tech Stack - **Next.js 15** App Router + TypeScript - **Tailwind CSS** + shadcn/ui components - **React-Leaflet** + OpenStreetMap tiles - **Supabase** — Auth, Postgres + PostGIS, Realtime, Storage - **Zustand** — localStorage cart ## Project Structure ``` exposedgays/ ├── public/ │ └── manifest.json # PWA manifest ├── src/ │ ├── app/ │ │ ├── layout.tsx # Root layout + nav │ │ ├── page.tsx # Map (home) │ │ ├── shop/page.tsx # Sex shop │ │ ├── chat/page.tsx # City chat + DMs │ │ ├── spots/page.tsx # Spot directory │ │ └── profile/page.tsx # User profile editor │ ├── components/ │ │ ├── AgeGate.tsx # 18+ DOB verification │ │ ├── Map.tsx # Interactive cruising map │ │ ├── Shop.tsx # Product grid + cart │ │ ├── Nav.tsx # Top/bottom nav with Shop link │ │ ├── ChatPanel.tsx # Real-time chat UI │ │ ├── CruiserCard.tsx # Squirt-style cruiser cards │ │ ├── ProfilePopup.tsx # Tap icon → profile modal │ │ ├── SpotDirectory.tsx # Spot listings + search │ │ └── ui/ # shadcn components │ ├── lib/ │ │ ├── products.ts # Dummy shop inventory │ │ ├── cart.ts # Zustand localStorage cart │ │ ├── mock-data.ts # Demo cruisers + spots │ │ └── supabase/ # Supabase client helpers │ └── types/index.ts ├── supabase/ │ └── schema.sql # Full Postgres + PostGIS + RLS ├── .env.example └── package.json ``` ## Auth (Supabase) Auth is wired via `src/lib/auth/context.tsx` + `AuthModal.tsx`: - **Join Free** in nav → email/password signup or login - **Continue Anonymously** → `signInAnonymously()` (enable in Supabase Dashboard → Auth → Providers → Anonymous) - Profile page syncs to `profiles` table when signed in Enable on https://supabase.onsethost.com → Authentication → Providers: - Email (confirm email optional for dev) - Anonymous sign-ins ## Supabase Setup ### 1. Create project Go to [supabase.com](https://supabase.com) → New Project (free tier). ### 2. Run schema SQL Editor → paste contents of `supabase/schema.sql` → Run. ### 3. Enable Realtime Dashboard → Database → Replication → enable `chat_messages` and `profiles`. ### 4. Create Storage bucket ```sql INSERT INTO storage.buckets (id, name, public) VALUES ('gallery', 'gallery', true); INSERT INTO storage.buckets (id, name, public) VALUES ('shop', 'shop', true); ``` ### 5. Copy keys to `.env.local` ``` NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ... SUPABASE_SERVICE_ROLE_KEY=eyJ... ``` ### CLI alternative ```bash npx supabase init npx supabase link --project-ref YOUR_PROJECT_REF npx supabase db push ``` ## 5-Minute Deployment (Vercel + Supabase + DNS) ### Step 1 — Push to GitHub (1 min) ```bash git init git add . git commit -m "ExposedGays starter" gh repo create exposedgays --private --push ``` ### Step 2 — Vercel deploy (2 min) 1. [vercel.com](https://vercel.com) → Import Git repo 2. Framework: **Next.js** (auto-detected) 3. Add environment variables from `.env.example` 4. Deploy → get `exposedgays.vercel.app` ### Step 3 — Custom domain (1 min) 1. Vercel → Project → Settings → Domains → Add `exposedgays.com` + `www.exposedgays.com` 2. Vercel shows required DNS records ### Step 4 — DNS at registrar (1 min) | Type | Name | Value | |------|------|-------| | A | @ | `76.76.21.21` | | CNAME | www | `cname.vercel-dns.com` | (Or use Cloudflare CNAME flattening if proxied.) ### Step 5 — Verify - Visit `https://exposedgays.com` — age gate appears - Map loads with cruiser icons - Shop nav works with affiliate buttons - PWA installable on mobile ## Shop Affiliate Notes - Cart is **localStorage only** — no checkout on-site - "Buy Now" opens affiliate URLs in new tab (`rel="sponsored"`) - Replace placeholder URLs with real Amazon Associates / AdamMale affiliate links - Products defined in `src/lib/products.ts` (static) or `shop_products` table (DB) ## License Private — exposedgays.com © 2026