- infrastructure-gap-assessment: full audit doc - project-log: recent completions - hotnow, hotnow-phase1, ops-portal-runcloud-design-brief, schoolcart PTA docs - intelsight and schoolcart updates
45 KiB
HotNow.io — Phase 1: Architecture + Competitive Intel
Phase 1 of 4 — $50 Premium Build Date: August 2, 2026 Status: ✅ Complete — Awaiting Germaine Review
Table of Contents
- Competitive Landscape
- Opportunity Analysis & HotNow's Edge
- Product Architecture
- Data Model
- API Surface
- Real-Time Ranking Algorithm
- Component Tree & PWA Shell
- Infrastructure & Deployment
- Build Plan Preview (Phases 2-4)
- Follow-Up Questions for Germaine
1. Competitive Landscape
Market Segmentation
The local discovery space is fragmented across four segments — nobody owns all of them:
| Segment | What It Covers | Key Players |
|---|---|---|
| Restaurant/Business Discovery | Finding places to eat, drink, shop | Yelp, Google Maps, Beli, Corner, TripAdvisor |
| Event/Ticketing Platforms | Buying tickets, browsing events | Eventbrite, DICE/Fever, Songkick, Bandsintown |
| Neighborhood Social | Hyperlocal community chatter | Nextdoor, Facebook Groups, Ring Neighbors |
| Curated Experiences | Immersive, premium, one-off events | Fever (Candlelight), Secret Cinema, Airbnb Experiences |
Competitor Deep Dives
2. Yelp — The Incumbent Giant
- What it is: 20-year-old local business discovery platform. 21-22M reviews/year. Massive community-generated content moat.
- What's new (2025 Fall Release): Massive AI push — Yelp Assistant (AI chatbot on every business page), Menu Vision (AR menu scanning), natural language/voice search, Popular Offerings (LLM-extracted crowd favorites), Yelp Host/Receptionist (AI call answering for businesses). Partnered with DoorDash for delivery.
- Pricing: Free for consumers. Business advertising: $150-$5,000+/mo. Yelp Host: $99/mo.
- UX Pattern: List-first with map secondary. Search-driven discovery.
- Weaknesses:
- Not real-time — Yelp ranks on accumulated review history, not "what's hot right now"
- Weak on events — events are an afterthought, not core UX
- Gen Z exodus — Beli and Corner are eating its lunch with younger demographics
- No social buzz integration — no TikTok/Instagram trend signals
- 🔴 HotNow opportunity: Real-time trending that Yelp's batch-oriented ranking can't match. Social buzz as a ranking signal. Event-first UX.
3. Fever — The Experience Curator
- What it is: Global ticketing platform for curated experiences. 30+ cities worldwide. Known for Candlelight Concerts, immersive Van Gogh exhibits, themed pop-ups.
- Big news: Acquired DICE in 2025 — combined entity now dominates curated event ticketing
- Pricing: Free to browse. Fever takes a commission on ticket sales (service fees added). No consumer subscription.
- UX Pattern: Feed-first (curated hero cards). List + grid browse. Map only for venue lookup.
- Weaknesses:
- Curated, not comprehensive — Fever only shows its own catalog (events they ticket)
- Not real-time — no trending algorithm, fixed listings
- Not local-discovery — it's a ticketing platform, not a "what's happening around me" tool
- B2C curation model — doesn't surface grassroots/pop-up/unlisted happenings
- 🔴 HotNow opportunity: Comprehensive vs. curated. Real-time vs. scheduled. Discovery vs. ticketing.
4. DICE — Transparent Ticketing
- What it is: Music-first ticketing platform with transparent pricing (no hidden fees). Strong in UK/Europe, expanding in US. Acquired by Fever.
- Pricing: No consumer fees — built into ticket price. Artist/venue revenue share.
- UX Pattern: Feed-first with personalized recommendations based on listening history (Spotify/Apple Music integration).
- Weaknesses:
- Music-only — no restaurant/bar/pop-up discovery
- Ticketing-centric — useless if you just want to know what's happening without buying a ticket
- Post-acquisition uncertainty — Fever integration may shift focus
- 🔴 HotNow opportunity: Cross-category discovery (not just music). Free-form exploration without ticket purchase obligation.
5. Eventbrite — The Event Marketplace
- What it is: Largest self-service event platform. 5M+ events/year. 2025 rebrand from utility to "cultural hub."
- New initiatives: AI personalization, Listener.com partnership for audience reach, AI-powered event recommendations.
- Pricing: Free to browse. Organizers pay: free tier (up to 25 tickets), then 2% + $0.79 per paid ticket, or subscription plans.
- UX Pattern: Search-first with category browse. List results. Map secondary.
- Weaknesses:
- Quantity over quality — lots of spam, online webinars, low-quality listings
- No real-time signal — static listings sorted by date/relevance
- Brand perception: "event Craigslist" — utilitarian, not aspirational
- Not Gen Z cool — zero social features
- 🔴 HotNow opportunity: Quality-filtered, social-buzz ranked. Cool brand. Map-first UX.
6. Nextdoor — Neighborhood Social
- What it is: Hyperlocal social network for neighborhoods. 15 years old. User-generated content: recommendations, alerts, events.
- 2025 redesign: AI-powered "Faves" for local business discovery, real-time emergency alerts (weather/traffic/power), local news from 3,500+ publisher partners, LLM per neighborhood trained on 15 years of conversations.
- Pricing: Free. Ad-supported + promoted business posts.
- UX Pattern: Feed-first (social). Map for alerts. List for businesses.
- Weaknesses:
- Brand damage — associated with racism, misinformation, "Karen" culture
- Demographic skew — older homeowners, not Gen Z/Millennials going out
- Events are buried — not a discovery tool, it's a neighborhood bulletin board
- Reactive, not proactive — "lost cat" dominates over "cool thing happening"
- 🔴 HotNow opportunity: Aspirational, cool brand. Discovery-first. Young demographic. No neighborhood baggage.
7. Beli — Gen Z Restaurant Ranking
- What it is: Restaurant ranking + social app. Goodreads/Letterboxd for food. 80% of users under 35. 30M reviews in 2024 (surpassing Yelp's 21M).
- How it works: Log restaurants, compare them head-to-head (pairwise ranking algorithm assigns scores /10), follow friends, browse feeds. No star ratings.
- Growth engine: College campus ambassador program. Leaderboards by school. Dating app integration (sharing rankings to vet dates). TikTok/Instagram virality.
- Pricing: Free (currently). No ads. No monetization yet.
- UX Pattern: Feed-first (social). Profile-centric. No map.
- Weaknesses:
- Restaurant-only — no events, bars (as venues), pop-ups, activities
- Past-tense — about where you've been, not what's happening right now
- No map — poor for real-time exploration
- No monetization path yet — unclear business model
- 🔴 HotNow opportunity: Real-time + events + map. Broader than restaurants. Clear revenue model from day one.
8. Corner — Gen Z Social Map
- What it is: Map-first social app for Gen Z. User-curated map of places (restaurants, bars, shops, sunset spots). No star ratings. Mood-board style lists. $3.75M raised.
- Key features: AI semantic search ("sexy wine bar" → results), Instagram/TikTok bookmark import, user-generated descriptions (Gen Z voice: "performative male wine bar to break someone's heart"), Mapbox-powered.
- Stats: 55,000 users, 275,000+ places, 450 cities. Hubs: NYC, SF, Tokyo, LA, Seoul.
- Pricing: Free. Considering premium trip-planning tier. No sponsored placements (stated philosophy).
- UX Pattern: Map-first. Feed of friend activity. Profile + lists.
- Weaknesses:
- Tiny scale — 55K users vs. Yelp's millions
- User-generated only — no data if nobody has added a place yet
- No events — purely place discovery (static)
- Gen Z monoculture — alienates 30+ demographic
- No monetization — pre-revenue, burning VC
- 🔴 HotNow opportunity: Events + real-time + broader demographic. Data-rich from day one (Super Search v2). Revenue from launch.
9. Google Maps — The 800-Pound Gorilla
- What it is: Default map for 1B+ users. 20 years old. "Explore" tab surfaces nearby restaurants, attractions, activities.
- Recent AI: Gemini-powered conversational search, AR Live View, "Popular Times" (historical foot traffic data), AI-summarized place descriptions.
- Pricing: Free for consumers. Google Ads for businesses.
- UX Pattern: Map-first. Everything is on the map. Unbeatable directions + navigation.
- Weaknesses:
- Not events-first — events are buried, inconsistent, often missing
- Static data — "Popular Times" is historical, not real-time
- No social — no friend activity, no trending rankings
- Generic UX — one-size-fits-all, no personality
- 🔴 HotNow opportunity: Events-first UX. Real-time trending. Social layer. Brand personality.
10. Songkick / Bandsintown — Live Music Trackers
- What it is: Track artists you follow → get notified when they're playing near you. Songkick acquired by Suno (AI music company). Bandsintown is independent.
- Pricing: Free for fans. Bandsintown: artist promo packages ($25-$100+/mo).
- UX Pattern: List-first (concerts by date). Artist-centric.
- Weaknesses:
- Music-only — no other event categories
- Artist-dependent — you must follow artists to get value
- No real-time trending — chronological, not ranked by buzz
- 🔴 HotNow opportunity: All categories. Buzz-ranked. No following required — discover without pre-configuring.
11. Resident Advisor (RA) — Electronic Music Authority
- What it is: The definitive electronic music events platform. Global listings, reviews, news, ticket sales.
- Pricing: Free to browse. Ticket commission + promoted event listings.
- UX Pattern: List-first. Deep filtering by genre/city/date.
- Weaknesses:
- Niche (electronic music only) — tiny addressable market
- Community-specific — not for general audience
- 🔴 HotNow opportunity: Mass-market appeal. All genres + all categories.
12. Seeker.io — B2B AI Event Aggregation
- What it is: AI-native event discovery for tourism boards, CVBs, local media. Crawls any website to extract events. Used by SF Peninsula (500+ sources, 16 cities), Tennessee Tourism (statewide), Calgary Co-op (4 orgs, 1 feed).
- Pricing: Enterprise B2B SaaS (not publicly listed — likely $500-$5K+/mo depending on scale).
- UX Pattern: Embeddable calendar widget for partner websites. REST API for custom integrations.
- Weaknesses:
- B2B, not consumer-facing — no social, no map UX, no mobile app
- No real-time trending — chronological curation
- Expensive — not for small businesses
- 🔴 HotNow opportunity: Consumer experience. Real-time social ranking. Affordable business tiers.
2. Opportunity Analysis & HotNow's Edge
The White Space
After analyzing 12 competitors, nobody is doing all of these together:
| Capability | Yelp | Fever/DICE | Eventbrite | Nextdoor | Beli | Corner | Google Maps | HotNow |
|---|---|---|---|---|---|---|---|---|
| Real-time trending | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
| Social buzz signals | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
| Map-first UX | 🔶 | ❌ | ❌ | 🔶 | ❌ | ✅ | ✅ | ✅ |
| Events + Places | ❌ | 🔶 | ✅ | 🔶 | ❌ | ❌ | 🔶 | ✅ |
| AI ranking | 🔶 | ❌ | 🔶 | ✅ | ✅ | ✅ | 🔶 | ✅ |
| Gen Z cool factor | ❌ | 🔶 | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ |
| Business monetization | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ |
| Offline mode (PWA) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
| PWA (no app store) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
🔶 = partially / second-class feature
HotNow's Core Differentiators
-
Real-Time Trending Ranking — The single biggest gap. Everyone ranks by reviews, dates, or manual curation. HotNow ranks by what's buzzing right now — social signals, check-in velocity, search volume, AI sentiment.
-
Super Search v2 Integration — Already live on Core server with 7 providers. This is HotNow's data engine — aggregates events, venues, reviews, and social signals from multiple sources without needing to build every scraper from scratch.
-
Map-First PWA — No app store friction. Instant onboarding. Works offline. Lower CAC than native app competitors.
-
Three-Tier Consumer Monetization — Explorer (free), Pro ($4.99/mo), Concierge ($19.99/mo). Competitors are either free/ad-supported or ticket-commission-only. Recurring subscription revenue from day one.
-
Business Revenue from Launch — Featured Placement ($97/mo) + Event Boost ($47/event). Affordable for small businesses (unlike Yelp's $500+ minimums).
-
Brand Identity — Dark theme, warm gradient accent. "What's good, right now, near you." Gen Z/Millennial voice without alienating 30+.
3. Product Architecture
System Overview
┌─────────────────────────────────────────────────────────────────┐
│ USERS (PWA) │
│ app.hotnow.io ─── Map View ─── Discovery Feed ─── etc. │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ CLOUDFLARE CDN │
│ Static assets (JS/CSS/icons) │ API proxy │ DDoS protection │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ CADDY REVERSE PROXY │
│ SSL termination │ Rate limiting │ Route by subdomain │
└─────────────────────────────────────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ app.hotnow.io │ │ api.hotnow.io │ │ dashboard.hotnow │
│ (Static PWA) │ │ (FastAPI) │ │ (Business Dash) │
│ SvelteKit SPA │ │ Port 8001 │ │ Static + API │
└──────────────────┘ └──────────────────┘ └──────────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
│ PostgreSQL │ │ Redis │ │ Super Search v2 │
│ + PostGIS │ │ Cache + Queue│ │ (7 providers) │
│ │ │ + Real-time │ │ Existing on Core │
└──────────────┘ └──────────────┘ └──────────────────┘
Tech Stack
| Layer | Technology | Why |
|---|---|---|
| PWA Frontend | SvelteKit (static adapter) | Fast, small bundles, great PWA support |
| Map | Leaflet.js + OpenStreetMap tiles | Free, no API keys, works offline with cached tiles |
| Backend API | FastAPI (Python 3.11) | Async, auto-docs, Python matches existing Core stack |
| Database | PostgreSQL 16 + PostGIS | Geospatial queries (proximity, radius, bounding box) |
| Cache | Redis | Trending scores, session cache, rate limit counters, real-time pub/sub |
| Task Queue | Redis + ARQ (or Celery) | Background: Super Search ingestion, trend recalculation, notifications |
| Auth | JWT tokens + refresh | Stateless, PWA-friendly, no cookies needed |
| Payments | Stripe | Consumer subs + business placements, Webhook integration |
| Search | PostgreSQL full-text search + Super Search v2 | Hybrid: own DB for quick lookups, Super Search for deep aggregation |
| Offline | Service Worker + IndexedDB | Cache map tiles, event data, user preferences |
| Push Notifications | Web Push API + VAPID | PWA native, no app store needed |
| Postmark or SendGrid | Transactional + marketing |
Subdomain Architecture
| Subdomain | Purpose | Technology |
|---|---|---|
hotnow.io |
Marketing/SEO landing page | Static HTML (existing /var/www/hotnow/index.html) |
app.hotnow.io |
PWA shell | SvelteKit SPA, static export, served by Caddy |
api.hotnow.io |
REST API backend | FastAPI on Core server (152.53.192.33), port 8001 |
dashboard.hotnow.io |
Business dashboard | SvelteKit SPA (shared component library with app) |
cdn.hotnow.io |
Static assets (optional) | Cloudflare CDN caching |
admin.hotnow.io |
Internal admin panel | Protected by Tailscale, minimal FastAPI admin |
4. Data Model
Core Entities
Events
CREATE TABLE events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
title VARCHAR(255) NOT NULL,
description TEXT,
category event_category NOT NULL, -- enum: music, food_drink, arts_culture, nightlife, sports, family, pop_up, other
start_time TIMESTAMPTZ NOT NULL,
end_time TIMESTAMPTZ,
timezone VARCHAR(50) DEFAULT 'America/Chicago',
is_recurring BOOLEAN DEFAULT false,
recurrence_rule VARCHAR(255), -- RRULE format
is_featured BOOLEAN DEFAULT false,
-- Venue relationship
venue_id UUID REFERENCES venues(id) ON DELETE CASCADE,
-- Media
cover_image_url VARCHAR(500),
media_urls JSONB DEFAULT '[]', -- [{url, type, order}]
-- Pricing
price_info JSONB DEFAULT NULL, -- {type: free|paid|varies, range: {min, max}, currency}
ticket_url VARCHAR(500),
-- Source attribution
source VARCHAR(100) NOT NULL, -- 'manual', 'super_search', 'user_submitted', 'api_partner'
source_event_id VARCHAR(255), -- external ID for dedup
source_url VARCHAR(500),
-- Real-time signals (updated by background worker)
trending_score FLOAT DEFAULT 0.0,
popularity_pulse INTEGER DEFAULT 0, -- short-term velocity (last 2 hours)
social_mention_count INTEGER DEFAULT 0,
search_volume_24h INTEGER DEFAULT 0,
check_in_count INTEGER DEFAULT 0,
ai_sentiment_score FLOAT DEFAULT 0.0, -- -1.0 to 1.0
-- Metadata
tags TEXT[] DEFAULT '{}',
is_active BOOLEAN DEFAULT true,
reviewed_by_admin BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Geospatial: events inherit location from venue, but can override
-- Indexes
CREATE INDEX idx_events_trending ON events (trending_score DESC) WHERE is_active = true;
CREATE INDEX idx_events_time_range ON events (start_time, end_time) WHERE is_active = true;
CREATE INDEX idx_events_category ON events (category) WHERE is_active = true;
CREATE INDEX idx_events_venue ON events (venue_id);
CREATE INDEX idx_events_source_dedup ON events (source, source_event_id);
Venues
CREATE TABLE venues (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
description TEXT,
venue_type venue_type NOT NULL, -- enum: bar, restaurant, club, theater, park, gallery, pop_up, other
-- Contact
address VARCHAR(500),
city VARCHAR(100) NOT NULL,
state VARCHAR(50),
postal_code VARCHAR(20),
country VARCHAR(2) DEFAULT 'US',
-- Geospatial (PostGIS)
location GEOGRAPHY(POINT, 4326), -- lat/lng for proximity queries
geo_json JSONB DEFAULT NULL, -- polygon for venues with boundaries
-- Contact
phone VARCHAR(20),
website VARCHAR(500),
social_links JSONB DEFAULT '{}', -- {instagram, facebook, twitter, tiktok}
-- Hours
hours JSONB DEFAULT NULL, -- [{day, open, close}]
is_permanently_closed BOOLEAN DEFAULT false,
-- Media
cover_image_url VARCHAR(500),
media_urls JSONB DEFAULT '[]',
-- Real-time signals
trending_score FLOAT DEFAULT 0.0,
current_busy_level busy_level DEFAULT 'unknown', -- enum: quiet, moderate, busy, packed
-- Business owner (links to Stripe customer)
owner_user_id UUID REFERENCES users(id),
-- Metadata
source VARCHAR(100) DEFAULT 'manual',
source_venue_id VARCHAR(255),
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_venues_location ON venues USING GIST (location);
CREATE INDEX idx_venues_city ON venues (city, state);
CREATE INDEX idx_venues_type ON venues (venue_type);
Users
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE,
display_name VARCHAR(100),
avatar_url VARCHAR(500),
-- Auth
password_hash VARCHAR(255),
auth_provider auth_provider DEFAULT 'email', -- enum: email, google, apple
auth_provider_id VARCHAR(255),
email_verified BOOLEAN DEFAULT false,
-- Subscription
tier subscription_tier DEFAULT 'explorer', -- explorer, pro, concierge
stripe_customer_id VARCHAR(100),
subscription_status subscription_status DEFAULT 'inactive', -- active, past_due, canceled, inactive
subscription_expires_at TIMESTAMPTZ,
-- Preferences
home_city VARCHAR(100),
home_location GEOGRAPHY(POINT, 4326),
preferred_categories TEXT[] DEFAULT '{}',
preferred_radius_km INTEGER DEFAULT 10,
notification_prefs JSONB DEFAULT '{}', -- {push, email, sms, categories}
-- PWA
push_subscription JSONB DEFAULT NULL, -- Web Push subscription object
-- Metadata
is_business BOOLEAN DEFAULT false,
is_admin BOOLEAN DEFAULT false,
last_active_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_users_email ON users (email);
CREATE INDEX idx_users_stripe ON users (stripe_customer_id);
Search/Discover Events (Lightweight for feed)
CREATE TABLE discover_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
event_id UUID REFERENCES events(id) ON DELETE CASCADE,
user_id UUID NOT NULL, -- anonymized session UUID for anonymous users
action discover_action NOT NULL, -- enum: view, click, save, share, check_in
source_context VARCHAR(50), -- 'map', 'feed', 'search', 'detail'
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_discover_events_user_time ON discover_events (user_id, created_at DESC);
CREATE INDEX idx_discover_events_event ON discover_events (event_id, created_at);
Business Features
CREATE TABLE business_features (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
venue_id UUID REFERENCES venues(id) ON DELETE CASCADE,
feature_type feature_type NOT NULL, -- featured_placement, event_boost, promoted_listing
status feature_status DEFAULT 'active',
starts_at TIMESTAMPTZ NOT NULL,
ends_at TIMESTAMPTZ NOT NULL,
stripe_payment_id VARCHAR(100),
amount_paid_cents INTEGER,
metadata JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT NOW()
);
Cached/Search Index (Redis)
# Trending events by city (sorted set, scored by trending_score)
trending:{city}:{category} → Sorted Set {event_id: score}
# Real-time pulse (current activity, 15-min TTL)
pulse:{event_id} → {view_count, click_count, save_count, last_updated}
# User sessions (JWT refresh tokens)
session:{user_id}:{device_id} → {refresh_token, expires_at, device_info}
# Rate limiting
ratelimit:{ip}:{endpoint} → counter with TTL
# Geo-index cache (pre-computed bounding boxes)
geo:{lat}:{lng}:{radius_km} → Set of event_ids (TTL: 5 min)
5. API Surface
REST API (api.hotnow.io/v1)
Events
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/events/trending |
Optional | Trending events (paginated, filtered by location/category) |
GET |
/events/nearby |
Optional | Events within radius of lat/lng |
GET |
/events/:id |
Optional | Full event detail with venue info |
GET |
/events/search |
Optional | Full-text search + Super Search v2 aggregation |
POST |
/events/submit |
User | User-submitted event (goes to review queue) |
POST |
/events/:id/save |
User | Save/bookmark event |
POST |
/events/:id/check-in |
User | Check in (anonymized, feeds trending) |
GET |
/events/:id/pulse |
Optional | Real-time activity data for this event |
Venues
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/venues/nearby |
Optional | Venues within radius |
GET |
/venues/:id |
Optional | Venue detail + upcoming events |
GET |
/venues/:id/busy |
Optional | Current busy level estimate |
Discovery
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/discover/feed |
Optional | Personalized feed (AI if Pro tier, trending if free) |
GET |
/discover/recommendations |
Pro | AI-powered recommendations |
POST |
/discover/action |
Optional | Log view/click/save for trending signals |
Auth
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/auth/register |
None | Create account (email + password) |
POST |
/auth/login |
None | Login → JWT access + refresh token |
POST |
/auth/refresh |
Refresh | Get new access token |
POST |
/auth/logout |
Access | Revoke refresh token |
POST |
/auth/oauth/google |
None | Google OAuth login |
GET |
/auth/me |
Access | Current user profile |
Subscriptions
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/billing/plans |
None | Available subscription tiers |
POST |
/billing/subscribe |
User | Create Stripe checkout session |
GET |
/billing/portal |
User | Redirect to Stripe Customer Portal |
POST |
/billing/webhook |
Stripe | Stripe webhook receiver |
Business
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/business/dashboard |
Business | Business metrics and active features |
POST |
/business/featured |
Business | Purchase Featured Placement |
POST |
/business/boost |
Business | Purchase Event Boost |
GET |
/business/analytics |
Business | Impressions, clicks, conversions |
Admin (internal)
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/admin/review-queue |
Admin | Events/venues pending review |
POST |
/admin/review/:id |
Admin | Approve/reject submission |
POST |
/admin/recalculate-trending |
Admin | Force trend recalculation |
GET |
/admin/stats |
Admin | Platform metrics |
Auth Flow
1. User registers/logs in → receives:
- access_token (JWT, 15 min expiry)
- refresh_token (opaque, 30 day expiry, stored in Redis)
2. Every API call: Authorization: Bearer <access_token>
3. Access token expires → POST /auth/refresh → new access_token
4. Logout → revoke refresh_token in Redis
5. Anonymous users: session_id (UUID v4, stored in localStorage)
- Limited rate: 100 requests/hour
- Cannot save/bookmark (no persistence without account)
Rate Limits
| Tier | Requests/Hour | Special Limits |
|---|---|---|
| Anonymous | 100 | Search: 10/hr |
| Explorer (Free) | 300 | AI recs: none, Save: 50 |
| Pro ($4.99/mo) | 1000 | AI recs: 100/hr, Offline: full |
| Concierge ($19.99/mo) | 5000 | AI recs: unlimited, Concierge chat: 50/day |
| Business | 500 | Dashboard + analytics |
| Admin | Unlimited | All endpoints |
6. Real-Time Ranking Algorithm
The HotNow Score
The core innovation. Every event has a trending_score recalculated every 5 minutes by a background worker.
HOT_SCORE = (
SOCIAL_BUZZ × 0.30 +
ENGAGEMENT_VELOCITY × 0.25 +
RECENCY_DECAY × 0.20 +
AI_SENTIMENT × 0.15 +
MANUAL_BOOST × 0.10
) × CITY_NORMALIZATION
Signal Components
| Signal | Weight | Sources | Decay |
|---|---|---|---|
| SOCIAL_BUZZ | 30% | Instagram geotag mentions, X/Twitter mentions, TikTok location tags (via Super Search) | Half-life: 4 hours |
| ENGAGEMENT_VELOCITY | 25% | HotNow own telemetry: views/min, clicks/min, saves/min, check-ins/min | Half-life: 2 hours |
| RECENCY_DECAY | 20% | Time until event start. Events starting soon get boost. | Linear ramp: peaks 2h before, decays after start |
| AI_SENTIMENT | 15% | Super Search v2 NLP sentiment on social mentions about the venue/event | 24h rolling window |
| MANUAL_BOOST | 10% | Featured Placement ($97/mo), Event Boost ($47/event) | Fixed duration |
City Normalization
CITY_NORMALIZATION = log10(active_users_in_city + 1) / log10(total_events_in_city + 1)
Prevents NYC/London from dominating. Small cities can compete.
Anti-Gaming Measures
- Velocity caps: engagement increase >300% in 15 min → throttled
- Bot detection: suspicious patterns (same IP, rapid fire) → excluded
- Review queue: user-submitted events require admin approval before trending
- Manual boost transparency: clearly labeled in UI ("Promoted")
Data Pipeline
┌─────────────────┐
│ Super Search v2 │ ← 7 providers, already live on Core
│ (aggregator) │
└────────┬────────┘
│ Every 15 min
▼
┌─────────────────┐
│ Ingestion Worker │ ← Redis queue (ARQ), dedup by source_event_id
│ │ enrich with geocoding, AI sentiment
└────────┬────────┘
│
▼
┌─────────────────┐
│ PostgreSQL │ ← Events + Venues tables
└────────┬────────┘
│ Every 5 min
▼
┌─────────────────┐
│ Trend Calculator │ ← Compute HOT_SCORE for all active events
│ (ARQ cron job) │ Update trending_score, write to Redis sorted sets
└────────┬────────┘
│
▼
┌─────────────────┐
│ Redis │ ← Sorted sets: trending:{city}:{category}
│ │ API reads directly from Redis (sub-millisecond)
└─────────────────┘
7. Component Tree & PWA Shell
PWA Architecture
app.hotnow.io (SvelteKit SPA, static export)
│
├── src/
│ ├── routes/
│ │ ├── +layout.svelte # Shell (nav, bottom tabs, auth state)
│ │ ├── +page.svelte # Map view (default/home)
│ │ ├── discover/
│ │ │ └── +page.svelte # Discovery feed (list)
│ │ ├── event/
│ │ │ └── [id]/
│ │ │ └── +page.svelte # Event detail
│ │ ├── venue/
│ │ │ └── [id]/
│ │ │ └── +page.svelte # Venue detail
│ │ ├── search/
│ │ │ └── +page.svelte # Search + filters
│ │ ├── profile/
│ │ │ └── +page.svelte # User profile, saved events
│ │ ├── settings/
│ │ │ └── +page.svelte # Preferences, notifications
│ │ ├── auth/
│ │ │ ├── login/+page.svelte
│ │ │ └── register/+page.svelte
│ │ └── concierge/
│ │ └── +page.svelte # Concierge chat (Pro tier)
│ │
│ ├── lib/
│ │ ├── components/
│ │ │ ├── Map.svelte # Leaflet wrapper
│ │ │ ├── EventCard.svelte # Horizontal/vertical card variant
│ │ │ ├── EventDetail.svelte # Full modal/page detail
│ │ │ ├── VenueCard.svelte
│ │ │ ├── TrendPulse.svelte # Live activity indicator
│ │ │ ├── CategoryFilter.svelte
│ │ │ ├── SearchBar.svelte
│ │ │ ├── BottomNav.svelte # Mobile bottom tab bar
│ │ │ ├── ConciergeChat.svelte # AI chat interface
│ │ │ └── PwaInstall.svelte # Install prompt
│ │ ├── stores/
│ │ │ ├── auth.ts # JWT + refresh logic
│ │ │ ├── location.ts # Geolocation watcher
│ │ │ ├── events.ts # Event cache + trending
│ │ │ └── settings.ts # User preferences
│ │ ├── api/
│ │ │ ├── client.ts # Fetch wrapper with auth
│ │ │ ├── events.ts
│ │ │ ├── venues.ts
│ │ │ ├── discover.ts
│ │ │ └── auth.ts
│ │ └── utils/
│ │ ├── geo.ts # Distance, bounding box calc
│ │ ├── offline.ts # IndexedDB + SW helpers
│ │ └── format.ts # Date, price, category formatting
│ │
│ ├── service-worker.ts # PWA offline cache
│ └── app.css # Tailwind + brand colors
│
├── static/
│ ├── manifest.json # PWA manifest
│ ├── icons/ # PWA icons (192, 512)
│ └── favicon.ico
│
├── svelte.config.js
├── vite.config.ts
├── tailwind.config.ts
└── package.json
Key UI Patterns
Map View (Home Screen)
- Full-screen Leaflet map (OpenStreetMap tiles pre-cached for offline)
- Clustered markers colored by category
- Pulsing markers for "hot right now" (pulse speed = trending_score)
- Bottom sheet (swipeable): list of nearby trending events
- Filter chip bar: All | Music | Food/Drink | Arts | Nightlife | Pop-ups
- Location button: recenter, radius slider
Discovery Feed
- Vertical scroll list of EventCards
- Each card: cover image, title, venue, distance, trending badge, time
- Pull-to-refresh (recalculates location + trending)
- "Happening Now" horizontal carousel at top
- Skeleton loading states
Event Detail
- Hero image with gradient overlay
- Title, venue name (tappable → venue detail), distance
- "Hot right now" pulse indicator
- Description, category badges, tags
- Price info + ticket link
- Actions: Save, Share, Check In, Get Directions
- Map snippet showing location
- "Nearby" section: other trending events nearby
Business Dashboard (dashboard.hotnow.io)
- Auth-gated, only for users with
is_business = true - Overview: impressions, clicks, saves for their venue/events
- Purchase flow: Featured Placement, Event Boost
- Analytics: 7-day, 30-day charts
- Manage venue details, hours, photos
8. Infrastructure & Deployment
Server: Netcup RS 2000 (Core — 152.53.192.33)
Services:
PostgreSQL 16 + PostGIS:
database: hotnow
user: hotnow_app
extensions: postgis, pg_trgm, uuid-ossp
Redis 7:
instance: hotnow
maxmemory: 256mb
policy: allkeys-lru
FastAPI (api.hotnow.io):
port: 8001
workers: 4 (gunicorn + uvicorn)
systemd service: hotnow-api
ARQ Workers:
service: hotnow-worker
queues: ingestion, trending, notifications, cleanup
Caddy:
config: /etc/caddy/Caddyfile
routes:
hotnow.io → /var/www/hotnow/index.html (landing page)
app.hotnow.io → /var/www/hotnow-app/ (SvelteKit build)
api.hotnow.io → reverse_proxy localhost:8001
dashboard.hotnow.io → /var/www/hotnow-dashboard/ (SvelteKit build)
Cloudflare DNS
A hotnow.io → 152.53.192.33
A app.hotnow.io → 152.53.192.33 (or CNAME → hotnow.io)
A api.hotnow.io → 152.53.192.33 (or CNAME → hotnow.io)
A dashboard.hotnow.io → 152.53.192.33 (or CNAME → hotnow.io)
CNAME www.hotnow.io → hotnow.io
Environment Variables
# /etc/hotnow/.env
DATABASE_URL=postgresql://hotnow_app:${DB_PASSWORD}@localhost:5432/hotnow
REDIS_URL=redis://localhost:6379/0
JWT_SECRET=${JWT_SECRET}
JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET}
STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY}
STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET}
SUPER_SEARCH_ENDPOINT=http://localhost:8000 # Super Search v2 MCP
SUPER_SEARCH_API_KEY=${SUPER_SEARCH_API_KEY}
ENVIRONMENT=production
CORS_ORIGINS=https://app.hotnow.io,https://dashboard.hotnow.io
9. Build Plan Preview (Phases 2-4)
Phase 2: Core Build ($20-25 budget, premium models)
What gets built:
- Database setup — PostgreSQL + PostGIS on Core server. Run migrations for all tables.
- FastAPI backend — All API endpoints listed above. Auth flow (JWT + refresh). Stripe integration (subscriptions + business payments).
- Super Search v2 integration — Event ingestion pipeline. Dedup logic. Geocoding enrichment.
- Trending algorithm — HOT_SCORE calculator. ARQ cron job. Redis sorted set population.
- PWA shell — SvelteKit SPA. Map view with Leaflet. Discovery feed. Event detail. Search. Auth. Bottom navigation.
- Business dashboard — Basic dashboard with analytics and purchase flow.
- Caddy + Cloudflare — Subdomain routing. SSL. Rate limiting.
Models used: claude-sonnet-4-20250514 for complex backend logic, gpt-4o for frontend, deepseek-v4-pro for architecture decisions.
Phase 3: Review + Hardening ($8-10 budget)
What gets hardened:
- Security audit — JWT hardening, input validation, SQL injection check, CORS review.
- Performance — API response time optimization, database query tuning, Redis cache hit rate.
- Error handling — Graceful degradation, offline fallbacks, rate limit UX, payment failure flows.
- PWA audit — Lighthouse PWA score, offline functionality, install flow, push notifications.
- Mobile testing — iOS Safari, Chrome Android, Samsung Internet. Responsive breakpoints.
- Seed data — Populate with real events for launch city. Verify trending algorithm with live data.
- Business onboarding flow — Stripe Connect setup, venue claim flow, payment testing.
Models used: claude-sonnet-4-20250514 for code review, gpt-4o for testing, deepseek-v4-pro for security analysis.
Phase 4: Launch Package ($5-7 budget)
What gets packaged:
- Launch city campaign — SEO landing page for target city. Social media post templates.
- Email sequence — Welcome email, weekly digest ("What's Hot This Weekend"), re-engagement.
- Analytics dashboard — Simple admin analytics: DAU/MAU, event engagement, revenue tracking.
- Business outreach kit — One-page pitch for venues to advertise. "Claim your venue" email template.
- Documentation — Deployment runbook, API docs (auto-generated by FastAPI), admin guide.
- Monitoring — Uptime Kuma check for api.hotnow.io health endpoint. Error alerting.
- Launch checklist — Pre-launch verification items. Go/no-go criteria.
10. Follow-Up Questions for Germaine
Launch Strategy
-
Launch city? You mentioned Savannah in the doc. Is that the definite first market? Pros: manageable size, tourist economy, strong local culture, your home base. Cons: smaller user base, seasonal tourism. Alternatives to consider: Austin (tech-forward, young demo), Nashville (music + nightlife), Charleston (tourism + culture, close to Savannah).
-
Savannah-specific considerations? SCAD students are a natural early adopter demographic. Should we do a SCAD ambassador program (similar to Beli's campus model)? Are there local event organizers / venues we should partner with pre-launch?
-
City-rollout strategy? One city at a time (depth-first) or multi-city from launch (breadth-first)? Depth-first: build strong network effects in one market, then expand. Breadth-first: broader appeal but thinner data per city.
Data Strategy
-
Seed data sources? Super Search v2 gives us web crawl + search aggregation. But for launch, should we also:
- Manually curate 50-100 events/venues in the launch city to ensure quality?
- Partner with local event organizers, venues, tourism boards?
- Scrape existing platforms (Eventbrite, Facebook Events) as seed data?
- User submissions from day one (UGC)?
-
Data quality vs. quantity? Fever/DICE has 100% quality (curated) but narrow scope. Eventbrite has massive scope but low quality. Where should HotNow start on this spectrum?
Revenue Priority
-
Consumer subscriptions vs. business placements — which is Priority A?
- Consumer-first: requires user acquisition → conversion to Pro/Concierge. Longer path to revenue.
- Business-first: sell Featured Placement + Event Boost to venues immediately. Faster revenue, but need traffic to sell.
- Hybrid: launch with free tier + business placements, add Pro/Concierge in month 2-3.
-
Concierge tier ($19.99/mo) — what should it actually offer at launch? Curated experiences require human or AI curation effort. Options:
- AI-powered concierge chat (lower cost, always available)
- Human-curated weekly picks (higher value, higher cost)
- Hybrid: AI for instant answers, human for weekly curated lists
Technical Choices
-
Map provider — Leaflet (OpenStreetMap) free or splurge on Mapbox?
- Leaflet + OSM: free, no API keys, works offline. Less polished tiles.
- Mapbox: beautiful tiles, better dark theme, 3D buildings. $0 for first 50K monthly loads, then ~$200+/mo at scale.
- Recommendation: start with Leaflet, swap to Mapbox when revenue supports it.
-
Hard constraints on tech stack? You've already chosen FastAPI + SvelteKit + PostgreSQL. Any of these non-negotiable? Any you'd prefer to swap?
-
Progressive Web App vs. native mobile? PWA is the plan (no app store, instant updates, offline). When/if should we invest in native iOS/Android? Trigger points: 10K MAU? Revenue milestone?
Timeline & Budget
-
Phase 2 timeline expectations? At $20-25 budget with premium models, I estimate Phase 2 takes about 8-12 hours of build time (subagent + human orchestration). Does that match your timeframe?
-
MVP definition — what's the absolute minimum for "go live"?
- Must have: map, trending events, search, event detail, basic auth
- Nice to have: AI recommendations, offline mode, Concierge chat, business dashboard
- Your call on the cutoff for launch
Appendix A: Existing Assets Snapshot
| Asset | Path | Status |
|---|---|---|
| Landing page | /var/www/hotnow/index.html |
✅ Live (1342 lines, 38KB) |
| Mockup | /var/www/mockup/hotnow/index.html |
✅ Complete (432 lines, 14KB) |
| Project doc | /root/projects/itpp-infrastructure/projects/hotnow.md |
✅ Comprehensive (827 lines) |
| Domain | hotnow.io |
✅ Registered at Cloudflare |
| Server | Core (152.53.192.33), Netcup RS 2000 | ✅ Operational |
| Super Search v2 | MCP on Core | ✅ 7 providers, all healthy |
| Caddy | Reverse proxy on Core | ✅ Configured |
| PostgreSQL 16 | On Core | ✅ Running |
| Redis | On Core | ✅ Running |
Appendix B: Key Market Signals
- Gen Z discovery: 77% discover restaurants on social media (Eater/Vox 2025 survey)
- Beli growth: 30M reviews in 2024 (surpassing Yelp's 21M) — demand for social-forward discovery
- Fever acquired DICE: Consolidation in curated event space — leaves gap for comprehensive real-time
- Nextdoor AI pivot: "LLM for every neighborhood" — validates AI + hyperlocal
- Corner's $3.75M raise: VCs betting on map-first social discovery for Gen Z
- Yelp's AI transformation: Incumbent feels threat from new discovery paradigms
- Eventbrite rebrand: Moving from utility to cultural hub — validates shift toward experience economy