Initial commit: MSD backend API, docs, mockups, README
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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 |
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user