c6b56a22026-06-01/api/facets now drill-down counts over the active filtered set via shared filterProducts() (was counting whole niche catalog regardless of q/aesthetic/vendor; /api/products reuses helper) + 301 redirect legacy /*.html -> clean URLs (before express.static) + 404-guard for stray .bak/.pre-*/.orig backup files
489d7152026-05-30remove leaked backup file from public/ and fix .gitignore to cover *.bak-* pattern
934b57b2026-05-29feat(fleet): theme1/theme2 query-param-gated toggle on catalog page
6a0e7182026-05-28scrub vendor name leaks from products.json source (18 products: title/vendor/tags cleaned per sku-redact denylist)
9bac1292026-05-13remove stray contact modal markup that was rendering inline on the page
ae446c92026-05-13header: remove duplicate <header> with dwmOpen-contact (was overlapping ns-header) + add display:none default to .ns-modal so How-can-we-help only opens on click. Restores canonical logo-UL + hamburger-UR layout per MEMORY rule.
Commits with substantial prose (≥120 chars) — the rationale behind each move.
489d715 · 2026-05-30 · remove leaked backup file from public/ and fix .gitignore to cover *.bak-* pattern
public/index.html.bak-20260526152130 was being served by express.static — removed.
Added *.bak-* and *.orig patterns to .gitignore (existing *.bak.* missed hyphen-dated backups).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Default: theme1, toggle hidden. Opt-in via ?theme=2 or localStorage
('wallco-page-theme' key shared across the fleet). Same gate pattern
as dw-domain-fleet productPage.
- Wired buildRails/railFacets from ../_shared/rail-match.js into /api/sliders + /api/facets
- Replaced aspirational aesthetic-only rails (fine/heavy/dyed/metallic/blended) with 6 tag-matched buckets: grasscloth, sisal, beige, woven, natural texture, textured (54–82% hit rates)
- Added editorial LABELS for all 6 new keys in public/index.html
- Result: 6 rails fire (was 0), each capped at 12 items
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fleet rails sweep A3 — adds the canonical DW rail-sections pattern from
retrowalls (per LEDGER 2026-05-26 correction note). Renders rails from
/api/sliders ABOVE the flat grid on the unfiltered '/' home view; hides
itself when state.q or state.facet !== 'all'. Clicking 'View all -> on a
rail title calls state.facet=aes + resetGrid + scrollIntoView('#shop')
which is the canonical jumpToFacet behavior. Patch is 3 pieces:
(1) <div id='rails' style='display:none'></div> before <div id='grid'>
(2) .rail-section/.rail-head/.rail-all/.grid.rail-grid CSS
(3) async renderRailSections() fn + startup call right after loadGridPage().
Coexists cleanly with the existing 2-rail Ideas block above (which renders
'New this week' + 'Curated picks' from /api/products and survives in any
filter state).
4e2dc09 · 2026-05-25 · hydrate sort from localStorage pre-grid-load + noreferrer on Facebook target=_blank
- move sort restore into the pre-load view-hydration IIFE so the initial
/api/products fetch fires with the user's saved sort instead of 'newest'
(was racing with the post-DOM sort-select wire-up at line 1049)
- add noreferrer to the Facebook footer link (tab-nabbing + referer-leak
defense; pairs with existing rel=noopener)
- mount _shared/api-vendor-redact before /api/* routes so /api/facets stops
emitting vendors map and /api/products stops accepting ?vendor= filter
- replace p.vendor literal in hydrateIdeas rail-card with 'Designer Wallcoverings'
to match the rest of the storefront (defense-in-depth alongside the middleware)