Initial commit: MSD backend API, docs, mockups, README

This commit is contained in:
root
2026-08-07 10:40:57 -04:00
commit 2f744811fc
12 changed files with 3159 additions and 0 deletions
+88
View File
@@ -0,0 +1,88 @@
# Anti-VRBO Playbook — Beating Vacation Rental Site Bot Protection
## Test Results (Aug 1, 2026)
| Site | Protection | Camofox Result | Notes |
|------|-----------|---------------|-------|
| **Airbnb** | Cloudflare + custom | **BEATEN** ✓ | Full page load, 5.7KB body, all content extracted. Camofox + DataImpulse proxy cleared Cloudflare with zero issues. |
| **VRBO** | Imperva/Incapsula | **BLOCKED** ✗ | "Bot or Not?" challenge wall. Imperva blocks at the application layer even after Cloudflare passthrough. Challenge doesn't auto-resolve even after 45s wait. |
| **Booking.com** | Akamai | **Untested** | — |
| **Vacasa** | Unknown | **Untested** | — |
| **Evolve** | Unknown | **Untested** | — |
## VRBO / Imperva — What We Tried
### Failed Approaches
1. **Direct camofox navigation** — Landed on "Bot or Not?" challenge page with Imperva session ID
2. **Extended wait (45s)** — Challenge regenerates but never auto-resolves
3. **Snapshot inspection** — Imperva challenge page has almost zero interactive elements; just a logo link
### Why Imperva Is Harder Than Cloudflare
- Cloudflare challenges happen at the edge (before the page loads) and Camoufox's C++-level fingerprint spoofing clears them
- Imperva challenges happen at the application layer AFTER the page loads — they inject their own JS that runs fingerprinting on top of whatever the browser reports
- Imperva's SDK (`window._Incapsula_Resource`) does behavioral analysis: mouse movements, scroll patterns, timing
- The challenge ID changes on every request (different UUID each time), suggesting it's stateless at the edge but stateful in their backend
## Strategies to Beat VRBO
### Strategy 1: Headful Browser with Human Emulation (Most Promising)
Instead of headless camofox, use a real Chrome/Chromium with CDP and emulate realistic human behavior:
```
1. Launch Chrome with puppeteer-real-browser or nodriver
2. Navigate to VRBO
3. Inject human-like mouse movements (bezier curves, not straight lines)
4. Random scrolls and hover events
5. Wait for Imperva challenge to auto-resolve (usually 5-15s in a real browser)
6. Extract data once page loads normally
```
### Strategy 2: VRBO API Reverse Engineering
VRBO's frontend calls internal APIs. If we can find the endpoints:
- Search: `vrbo.com/api/v1/search?...`
- Property details: `vrbo.com/api/v1/properties/1313017`
- Calendar: `vrbo.com/api/v1/properties/1313017/calendar`
Many of these may have weaker bot protection than the HTML pages. Imperva primarily protects the SSR HTML; API calls may use simpler auth.
### Strategy 3: Browserbase / Anchor (Cloudflare Web Bot Auth)
If VRBO opts into Cloudflare's Bot Verifier program, Browserbase/Anchor can get a signed "verified bot" token. But this only works if VRBO explicitly allows it — unlikely for a booking site.
### Strategy 4: Alternative Data Sources
Since Airbnb works perfectly with camofox, and most vacation rentals cross-list:
- **Airbnb** (working): Property details, pricing, reviews, calendar, photos
- **Google Travel / Hotel search**: Aggregates VRBO listings
- **VRBO via Google cache**: `webcache.googleusercontent.com/search?q=cache:vrbo.com/1313017`
### Strategy 5: Proxy Rotation + Fingerprint Diversity
Imperva may be flagging specific DataImpulse IP ranges. Try:
- Different proxy providers (SOAX, Bright Data, IPRoyal)
- Different geolocations
- Different Camoufox fingerprint profiles
- Session-level IP rotation
## Recommended Approach for Moore Sunny Daze
**Short-term (now):** Use Airbnb data since camofox clears it consistently. All the same content is there — Tim's listing is synced across platforms.
**Medium-term (this week):** Implement Strategy 1 (headful browser with human emulation) specifically for VRBO. This is the most reliable path.
**Long-term (product):** Build a unified scraper that tries Airbnb first, falls back to headful browser for VRBO, and caches results. This becomes the "Competitive Intelligence" feature of Beach Direct — show owners how their property compares to nearby listings on ALL platforms.
## Airbnb Data We Successfully Extracted
From the Airbnb listing (camofox, Aug 1 2026):
- Full property description
- 47 amenities list
- 5.0 rating across all categories (cleanliness, accuracy, check-in, communication, location, value)
- 4 reviews with text
- Calendar availability for Aug-Sep 2026
- Host: Ashley, 1 year hosting
- Property photos from Airbnb CDN
- Pricing: shown after date selection (requires interaction)
## Next Steps
1. [x] Confirm camofox beats Airbnb
2. [x] Document VRBO Imperva failure
3. [ ] Test headful browser approach for VRBO
4. [ ] Test Booking.com, Vacasa, Evolve
5. [ ] Build unified scraper module for Beach Direct
+85
View File
@@ -0,0 +1,85 @@
# Moore Sunny Daze — Email Migration: Gmail → MXroute
## Current State
- Tim & Ashley use a @gmail.com address for rental inquiries
- Business correspondence mixed with personal email
- No professional domain-based email
## Target State
- **Email:** reservations@mooresunnydaze.com (or hello@, stay@ — TBD)
- **Platform:** Germaine's MXroute account
- **Access:** Webmail (Roundcube) + IMAP/SMTP for phone/desktop
## Steps
### 1. Create mailbox on MXroute
```bash
# Via MXroute DirectAdmin (Germaine's account)
# Add new mailbox: reservations@mooresunnydaze.com
# Generate strong password, save to Vaultwarden
```
### 2. Configure DNS at Cloudflare
After domain transfer is complete, add MX records:
```
Type Name Content Priority TTL
MX @ mx1.mxroute.com 10 120
MX @ mx2.mxroute.com 20 120
TXT @ v=spf1 include:mxroute.com ~all 120
```
### 3. Add DKIM (if MXroute provides it)
- Get DKIM record from MXroute control panel
- Add as TXT record in Cloudflare DNS
### 4. Add DMARC (optional but recommended)
```
Type Name Content
TXT _dmarc v=DMARC1; p=none; rua=mailto:g@germainebrown.com
```
### 5. Test email delivery
```bash
# Send test from external account
echo "test" | mail -s "Test" reservations@mooresunnydaze.com
# Verify receipt in Roundcube
# Send reply back
# Check SPF/DKIM/DMARC at mail-tester.com
```
### 6. Migrate existing emails (if needed)
- Google Takeout export of Gmail mailbox
- Import to MXroute via IMAP migration tool
- OR: set up Gmail forwarding for 90 days
### 7. Configure on Tim & Ashley's devices
- iPhone: Settings → Mail → Add Account → Other → IMAP
- Server: mail.mxroute.com
- IMAP port: 993 (SSL)
- SMTP port: 587 (STARTTLS) or 465 (SSL)
- Desktop: same IMAP settings in Apple Mail / Outlook / Thunderbird
### 8. Update all listings
- VRBO/Airbnb contact email → reservations@mooresunnydaze.com
- Facebook page contact → reservations@mooresunnydaze.com
- New website contact → reservations@mooresunnydaze.com
- Business cards/signage if any
### 9. Transition period (90 days)
- Set Gmail auto-reply: "We've moved! Please email reservations@mooresunnydaze.com"
- Forward Gmail → MXroute for 90 days
- After 90 days: remove forwarding, keep Gmail for personal use only
## Email addresses to set up
| Address | Purpose | Who accesses |
|---------|---------|-------------|
| reservations@ | Booking inquiries, guest communication | Tim & Ashley |
| stay@ | Alternative booking alias | Tim & Ashley |
| tim@ | Owner direct | Tim |
| ashley@ | Owner direct | Ashley |
## Cost
- **$0 additional** — included in Germaine's existing MXroute plan
- Domain email hosting = free with our hosting
+99
View File
@@ -0,0 +1,99 @@
# Moore Sunny Daze — Migration Plan
- **Mockups:** https://mockup.iamgmb.com/mooresunnydaze/ — three theme options + admin dashboard
- **Deployment standard:** mockup.iamgmb.com for prototypes/design review, proposals.iamgmb.com for business documents
## Current State
| Asset | Provider | Details |
|-------|----------|---------|
| Domain | GoDaddy | mooresunnydaze.com |
| Website | Wix | mooresunnydaze.com, Wix-built |
| Email | Gmail | @gmail.com (exact address TBD) |
| Booking | VRBO + Airbnb | vrbo.com/1313017, Airbnb listing |
| Social | Facebook | facebook.com/mooresunnydaze |
## Phase 1: Domain Transfer (GoDaddy → Cloudflare)
**Timeline:** 5-7 days (ICANN-mandated transfer lock)
### Steps
1. **Unlock domain at GoDaddy**
- GoDaddy Dashboard → Domain Settings → Turn off "Domain Lock"
2. **Get authorization code from GoDaddy**
- Domain Settings → Transfer domain away → Copy auth code
- Auth code valid for 15 days
3. **Initiate transfer at Cloudflare**
- Cloudflare Dashboard → Domain Registration → Transfer Domains
- Enter mooresunnydaze.com + auth code
- Cost: $10.46 (.com transfer, adds 1 year to registration)
4. **Approve transfer**
- GoDaddy sends confirmation email → approve
- Optional: expedite by accepting at GoDaddy immediately
5. **Wait for transfer** (5 days typical)
- Cloudflare auto-copies existing DNS records
- Nameservers switch to Cloudflare automatically
6. **Verify DNS**
- Check all records propagated
- Enable DNSSEC (free at Cloudflare)
- Keep proxy off until site is deployed (grey cloud)
## Phase 2: Website Migration (Wix → Us)
**Timeline:** After domain transfer + 24hr DNS propagation
### Steps
1. **Build new site** on our infrastructure
- Serve from Core via Caddy
- Domain: mooresunnydaze.com (A record → 152.53.33.195)
- Static HTML landing page (single file) + booking portal pages
2. **DNS cutover**
- Update A record for mooresunnydaze.com → Core IP
- Add www CNAME → mooresunnydaze.com
- Keep proxy off initially for Caddy ACME cert issuance
3. **SSL certificate**
- Caddy auto-obtains Let's Encrypt cert on first request
- Verify: curl -sI https://mooresunnydaze.com → 200
4. **Enable Cloudflare proxy** (optional, after cert valid)
- Toggle orange cloud on A record
- Switch to Full (strict) SSL in Cloudflare dashboard
5. **Post-migration cleanup**
- Cancel Wix subscription (wait until site live + verified)
- Export any Wix blog/content if needed
- Archive old Wix design as reference
## Phase 3: Email Migration (Gmail → MXroute)
See separate email migration plan.
## Phase 4: Booking System (VRBO/Airbnb → Direct)
### Short-term (keep both)
- Link "Book Now" to our own booking page
- Keep VRBO/Airbnb listings live during transition
- Add "Book Direct & Save" messaging on our site
### Long-term (go direct)
- Build Stripe-integrated reservation system
- Remove/downgrade VRBO listing once direct bookings established
- Leverage existing Facebook following for direct booking marketing
- Offer returning guest discounts for direct bookings
## Phase 5: Ongoing
- Nightly backups to S3 via hermes-backup
- Uptime monitoring via Uptime Kuma
- SSL auto-renewal via Caddy
- Monthly domain renewal check (Cloudflare auto-renew)
## Risk Mitigation
| Risk | Mitigation |
|------|-----------|
| DNS propagation delay | Start transfer on Monday, complete before weekend |
| Wix SSL break during DNS cutover | Keep Wix site active until new cert issued |
| Email downtime during MX switch | Configure MXroute first, then change MX records |
| Booking loss during transition | Keep VRBO/Airbnb live for 60 days minimum |
| Domain transfer rejection | Verify domain unlocked + WHOIS privacy off at GoDaddy |
+85
View File
@@ -0,0 +1,85 @@
# Moore Sunny Daze — Product Strategy: Beach Direct
## The Opportunity
Every vacation rental owner using VRBO/Airbnb pays 10-15% in platform fees. Tim's property is booked solid in peak season and has a 5.0-star rating with a growing following. This is the perfect profile for going direct.
But the real opportunity is bigger: **this is a repeatable playbook** for ANY vacation rental owner who wants to escape platform fees without losing bookings.
## Phase 1: Tim's Site (the blueprint)
Build Moore Sunny Daze as the reference implementation:
- Beautiful landing page with real photos
- Direct booking with Stripe (saves 10-15% vs VRBO)
- Admin dashboard for Tim to manage reservations
- Email marketing for returning guests
- Social media integration (Facebook following → direct bookings)
## Phase 2: Beach Direct — The Product
### What it is
A white-label vacation rental website + booking system for property owners who want to go direct.
### Target Customer
- Owns 1-3 vacation rental properties
- Listed on VRBO/Airbnb but frustrated with fees
- Has some existing guest following (social, email list)
- Wants a professional direct-booking website
- Doesn't want to manage complex tech
### Core Features
| Feature | Description |
|---------|-------------|
| Property Site | Single-page or multi-page custom site with their photos |
| Direct Booking | Calendar + Stripe payment integration |
| Admin Dashboard | Manage reservations, guest messages, availability |
| Guest CRM | Past guest database, email collection |
| Smart Pricing | Seasonal rates, minimum stays, holiday pricing |
| Email Automation | Booking confirmations, pre-arrival info, post-stay review request |
| Channel Sync | (v2) Sync availability calendar with VRBO/Airbnb to prevent double-booking |
| Analytics | Booking trends, revenue, guest sources |
### Pricing Model
| Tier | Setup Fee | Monthly | Features |
|------|-----------|---------|----------|
| Starter | $997 | $47/mo | Landing page, basic booking, admin dashboard |
| Pro | $2,497 | $97/mo | + Email automation, guest CRM, smart pricing |
| Full Service | $3,997 | $197/mo | + Channel sync, analytics, priority support |
*No per-booking fees — flat monthly only. This is the key differentiator vs VRBO.*
### Tech Stack
- Frontend: Single-file HTML/CSS/JS (or SvelteKit for dashboard)
- Backend: FastAPI on Core/app1 (Python)
- Payments: Stripe Connect (direct to owner's bank)
- Database: SQLite per property (simple, portable)
- Email: Resend or Postmark for transactional
- Hosting: Included in monthly fee
### Go-to-Market
1. **Tim's site** = first case study
2. **Cold outreach** to VRBO-listed owners in Destin/Miramar Beach area
3. **"Save $X,XXX/year" calculator** on our landing page
4. **Facebook groups** — vacation rental owner communities
5. **Referral program** — Tim refers other owners, gets free months
### Revenue Math (per 10 clients at Pro tier)
- Setup: 10 × $2,497 = $24,970 (one-time)
- Monthly: 10 × $97 = $970/mo recurring
- Annual: $36,610
### Differentiators vs VRBO/Airbnb
| | VRBO/Airbnb | Beach Direct |
|---|-------------|-------------|
| Booking fee | 10-15% per booking | $0 per booking |
| Guest data | Platform owns it | Owner owns it |
| Branding | Platform-branded | Owner's brand |
| Pricing control | Algorithm-influenced | Full control |
| Guest relationship | Platform-mediated | Direct relationship |
| Email marketing | Not allowed | Built in |
## Next Steps
1. Complete Tim's reference implementation
2. Document the build process as a playbook
3. Register beachdirect.io or similar domain
4. Build our own sales landing page
5. Target first 5 beta clients (free/discounted for testimonials)
6. Launch to Destin/Miramar Beach market
+205
View File
@@ -0,0 +1,205 @@
# Moore Sunny Daze — Reservation System with Stripe
## Architecture Overview
```
Guest Browser → Landing Page → Check Availability → Book → Stripe Checkout → Confirmation
Admin Dashboard (Tim)
```
## Components
### 1. Public Booking Flow
```
Landing Page (mooresunnydaze.com)
→ "Check Availability" button
→ Availability calendar (fetches from API)
→ Select dates → guest count → price quote
→ Guest details form (name, email, phone, # guests, pet?)
→ Stripe Checkout (embedded or redirect)
→ Confirmation page + email
```
### 2. Backend API (FastAPI on Core/app1)
| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/api/availability` | GET | Get booked dates for a month |
| `/api/quote` | POST | Calculate price for selected dates |
| `/api/booking` | POST | Create booking (pending payment) |
| `/api/booking/{id}/confirm` | POST | Confirm after Stripe payment |
| `/api/booking/{id}` | GET | View booking details |
| `/api/guest/{email}` | GET | Lookup returning guest |
### 3. Database Schema (SQLite)
```sql
-- Guests
CREATE TABLE guests (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
phone TEXT,
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Bookings
CREATE TABLE bookings (
id TEXT PRIMARY KEY,
guest_id TEXT REFERENCES guests(id),
check_in DATE NOT NULL,
check_out DATE NOT NULL,
guests_count INTEGER NOT NULL,
nightly_rate REAL NOT NULL,
cleaning_fee REAL DEFAULT 150,
total REAL NOT NULL,
status TEXT DEFAULT 'pending', -- pending, confirmed, cancelled, completed
stripe_session_id TEXT,
stripe_payment_intent TEXT,
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Blocked Dates
CREATE TABLE blocked_dates (
date DATE PRIMARY KEY,
reason TEXT -- 'booking_XYZ', 'maintenance', 'owner'
);
-- Rate Rules
CREATE TABLE rate_rules (
id TEXT PRIMARY KEY,
name TEXT,
start_date DATE,
end_date DATE,
nightly_rate REAL,
min_nights INTEGER DEFAULT 3
);
```
## Stripe Integration
### Setup
1. Tim creates Stripe account (stripe.com)
2. Connects business bank account
3. We get API keys from Stripe Dashboard
4. Store in `.env` on server
### Payment Flow
```python
# 1. Create Stripe Checkout Session
session = stripe.checkout.Session.create(
payment_method_types=['card'],
line_items=[{
'price_data': {
'currency': 'usd',
'product_data': {
'name': f'Moore Sunny Daze — {nights} nights',
'description': f'{check_in} to {check_out}, {guests} guests'
},
'unit_amount': int(total * 100), # cents
},
'quantity': 1
}],
mode='payment',
success_url='https://mooresunnydaze.com/booking/confirmed?session_id={CHECKOUT_SESSION_ID}',
cancel_url='https://mooresunnydaze.com/booking/cancelled',
customer_email=guest_email,
metadata={
'booking_id': booking_id,
'property': 'moore-sunny-daze'
}
)
# 2. Redirect to session.url
# 3. Stripe webhook → mark booking confirmed
```
### Webhook Handling
```python
@app.post("/stripe-webhook")
async def stripe_webhook(request: Request):
payload = await request.body()
sig = request.headers.get('stripe-signature')
event = stripe.Webhook.construct_event(payload, sig, WEBHOOK_SECRET)
if event['type'] == 'checkout.session.completed':
session = event['data']['object']
booking_id = session['metadata']['booking_id']
mark_booking_confirmed(booking_id)
send_confirmation_email(booking_id)
add_blocked_dates(booking_id)
return {"status": "ok"}
```
## Deployment
### Server
- Deploy on Core (152.53.33.195) as systemd service
- Port: 8910 (internal)
- Caddy reverse proxy: `mooresunnydaze.com/api/* → localhost:8910`
### Filesystem
```
/opt/mooresunnydaze/
├── server.py # FastAPI app
├── db.sqlite # SQLite database
├── .env # STRIPE_SECRET_KEY, etc
├── requirements.txt # fastapi, uvicorn, stripe, aiosqlite
└── templates/ # Email templates
```
### systemd Service
```ini
# /etc/systemd/system/mooresunnydaze.service
[Unit]
Description=Moore Sunny Daze Booking API
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/mooresunnydaze
ExecStart=/opt/mooresunnydaze/venv/bin/uvicorn server:app --host 127.0.0.1 --port 8910
Restart=always
[Install]
WantedBy=multi-user.target
```
## Admin Features
1. **Calendar view** — booked/available/blocked dates
2. **Booking management** — confirm, cancel, view details
3. **Guest directory** — past guests, contact info, stay history
4. **Rate management** — seasonal pricing, minimum stays
5. **Block dates** — maintenance, owner use
6. **Revenue reports** — monthly/annual totals
7. **Email templates** — confirmation, pre-arrival, post-stay
## Pricing Integration
Tim's property is currently listed at ~$295/night (peak season, from Airbnb). We'd implement:
- **Base rate:** $295/night peak, $225/night off-peak
- **Cleaning fee:** $150 flat
- **Pet fee:** $50 (if applicable)
- **Minimum stay:** 3 nights
- **Holiday premium:** +20% for major holidays
## Comparison: Direct vs VRBO
| | VRBO (current) | Direct (our system) |
|---|---|---|
| 3-night stay @ $295 | $885 + VRBO fee (~$130) | $885 (no fee) |
| Guest pays | ~$1,015 | $885 |
| Owner receives | ~$885 - VRBO 5% host fee | $885 - Stripe 2.9% |
| Owner net | ~$840 | ~$859 |
| **Savings to guest** | — | **$130 (13%)** |
| **Savings to owner** | — | **~$19/stay + guest relationship** |
## Next Steps
1. ✅ Design complete
2. Set up Stripe account for Tim
3. Build FastAPI backend
4. Deploy on Core
5. Wire up booking widget on landing page
6. Test end-to-end booking flow
7. Go live