Files
exposedgays/README.md

5.3 KiB

ExposedGays

100% free gay cruising map + chat + spots directory + sex shop. No subscriptions ever.

Domain: exposedgays.com

Quick Start

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

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 AnonymouslysignInAnonymously() (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 → 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

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

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)

git init
git add .
git commit -m "ExposedGays starter"
gh repo create exposedgays --private --push

Step 2 — Vercel deploy (2 min)

  1. 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