# Utah Mountain Luxury Management This is a private operations dashboard for short-term rentals (Ranch House, Lindon House, River House) and a construction project. Live: https://wilhite-portfolio.pages.dev ## For browser agents (Grok / Cursor) 1. Read `/api/agent/map` (JSON) or this file. 2. Prefer **hash routes** or `window.UML.navigate(...)` over clicking the top nav. Overlay widgets can intercept clicks. 3. After login, `document.documentElement.dataset.umlTab` is the current screen. 4. Primary controls use `data-bot="..."` attributes. ### Hash routes - `#/overview` — portfolio - `#/report` — P&L report - `#/report/documents` — e-sign / document vault - `#/guests` - `#/ranch` `#/lindon` `#/river` — River rental P&L - `#/river/build` — River House build cost spreadsheet (Todd vs Brandon & Stephanie). `#/construction` still opens this. - `#/ours` — Brandon & Stephanie household / furnishings (photo, paste text, or manual; off rental P&L) ### JavaScript bridge ``` UML.navigate("construction") UML.navigate("report", "documents") UML.setMonth("2026-08") UML.state() UML.help() ``` ### Login POST `/api/auth/login` with `{ "password": "..." }` (cookie). Form: `[data-bot="login-password"]` and `[data-bot="login-submit"]`. ### Do not - Put construction partner bills on ranch/lindon/river. Partner spend is construction only. - Treat Lindon as 50/50 with Todd; Lindon is Brandon’s rental P&L. - Use Firecrawl unless the user asked. ### Useful APIs (cookie auth) - GET `/api/portfolio/metrics?month=YYYY-MM` - GET `/api/expenses` - POST `/api/expenses` — construction: `propertyId: "construction"`, `paidBy: "brandon"|"todd"`, `stage` - POST `/api/expenses` — Brandon & Stephanie household: `propertyId: "household"`, `paidBy: "brandon"`, `category` Furnishings/Decor/Supplies/Other - POST `/api/agent/chat` — rental co-host tools - POST `/api/agent/construction/chat` — construction manager - GET `/api/construction/project` - GET `/api/esign/templates` - POST `/api/esign/parse-invoice` — import a contractor invoice or email onto a lien waiver (`type`: text / image / gmail / gmail-search) - GET `/api/surveys` — upcoming stays + preference surveys - POST `/api/surveys/send` — `{ reservationId? , confirmationCode?, channel: "email"|"sms"|"none" }` mints `/stay/:token`. `none` copies a link for Airbnb paste (does not email/SMS the guest). - GET/POST `/api/stay-preferences/:token` — public guest survey. River uses the short VIP flow.