Skip to content

Fix: Restored storefront highlighting and Early Access banners after Steam markup changes - #2372

Open
Guswut wants to merge 5 commits into
IsThereAnyDeal:developfrom
Guswut:fix/storefront-markup-2026
Open

Guswut wants to merge 5 commits into
IsThereAnyDeal:developfrom
Guswut:fix/storefront-markup-2026

Conversation

@Guswut

@Guswut Guswut commented Aug 23, 2026 •

Copy link
Copy Markdown

Steam's big June update broke some of the waitlist/wishlist/etc highlighting. I took a look and couldn't figure it out myself back in June but I recently had some spare usage with Claude so I had it take a look. It was able to figure out the issues and it is looking good to me now when testing on Firefox.

Also looks like this got skipped for the 5.0.0 release so I updated it to make sure everything was still good to go there.

Anyways, here is what Claude wanted me to paste in here which is way more informative than what I've got to say and likely way more useful haha:


Steam's 2026 storefront redesign renamed or replaced several capsule classes, which silently disabled highlighting, tagging and Early Access banners for most of the front page. This PR restores them. It is rebased onto v5.0.0 with no conflicts.

Highlighting and tagging

  • .sale_capsule was unknown to the selector list, so only legacy daily deals (.store_capsule) worked.
  • .home_area_spotlight no longer contains .spotlight_content, so the node to highlight was null and the highlight was dropped with no error. Fall back to .spotlight_bottom_ctn.
  • Storefront item rows are now .tab_row_item (.tab_item_details became .tab_item_content). Updated the selector, tag placement and the top sellers observer.
  • Added .community_recommendation_capsule (its <a> is covered by its image, so the parent is highlighted).
  • New: "Discounts & Events" and "Your Personal Calendar" are now rendered client-side by React with build-generated class names, and the Discounts & Events tiles no longer carry data-ds-appid. Both are matched through their stable hooks instead:
    • Discounts & Events: .DiscountsAndEventsReady a[href*="/app/"] (the app id is already read from the link's href), with tags placed in the tile's price block.
    • Personal Calendar: .personal_calendar_ctn [data-ds-appid]. Its tiles are bare images, so they get an outline in the highlight colour and no tag.
    • Both sections render after load and re-render slides as the carousel moves, so CStoreFront observes for new tiles. Tiles already handled are skipped via es_highlight_checked.

Early Access banners

  • Updated the selector list for .sale_capsule and .tab_row_item.
  • Key the capsule layout on the image (img.sale_capsule_image) rather than the capsule's classes, since daily deals have been served with both layouts.
  • Added a layout rule so the banner container stands in for the original layout and capsules keep their height.
  • Made the :has() selector valid after Svelte scoping.

Testing

Checked on a signed-in storefront in Firefox with a production build. Early Access capsule heights were compared against untouched capsules, and the ignored-game state was checked as well. tsc --noEmit passes. Highlighting uses DynamicStore data, which is fetched by the background page. Wishlist/owned highlights therefore need a Steam login in the default cookie jar. Inside a Firefox container, the background page sees an anonymous session and only ITAD-based (waitlist/collection) highlights appear. That is existing behaviour, not caused by this PR, and I've left it alone.

Not covered

  • Tag placement for a few capsule types.
  • specials/, whose markup I haven't re-checked.

🤖 Generated with Claude Code


@Guswut
Guswut force-pushed the fix/storefront-markup-2026 branch 2 times, most recently from c0716d6 to 23752f5 Compare August 23, 2026 18:52
Guswut and others added 5 commits October 8, 2026 10:53
…hanges

Steam's storefront redesign renamed several capsule classes and removed a
node AS highlighted, which silently disabled highlighting and tagging for
most of the front page.

- "Discounts & Events" carousel items are `.sale_capsule`; only the legacy
  daily deals also carry `.store_capsule`, so they were the only ones that
  still worked. Added `.sale_capsule` to the selector.
- `.home_area_spotlight` no longer contains `.spotlight_content`, so
  `nodeToHighlight` was null and the highlight was dropped with no error.
  Fall back to `.spotlight_bottom_ctn`, keeping the old node for
  compatibility.
- Storefront item rows are now `.tab_row_item` (`.tab_item` matches nothing),
  and `.tab_item_details` was replaced by `.tab_item_content`. Updated the
  selector, the tag container placement, and the top sellers observer.
- Added `.community_recommendation_capsule`. Its <a> is fully covered by its
  image, so the parent is highlighted instead, matching how other
  image-only capsules are handled.

On a signed-in storefront this takes the number of items carrying a store id
that are never checked from 107/211 to 2, both of which are `ds_no_flags`
navigation buttons that are correctly skipped.

The React-based sections (Personal Calendar, specials/) are still
unsupported; their class names are build-generated hashes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Early Access selector list carried the same stale class names as the
highlighting one, so no banner was shown on the storefront's carousel
capsules or item rows. Added `.sale_capsule` and `.tab_row_item`.

`.sale_capsule` also needs a layout rule of its own. The component moves the
capsule's own image into `.es_overlay_container`, which drops any Steam rule
that positioned that image through a child combinator, so each capsule type
needs the container to stand in for however Steam had laid that image out:

- `.store_capsule` positions its image absolutely inside a percentage-padding
  ratio box, which is what the existing absolute rule compensates for. That
  rule is left untouched.
- A `.sale_capsule` on its own is the opposite: its image is in flow and gives
  the capsule its height, so the container has to stay in flow too, or the
  capsule collapses to the height of its price bar.
- The daily deals carry both classes and need the `.store_capsule` treatment,
  hence the `:not(.store_capsule)`.

`.tab_row_item` needs no rule, matching the `.tab_item` it replaces.

Verified on a signed-in storefront by comparing every Early Access capsule
against untouched capsules sharing its class signature: heights and image
offsets match in all three cases (`store_capsule+sale_capsule` 193px,
`sale_capsule` 160-276px, `tab_row_item` 76px, image offset 0 throughout),
and all 20 banners sit at their capsule's top left corner.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…lasses

The previous fix treated `.sale_capsule:not(.store_capsule)` as the in-flow
case and gave `.store_capsule` the absolute ratio-box treatment. The daily
deals carry both classes but Steam now lays their image out in flow, so the
absolutely positioned overlay container left nothing to give the capsule
height: Early Access daily deals collapsed to their 34px price bar and the
carousel row below them was dropped.

Key the in-flow rule on the container holding `img.sale_capsule_image`
instead, which is correct for whichever layout Steam serves.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Svelte 4 leaves `:global()` literally in the output when it is nested inside
`:has()`, producing an invalid selector that the browser drops whole. Wrap the
`:has()` in `:global()` instead so it compiles to `:has(>img.sale_capsule_image)`.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… Calendar" sections

Steam now renders both storefront sections client-side with build-generated
class names. "Discounts & Events" tiles lost data-ds-appid, so none of the
selectors matched and nothing was highlighted or tagged there.

- "Discounts & Events": match the component's own stable class plus the
  `/app/` link in each tile (the app id is already read from the href), and
  place tags in the tile's price block.
- "Your Personal Calendar": tiles keep data-ds-appid, so key on the stable
  `.personal_calendar_ctn` container. They are bare images, so highlight with
  an outline instead of a background and skip tags.
- Both sections render after load and re-render slides as the carousel moves,
  so CStoreFront observes for new tiles; already-processed ones are skipped
  through es_highlight_checked.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@Guswut
Guswut force-pushed the fix/storefront-markup-2026 branch from 2161660 to 924e7e3 Compare October 8, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant