Thanks for taking the time to write all that up OnlineProxy! Genuinely appreciate the review. It actually pushed me to go through the article with a fine comb and fix a bunch of stuff. I updated the article based on your feedback. It now has a full Known Limitations section covering CSP, JWT expiry, persisted queries, and the single-user constraint. The What I Learned section also calls out schema versioning as the real maintenance headache, which you were spot on about. Credited you where relevant, so people know where those improvements came from. That said, a couple things you mentioned don't actually apply here, and I want to clear them up so the record is straight. Cursor invalidation in localStorage recovery. There's no cursor logic in this code at all. Expedia uses offset-based pagination through selPageIndex and selPageCount inside a selections[] array, not cursor tokens. The loadMoreAction returns startingIndex and hasNextPage, and the dedup key is searchId:startingIndex. So there's no cursor to invalidate, and no edge case around one. The localStorage recovery just timestamps the snapshot and drops it after 1 hour, nothing more. Duck-typing. I wish. The fetch hook checks requestBody.operationName !== "CarSearchV3", which is a hard string match on the operation name. That's the opposite of duck-typing. If Expedia ships CarSearchV4 tomorrow, it breaks. No shape inference happens. The article originally described it as shape matching (which was wrong), and I fixed that too in this revision. Dedup overhead. It's a Set of string keys tested with .has(). A Set lookup is O(1) average. For a worst case of 2500 items (100 pages x 25 listings, the hard cap), we're talking microseconds per check. Even at a hypothetical 5000+ items, this would never be the bottleneck. The delays between requests (600ms to 7s depending on speed setting) dominate the runtime by many orders of magnitude. I appreciate the engineering rigor, but this one is safe. GraphQL operation name changes being rare. That one you got right. V3 to V4 would be a big deal and I'd catch it immediately. But your real point about schema field mutations is what I took to heart. If Expedia renames priceSummary.total.price.amount to something else, the CSV export silently produces empty columns. That's now flagged in the article. So thanks again. Your comment helped make the article more honest about what this tool can and can't do. Even where you swung and missed (cursor invalidation, duck-typing), it made me double check my own assumptions and fix genuine inaccuracies in the writeup. Appreciate it.
