Version history
Changelog
This is a public log of every notable change to weeklyescapes. We update it for each meaningful release. Format inspired by Keep a Changelog with our own commentary on why decisions were made.
Changelog
All notable changes to weeklyescapes are documented here.
2026-05-19 (evening, fifth batch)
Added: Smart "Switch to Hotel or resort" CTA when apartments return zero rates
Real cause discovered while auditing LiteAPI: many vacation rentals listed on LiteAPI (Booking.com Holiday Rentals, individual host inventory) appear in /listings but don't have API-bookable rates for short stays. Tempe Sep 1-8 with property_types=extended_stay returns 0 of 5 apartments with rates from LiteAPI; same query with property_types=hotels returns 3 of 5 with rates.
When /listings/rates returns zero rates AND user picked extended_stay, the empty state now shows a one-click switch:
No availability found for these dates. Try shifting your dates or
different properties. Switch to Hotel or resort → Vacation rentals
often don't sell instantly via API.
If user already on hotels filter and gets zero, suggests "Show all property types →". Keeps the funnel unblocked without auto-changing user intent. Documented as Decision S28 in decisions-log.
2026-05-19 (evening, fourth batch)
Added: Children + property type filter UI on /search
Audited LiteAPI documentation systematically (every endpoint in https://docs.liteapi.travel/reference). Identified three improvements based on the audit:
1. Children support in occupancies. LiteAPI accepts children as an array of ages, e.g. [3, 7] for two children aged 3 and 7. We were only passing adults. Now /listings/rates accepts a children list and threads it into the LiteAPI body. Frontend has "Children" dropdown that conditionally renders N age inputs (0-17 each).
2. Property type filter UI on /search. Hardcoded extended_stay default was hidden under URL param. Now there's a "Stay type" dropdown:
- Apartment or villa (default, per Decision S21)
- Hotel or resort
- Show all
Selection threads through to /listings hotelTypeIds filter.
3. Better empty-state handling for stays >30 nights. LiteAPI returns error code 2001 'no availability found' when stay duration exceeds supplier max stay (often 28-30 nights). We detect this and surface a helpful availability_note field. UI shows: "Most properties cap stays at ~30 nights via API. Try splitting your trip."
Also added maxRatesPerHotel: 3 to keep response sizes manageable (LiteAPI default unlimited, can return 1MB+ per hotel) and refundable_only opt-in for travelers wanting cancellable rates only.
Created docs/spec/liteapi-reference.md (519 lines) as comprehensive endpoint catalog covering all primary endpoints, request/response shapes, error codes, performance characteristics, account-manager-enabled features, and how-to-test recipes. Source of truth for our LiteAPI integration.
2026-05-19 (evening, third batch)
Added: Cooler Sign-in pill button + homepage Day 3 status
- Sign-in changed from inconspicuous link to amber pill button
- Homepage hero updated: "Pre-launch" → "Building in public · Day 3";
- Homepage "What's actually built" list updated to reflect reality:
(px-4 py-1.5 rounded-full bg-ink hover:bg-amber)
removed waitlist signup form, replaced with two clear CTAs: - "Search stays now →" (primary, dark) → /search - "Create a free account" (secondary, outline) → /sign-up
search/listings/rates/booking-sandbox/auth/dashboard all checked, production cutover in-progress, V2 items as TODO
Updated: README + Steering doc
README.md fully rewritten for Day 3 state with 17-row status table, current API endpoint list, full repo structure with all routes. Steering doc updated with current product surface, S17-S27 summary, API endpoints v0.6.0, /weeklyescapes/auth/* SSM namespace.
2026-05-19 (afternoon, third batch)
Added: User dashboard V1 — Clerk auth + bookings list
Per Decision S27, full V1 dashboard ships:
- Clerk authentication via
@clerk/clerk-jsCDN script (Google OAuth, Apple /sign-in,/sign-uppages mount Clerk components client-side/accountdashboard shows: profile, trips list, loyalty placeholder- Header has auth-aware area: "Sign in" link → UserButton when signed in
- Email-as-identity design: bookings keyed on holder.email so anonymous
OAuth, passkeys, email magic link; no passwords)
bookings auto-link when user signs up with same email later
Backend:
lib/clerk.pyverifies Clerk session via their API (no JWT lib bundled)lib/bookings.pyprovides DynamoDB save/list/upsert helpers- New endpoints:
GET /api/me,GET /api/bookings(both Clerk-auth required) POST /book/finalizenow writes BOOKING#records to DynamoDB - Health bumped to v0.6.0
SSM:
- New params:
/weeklyescapes/auth/clerk-publishable-key,/weeklyescapes/auth/clerk-secret-key - IAM policy extended to grant Lambda read access to
/weeklyescapes/auth/*
Frontend:
Layout.astroinjects Clerk script + has auth-aware header- New pages:
/sign-in,/sign-up,/account - New
scripts/fetch-auth.shpulls publishable key from SSM, writes to frontend/.envgitignored
frontend/.env at deploy time, picked up by Astro's import.meta.env
What's NOT in V1 (queued for V2)
- Email confirmations from us: requires SES production access (24-48hr
- LiteAPI loyalty points display: shown as placeholder on /account.
Amazon review). Customers still get Nuitee's confirmation email today.
Requires LiteAPI dashboard config (guest tiers + perks per tier) and loyaltyGuestId passthrough in prebook.
Test in browser
1. Visit https://weeklyescapes.com/sign-in/ 2. Sign in via Google/Apple/passkey/email link 3. Land on /account — should show profile + "No trips yet" 4. Optionally redo sandbox booking with your signed-in email as holder to see it appear in trips list
2026-05-19 (afternoon, second batch)
Added: Open destination search (any country + any city)
Per Decision S23, the 10-city dropdown is gone. /search now lets users pick any country (~65 popular travel countries) and type any city name. LiteAPI has inventory globally; we just weren't surfacing it.
Live results from open search:
?country=US&city=Tempereturns Tempe Studios, Tempe Lofts, ROVE LIVING,?country=IN&city=Goareturns Alaya Stays apartments with pool?country=GR&city=Mykonos,?country=US&city=Phoenix, etc. — anywhere
holiday homes near ASU
LiteAPI has inventory
Backend:
routes/listings.pyaccepts EITHERcity=(existing curated shortcutssources/liteapi.pysearch_listings_open()handles direct city_name +
for backwards compatibility) OR city_name= (new open search)
country_code queries; uses extended_stay property type filter by default
Frontend (/search.astro):
- Country dropdown with ~65 popular travel countries (alphabetical, ISO codes)
- City as free text input
- Form layout went from 6 columns to 7 on desktop, gracefully stacks on mobile
KNOWN_AIRPORTSmap of ~80 city → IATA pairs powers the flight lookup- For cities without a known airport, flight section degrades gracefully:
- Suggested-trip pills now include Tempe (US), Goa (India), Mykonos (Greece)
- Old URLs (
?destination=lisbon) still work — auto-resolved to country + city
"Pick a major airport for flight prices, or browse stays below"
alongside the original curated 10
Tradeoffs:
- Two form fields (country + city) instead of one dropdown. Worth it for
- City guides (per requirements.md G3) remain on the curated 10 only. Open
- KNOWN_AIRPORTS is hand-curated; obscure cities show hotels but no flights.
global reach.
search shows listings only, no editorial.
Honest UX, no fabricated airport guesses.
2026-05-19 (afternoon)
Added: Apartment + villa filter on /listings (default for extended-stay focus)
This is a major positioning shift. Before today, /listings?city=lisbon returned 20 hotels because we never filtered LiteAPI's inventory by property type. LiteAPI actually has 52 property types: apartments, villas, holiday homes, condos, country houses, gites, chalets, cottages, even houseboats and castles.
Per Decision S21, /listings now defaults to property_types=extended_stay, which filters to apartment-style accommodations appropriate for 7+ night stays: Apartments, Residences, Villas, Aparthotels, Holiday homes, Homestays, Country houses, Chalets, Condos, Cottages, Gites, Riads, Vacation homes, Cabins, Houseboats, Castles, Palaces, Guest houses
Live results:
- Lisbon now returns real apartments: Lisbon Art Stay, Martinhal, Lisbon
- Bali returns real villas: Aleesha Villas, Villa D'Carik Bali, Sorrento
- Each card shows a property type badge: "Apartment", "Villa", "Holiday home"
Colours Bairro Alto, Almaria Ex Libris (instead of just hotels)
Villa, Villa Reina, Luxury Nanda Villa Ubud
Backend (sources/liteapi.py):
HOTEL_TYPE_LOOKUP(52 entries from/v3.0/data/hotelTypes)EXTENDED_STAY_TYPE_IDS,HOTEL_ONLY_TYPE_IDS,PROPERTY_TYPE_SETSget_hotels_in_city()accepts hotel_type_ids list, passes asnormalize_hotel()includeshotel_typeandhotel_type_id
comma-separated hotelTypeIds to LiteAPI server-side filter
Backend (routes/listings.py):
- Accepts
property_typesquery param (extended_stay | hotels | all)
Frontend (/search.astro):
- Property type badge above each hotel name (amber pill, e.g., "Apartment")
singularPropertyType()helper converts plural ("Apartments") to
singular ("Apartment") for display
Documented: Uber + eSIM addons (S22, deferred to V2)
LiteAPI supports attaching Uber vouchers ($10-$100 increments) and eSIM data packages to bookings via addons array during prebook. Customer pays on top of the room rate; non-refundable. Documented in Decision S22 with the full implementation spec for when V2 booking flow lands. Not building tonight; the manifesto is delivered at V1 without addons.
URLs to test
https://weeklyescapes.com/search?origin=LAX&destination=lisbon— apartments + guest houseshttps://weeklyescapes.com/search?origin=LAX&destination=bali— villas + guest houseshttps://api.weeklyescapes.com/listings?city=lisbon&property_types=hotels— opt into hotels onlyhttps://api.weeklyescapes.com/listings?city=bali— defaults to extended_stay (villas)
2026-05-19 (morning)
Added: Exclusive Rates + Perks + Promotions support (graceful empty states)
LiteAPI offers three additional feature surfaces beyond standard rates:
- Exclusive Rates: privately negotiated hotel prices with strikethrough original-vs-discounted display (
retailRate.initialPricevsretailRate.total) - Exclusive Perks: value-added benefits (breakfast, upgrades, property credits) tied to loyalty tiers
- Promotions: campaign metadata with discount %, date range, name (e.g., "Early Booker Deal")
Per Decision S20 in decisions-log.md, we now extract and display all of these on every rate. Currently the response fields are empty (LiteAPI account manager needs to enable Exclusive Rates + Perks for our account), but the implementation is in place so that the moment the switches flip, the badges and perks list appear automatically without a code change.
Backend (sources/liteapi.py normalize_rate):
- Extracts
initialPrice,promotions,perksfrom each rate - Computes
is_exclusive(when initialPrice > total) - Computes
exclusive_savings+exclusive_savings_pct - Computes
perks_total_value(sum of all perksamountfields) - Top-level
guest_levelfromguestLevelpassed through
Frontend (/search.astro buildRateBlockHtml):
- "★ Exclusive rate" amber badge when
is_exclusive: true - Strikethrough original price next to discounted total
- "Save $X (Y%) with [Promotion Name]" line when promotions populated
- Perks checklist with total value: "Included perks ($220 value): ✓ Daily breakfast for 2 ($40 value), ✓ Room upgrade ($60 value), ..."
- Empty states render cleanly (no orphan headers when perks/promotions absent)
Frontend (/book/test.astro step 1 output):
- Shows all new fields in the test JSON output for visibility while debugging
Action item for the user
Email your LiteAPI account manager to enable: 1. Exclusive Rates for our account 2. Exclusive Perks / Loyalty Program with guest tiers and per-tier perks
Both are eligibility-gated. Once enabled, the savings badges and perks lists appear automatically on /search hotel cards.
2026-05-18 (late late evening)
Added: V1.5 booking flow with LiteAPI User Payment SDK (SANDBOX ONLY)
Implements the full LiteAPI booking flow on weeklyescapes.com using their User Payment SDK, where the customer enters their card on our page (in their iframe) and Nuitee/LiteAPI is the merchant of record. This is per Decision S19 in decisions-log.md.
Tonight: sandbox-only deployment. Production cutover is deliberately deferred to a fresh session tomorrow. We never want to ship a payment-taking code path written tired.
Backend (Lambda v0.5.0-sandbox):
- New endpoint:
POST /book/prebook - New endpoint:
POST /book/finalize - Both default to
mode: sandboxfor safety - LiteAPI client extended with
prebook()andfinalize_booking()plus mode-aware /listings/ratesextended withmodeparameter for sandbox testing chain
- Body: {offer_id, mode} - Calls LiteAPI /v3.0/rates/prebook with usePaymentSdk: true - Returns {prebook_id, transaction_id, secret_key, hotel, room_types, ...}
- Body: {prebook_id, transaction_id, holder, guests, mode} - Calls LiteAPI /v2.0/rates/book with payment.method: TRANSACTION_ID - Returns {booking_id, confirmation_number, hotel, ...}
key selection (liteapi-sandbox-key SSM param vs liteapi-key)
Frontend:
/book/test.astro— hardcoded sandbox test booking flow/book/confirm.astro— booking finalization page
- Prominent SANDBOX MODE banner at top - Step 1: fetch sandbox rate for Meliá Lisboa (4 nights) - Step 2: holder details form (pre-filled with test data) - Step 3: LiteAPI payment SDK loads in our page (iframe, we never touch cards)
- Reads tid + pid from URL params (set by SDK after payment) - Reads holder/guest details from sessionStorage - Calls /book/finalize to confirm booking - Shows confirmation page with booking number, dates, total, supply chain disclosure - Honest "what happens next" block explaining Nuitee = merchant of record
Verified end-to-end (curl):
POST /book/prebookwith sandbox offer_id returns valid prebook_id, transaction_id, secret_key- Sandbox key separate from prod (so /listings + /listings/rates keep using prod for real users)
Manual test still pending (requires browser):
- Full flow with test card 4242 4242 4242 4242 from /book/test through SDK
payment to /book/confirm finalization. This is the next step.
Production cutover plan (tomorrow):
- Switch DEFAULT_MODE in routes/book.py from "sandbox" to "production"
- Update /book/test or build /book customer-facing page with prod mode
- Wire "Book this stay" button on /search top 5 hotels
- Test with own card on real low-cost hotel (cancellable rate)
- SES production access for confirmation emails (request now, lands in 24-48 hrs)
2026-05-18 (late evening)
Added: V1 trip planner with live LiteAPI rates + total trip cost
The /search rebuild now ships the full manifesto promise: real total trip cost, real savings vs competitors, real commission disclosed per result.
Backend changes (Lambda v0.4.0):
- New endpoint:
POST /listings/rates - LiteAPI client extended with
get_hotel_rates()andnormalize_rate() - Health endpoint reports both GET and POST endpoints
- Body: {hotel_ids, check_in, check_out, adults, currency} - Calls LiteAPI /v3.0/hotels/rates and normalizes the response - Returns per hotel: lowest_total, lowest_per_night, currency, supplier, room_name, board_name, competitor_price (booking.com), competitor_source, savings_vs_competitor, commission
Frontend changes:
- After
/listingsresolves, frontend takes top 5 hotels by rating, fires - Top 5 hotel cards show "Loading live rate from LiteAPI…" skeleton, replaced
- Trip header gains an estimated total trip cost panel: flight cost + cheapest
- Honest commission line: "We earn $297.18 commission if you book this stay
- For the bottom 15 hotels (no rates fetched), keep V0 metadata + Google
POST /listings/rates for those 5 in a background fetch
with real per-night + total + competitor comparison + savings + commission
stay cost, with savings vs booking.com when applicable
(5.7%)." Real number, not estimate
Hotels "Compare rates" link with V0 disclosure
Real numbers from the live site (LAX → Lisbon, 30 nights, 2 adults):
- Meliá Lisboa Aeroporto: $175.01 / night, $5,250.25 total
- Booking.com price for same room: $6,260.68
- Savings: $1,010.43 (16.1%)
- Our commission: $297.18 (5.7%)
V1.5 (next): wire booking flow to LiteAPI whitelabel. Currently "Compare rates →" still links to Google Hotels; we earn LiteAPI commission only once we have the booking flow integrated. Disclosure makes this clear.
2026-05-18 (evening)
Added: /search rebuild as combined trip planner (V0)
Replaced the flight-only /search with a unified trip planner showing both flights and housing for the same trip. Per Decisions S17 (frontend-combined architecture) and S18 (hybrid rates strategy: V0 metadata, V1 top-5 rates) in decisions-log.md.
What's live:
- Form: From (3-letter IATA) + To (10 city dropdown) + Check-in + Check-out + Adults
- Parallel fetches to
/flightsand/listingson submit - Trip header: "LAX → Lisbon, Aug 1 to Sep 1, 31 nights, 2 adults"
- Flight section: cheapest cached price (real), airline, duration, commission disclosure (~1.5% Travelpayouts), "Book on Aviasales →" with marker 729501
- Hotel section: 20 LiteAPI cards with photo, name, stars, rating, review count, address, description preview, "Find rates →" linking to Google Hotels search
- Honest V0 disclosure: "No commission yet on this link, partnerships pending" (because CJ Booking.com is in flight and LiteAPI whitelabel isn't wired yet)
- Mobile responsive, manifesto block at bottom
What's V1 (next session):
- New
POST /listings/ratesendpoint for top-5 hotels (single LiteAPI rates call, ~3s) - Inline per-night and total stay prices for top 5
- Calculated total trip cost = flight + cheapest stay
- Real commission amounts for hotels once we have rates
Spec changes documented
- decisions-log.md: Added S17 (frontend-combined trip planner) + S18 (hybrid rates strategy)
- requirements.md: Non-goal "Flight search / booking" replaced with finer-grained non-goals. Flight booking on weeklyescapes.com itself remains out of scope (we always redirect). Flight search as the primary product remains out of scope (housing is primary). Flight prices alongside housing for total trip cost transparency is now in scope.
- tasks.md: Task 7 rewritten with V0 + V1 task breakdown
- research-log.md: Documented brainstorm research (10 web searches, LiteAPI docs deep read, lastminute.com architecture article, Hipmunk failure analysis, Going.com history)
Backend change
- LiteAPI city lookup (
infra/lambda/api/sources/liteapi.py) extended withairportfield per city. Frontend uses this to map destination city slug to flight destination IATA automatically.
2026-05-18 (afternoon)
Added: /api/listings endpoint with real hotel data
Built /listings Lambda endpoint backed by LiteAPI. Returns real hotel inventory for our 10 launch cities (Lisbon, Porto, Mexico City, Bangkok, Chiang Mai, Bali/Denpasar, Medellín, Tbilisi, Buenos Aires, Cape Town).
Each result includes: hotel name, address, star rating, guest rating, review count, coordinates, main photo URL, description preview. Source: LiteAPI (sandbox key, but returns real production hotel data for content; sandbox applies only to bookings).
Live examples: curl https://api.weeklyescapes.com/listings?city=lisbon&limit=3 curl https://api.weeklyescapes.com/listings?city=bangkok&limit=5
Refactored Lambda from single-file to proper package
Lambda code now structured as:
infra/lambda/api/
├── index.py # entry point, dispatches to routes
├── routes/
│ ├── health.py
│ ├── flights.py
│ └── listings.py
├── sources/
│ ├── travelpayouts.py
│ └── liteapi.py
└── lib/
├── http.py # response helpers (json_response, error_response)
└── ssm.py # cached parameter retrieval
This is the production pattern, not research-grade single-file. Each endpoint stays under 100 lines, sources are testable in isolation, shared concerns (HTTP, SSM) live in lib/.
Updated IAM policy
Lambda now has SSM read access to BOTH:
/weeklyescapes/affiliates/*(existing)/weeklyescapes/hotel-apis/*(new, for LiteAPI key)
Bumped API version
/healthnow reports v0.3.0- Lists all three endpoints: /health, /flights, /listings
2026-05-18 (Day 1 continued, late night)
Added
/flightsendpoint at api.weeklyescapes.com, returns cheapest flight prices- API Lambda code moved from inline to
infra/lambda/api/index.py. - IAM policy: Lambda can now read
/weeklyescapes/affiliates/*from SSM. - API version bumped to 0.2.0.
via Travelpayouts API. Token kept server-side, only formatted results returned to client.
Verified working
GET /flights?origin=LAX&destination=LISreturns real flight data (~$794)GET /flights?origin=JFK&destination=CDGreturns real flight data (~$431)- Token authentication via
X-Access-Tokenheader (server-side only) - Validation errors return helpful messages
- 5-minute Cache-Control on responses
Affiliate signups
- CJ Affiliate publisher account approved (PID: 7961481)
- Applied to 6 CJ advertisers: Booking.com, Hotels.com, Priceline, Travelex,
- Travelpayouts signup complete, API token verified working
- Coliving slug confirmed: nick-f-4
- Outsite application submitted via Refersion (pending review)
- Email sent to support@travelpayouts.com requesting Hotel Search API access
TripAdvisor Commerce, CheapOair (pending advertiser approval, 1-7 days)
Infrastructure (NFLO Marketing LLC business setup)
- Mercury bank account application started
- LLC business info documented for affiliate signups
Secrets in SSM (us-east-2)
- /weeklyescapes/affiliates/cj-pid (7961481)
- /weeklyescapes/affiliates/travelpayouts-token (verified)
- /weeklyescapes/affiliates/travelpayouts-marker (729501)
- /weeklyescapes/affiliates/coliving-slug (nick-f-4)
Documentation (gitignored, local-only)
docs/spec/travelpayouts-api-reference.md, full API endpoint catalog by.secrets/cj-affiliate-agreement.md, CJ publisher agreement TL;DR
access tier, auth patterns, rate limits, /search architecture
API endpoint discovery
Working without application:
- /v1/prices/cheap (used by /flights)
- /aviasales/v3/grouped_prices (calendar of cheap flights by date)
- /finance/v2/get_user_balance (for /stats real revenue display)
- /data/cities.json (full airport database)
Gated, application sent:
- Hotel Search API (real-time hotel prices), 9% conversion threshold,
approval typically 2-4 weeks
Out of reach for now:
- Aviasales Real-time Search API requires 50k MAU minimum
Format: Keep a Changelog inspired but adapted for indie SaaS pre-launch tracking.
Updates flow into the public /changelog page eventually (per transparency-framework.md).
---
[Unreleased] — 2026-05-17
Added — afternoon updates
- Google Workspace email setup
- Added weeklyescapes.com as a User Alias Domain for virtualhomezone.com (free, no extra license) - Added Google verification TXT record to Route 53 - Swapped MX records: removed ImprovMX (10/20 priority), added 1 smtp.google.com. - Updated SPF: v=spf1 include:_spf.google.com ~all - Added DKIM record at google._domainkey.weeklyescapes.com (2048-bit RSA, properly chunked into 250+158 char strings) - Configured Gmail "Send mail as" for nick@weeklyescapes.com (verified) - Effect: can send + receive from @weeklyescapes.com addresses through main Gmail inbox - ImprovMX decommissioned — Google Workspace handles all email now
- Coliving.com partnership outreach
- Email sent to partners@coliving.com from nick@weeklyescapes.com - Subject: "Coliving.com partnership inquiry" - Asks: production API access, confirmation of 50% rev-share, co-marketing once traction - Offers: SEO pages, qualified high-intent traffic, public case study, designed integration - Lead time: typical 1-3 weeks for partnership replies - Follow-up reminder: 7 business days if no response
Built today (Day 1 of building)
Strategy & spec (~7,500 lines, 17 docs)
manifesto.md— soul of the project: "give money back to people, make corporations pay"research-process.md— research-driven decision methodology with N≥3 working/failing examplesresearch-log.md— every research session trackeddecisions-log.md— 16 documented decisions (S1–S16) with citationsbusiness-model-analysis.md— pricing model with full pros/cons + DMAI frameworkbrand-style-guide.md— visual identity locked (colors, typography, voice, anti-palette)brand-assets.md— single source of truth for domain, social handles, email- Updated: README, requirements, design, tasks, integration-strategy, monetization-setup, transparency-framework, validation-evidence
Domain & DNS
- Registered
weeklyescapes.comvia Route 53 ($13/year, auto-renew on, privacy enabled) - Hosted zone:
Z07606942A3I74LM0DCGL - Email forwarding via ImprovMX (free): catch-all
*@weeklyescapes.com→nsflournoy@gmail.com
Social handles claimed (4/5)
- ✅ X (Twitter):
@weeklyescapes - ✅ Instagram:
@weeklyescapes - ✅ Bluesky:
weeklyescapes.bsky.social - ✅ Reddit:
u/weeklyescapes - ⏳ TikTok: pending verification code issue
AWS infrastructure deployed (5 stacks)
weeklyescapes-data— DynamoDB single-table with PITR + GSI1weeklyescapes-api— Lambda + API Gateway HTTP API + custom domainweeklyescapes-frontend— S3 + CloudFront (us-east-1) + Route 53 aliasweeklyescapes-messaging— SES domain identity with DKIMweeklyescapes-monitoring— CloudWatch budget alarms ($25 / $50)
Live URLs
- https://weeklyescapes.com — placeholder with manifesto quote
- https://api.weeklyescapes.com/health — returns
{"status":"ok","version":"0.1.0"}
X API integration
- X developer account approved
- 7 tokens stored in AWS SSM Parameter Store as
SecureString(encrypted, free tier) - Path:
/weeklyescapes/x/* - OAuth 1.0a verified working (authenticated as
@weeklyescapes) - Bearer token valid (free tier endpoint limits expected)
Brand identity
- Color palette locked: Ink
#0f172a, Cream#fafaf7, Amber#d97706 - Typography locked: Inter (body + headlines), Fraunces (editorial), JetBrains Mono (data)
- Logo SVGs created (4 variants): wordmark, wordmark-horizon, monogram, favicon
- PNG exports for social profile pictures (400×400, 1024×1024, 180×180 Apple touch, 32×32 favicon)
Code repository
- Git initialized; SSH deploy key configured for
weeklyescapes/weeklyescapes - All work pushed to https://github.com/weeklyescapes/weeklyescapes
- Comprehensive
.gitignoreprotects.secrets/,.venv/,cdk.out/,node_modules/, env files - Audited: no leaked AWS keys, no leaked credentials in tracked files
Tooling installed
- AWS CDK 2.1122.0 (local, ~/.local/npm/bin)
- Python deps: cairosvg, requests-oauthlib, boto3 (in workspace .venv)
Decisions committed today (S1–S16)
See docs/spec/decisions-log.md for full reasoning + research citations.
| ID | Decision | Status | |---|---|---| | S1 | Sequenced launch (weeklyescapes → mistfare → pointssearch) | Active | | S2 | Family Slowmad as secondary persona | Active | | S3 | TikTok as Channel 1 (1-2 high-quality videos/week) | Active | | S4 | No cold-email host outreach (legal/brand risk) | Active | | S5 | Cross-platform comparison engine (Phase 2) | Active | | S6 | Watchlist as v1 of mistfare | Active | | S7 | "Anywhere" search as v1 of weeklyescapes | Active | | S8 | Multi-passenger optimization in pointssearch v1 | Active | | S9 | Real-time public stats counters | Active | | S10 | Auth: Clerk + social OAuth + passkeys | Active | | S11 | B2B Corporate Travel Partnership (Year 2+, OBA-gated) | Roadmap | | S12 | Frontend: Astro 6 hosted on AWS S3+CloudFront | Active | | S13 | Payments: Paddle as Merchant of Record | Active | | S14 | Pricing: Hybrid (free + $49/yr Pro + B2B) | Active | | S15 | Subscriber Stipend (sponsor-funded) | Year 1.5+ | | S16 | Two-track inventory (consumer = all sources, B2B = policy-compliant only) | Active |
---
How to update this file
When you make a meaningful change: 1. If it's substantive (decision, deploy, new asset), add a bullet under [Unreleased] 2. When we ship a real version (v0.1.0+), move the unreleased items into a versioned release section 3. The public /changelog page on weeklyescapes.com pulls from this file
Keep the entries factual and dated. Per the manifesto: show our work.
Want to know what's coming? See /decisions for major upcoming choices, or /building for daily progress.