Added snapshot_date column with unique constraint on (platform_id,
snapshot_date). Worker now upserts instead of inserting, so repeated
scrapes on the same day update the existing row rather than creating
duplicates that cause inflated chart values. Cleaned up existing
duplicate rows in migration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The trends and snapshots endpoints returned periodLabel ("last_30_days")
as the date field, which parseISO() couldn't parse, causing all records
to be filtered out. Now uses capturedAt timestamp for date filtering and
display.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full-stack short-term rental management platform with:
- React/Vite frontend with dark theme dashboard, performance, pricing,
reservations, experiments, and settings pages
- Fastify API server with auth, platform management, performance tracking,
pricing, reservations, experiments, and weekly report endpoints
- Playwright-based scraper service with Airbnb adapter (login with MFA,
performance metrics, reservations, calendar pricing, price changes)
- VRBO adapter scaffold and mock adapter for development
- PostgreSQL with Drizzle ORM, migrations, and seed scripts
- Job queue with worker for async scraping tasks
- AES-256-GCM credential encryption for platform credentials
- Session cookie persistence for scraper browser sessions
- Docker Compose for PostgreSQL database
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>