Skip to content

[demo] Big Enterprise#224

Draft
laugharn wants to merge 48 commits intomainfrom
demos/2026-04-29-ent
Draft

[demo] Big Enterprise#224
laugharn wants to merge 48 commits intomainfrom
demos/2026-04-29-ent

Conversation

@laugharn
Copy link
Copy Markdown
Contributor

Summary

  • Adds the custom.reviews metafield to the product fragment and parses it ({rating, count} shape, also accepts value/average + total/rating_count, normalized to a 0–5 scale).
  • New ProductRating component renders 5 lucide stars with a percentage-clipped yellow overlay above a gray base layer, plus the formatted review count.
  • Placed inside data-slot="product-info-header" directly above the <h1>. leading-none keeps the stars flush against the title with no gap.
  • When reviews data is missing the component still renders 5 grayed-out stars at the same dimensions (count hidden), so the title position stays stable — the fallback shell matches the hydrated size.

Test plan

  • Lint + tsc clean
  • Visual check on a PDP without custom.reviews populated: 5 grayed stars rendered flush above the title, no console errors
  • Simulated populated state via DOM injection: yellow fill respects rating percentage with a partially-filled trailing star, count renders as (247)
  • Populate custom.reviews JSON on a real Shopify product and confirm it lights up end-to-end

🤖 Generated with Claude Code

Reads the `custom.reviews` JSON metafield (rating + count, also accepts
value/average + total/rating_count, normalized to a 0–5 scale) and renders
five lucide stars with a percentage-clipped overlay for fractional fills.
Component always reserves the same dimensions; when reviews data is
missing, all five stars stay grayed out and the count is hidden so the
title position is stable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 29, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
shop-docs Ready Ready Preview, Comment May 1, 2026 3:58pm
shop-template Error Error May 1, 2026 3:58pm

…on PDP

Conflict in apps/template/lib/shopify/fragments.ts resolved in favor of
main (drops the metafields(identifiers:[...]) block from PRODUCT_FRAGMENT).
The custom.reviews-driven rating UI is preserved by reading from a new
getProductReviews(handle) server fetcher in lib/reviews/server.ts that is
'use cache' + cacheLife("max") and returns { rating: 3.00–5.00, count }.
PDP page kicks off reviewsPromise alongside productPromise and threads it
down through ProductDetailPage to ProductDetailSection.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Top nav: Shop (mega menu with 5 columns — Featured, Apparel, Footwear,
Accessories, Home), Lookbook, Stores. Footer: 5 columns — Shop, Help,
About, Connect, Legal. All URLs are "#" so this is purely structural
demo content for the demos/2026-04-29-ent branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Rename "Vercel Shop" → "Hausu" across storefront strings (siteConfig
  default, layout generator, about page, agent system prompt, footer,
  i18n messages). README left as-is since it documents the project.
- Add Bricolage Grotesque via next/font/google and register
  --font-display in @theme inline so font-display becomes a Tailwind
  utility (font-family: var(--font-bricolage)).
- Apply font-display to storefront-visible headings: nav brand, product
  card title, PDP h1s, footer column titles, mega-menu column titles,
  page headers (account, cart, search, collections, not-found),
  section headings (slider, products grid, related products), banner.
- BuyButtons grid now grid-cols-10 with col-span-4 on Buy with Shop and
  col-span-6 on Add to Cart (matching changes in the suspense fallback
  inside ProductDetailSection).
- Apply rounded-lg to color swatch wrapper + image to match the CTA
  button rounding.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
--link is #0011ff (just shy of #00f) and registered through
--color-link in @theme inline so the text-link Tailwind utility is
available. Prose anchors (currently used on the About page) pick it
up via @layer components alongside the existing heading override.

Nav and footer links keep their bespoke styling — they aren't body
content and shouldn't shout for attention with a vibrant blue.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Pair the existing --link token with --link-foreground (white) so
  text-link-foreground exists for white-on-blue contrast in CTAs.
- Nav: top-level QuickLinks, mega-menu column titles + leaves all use
  text-link with hover:opacity-70 (replacing muted/foreground tones).
- Mobile menu: top-level, accordion trigger, nested column + leaves,
  and "Show all X" footer link all use text-link.
- Footer: column title links and leaves use text-link. Headings (when
  no url) stay neutral — they aren't links.
- CTAs (Add to Cart, Checkout, Continue Shopping in not-found / empty
  cart / cart overlay, View full cart) swap bg-foreground/text-background
  for bg-link/text-link-foreground.
- Banner section button: white-on-dark → bg-link/text-link-foreground.

Buy with Shop is intentionally left on its Shopify purple, since that's
the merchant's brand color, not ours.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
laugharn and others added 2 commits April 29, 2026 10:00
- --link: #0011ff → #0a1f4b (navy). Cart count badge moves with it via
  bg-link/text-link-foreground.
- Brand wordmark, search trigger, account icon (auth + unauth), account
  fallback, cart icon (live + fallback), and mobile menu trigger all use
  text-link with hover:opacity-70.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A new h-8 bg-link strip in the layout reads x-vercel-ip-postal-code via
a Suspense boundary with no fallback — the static "Shipping to " label
renders instantly and the postal code streams in once the request
reaches the server. The header is declared on every unstable_instant
sample (products, collections, search) so prefetched placeholders are
aware of the read.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Section grid changed from lg:col-span-6/4 to lg:col-span-5/5 so the
  media and info columns share the row evenly.
- Replaces the desktop 2-column gallery with a single featured image and
  a vertical thumbnail column on the left. Selecting a thumbnail swaps
  the featured image; the featured image keeps its lightbox-on-click.
- Mobile snap carousel is unchanged.
- ProductMedia API simplified to a flat MediaItem[] list. Color image
  partitioning is now resolved server-side in a Suspense boundary
  (ResolvedMedia) so the gallery's items don't reorder mid-stream — the
  page-level skeleton + section-level skeleton match the new shape.
- Drops the old desktopSlot/mobileSlot pattern and ColorImageGrid /
  ColorImageCarouselItems exports — the gallery now consumes a single
  pre-ordered list (color images, then videos, then shared images).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes rounded-lg from the desktop gallery (thumbnails, featured image,
and matching skeletons in MediaSkeleton + ProductPageFallback). Active
thumbnail now uses ring-1 ring-inset ring-foreground/50 to mirror the
variant swatch's selected state instead of the heavier ring-2 ring-foreground.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A client-only DropdownMenu beside the Shipping label, defaulting to
"English (US)" with a few placeholder locales. No flags, no actual
market switching — selecting a value just updates local component
state for now. The bar is now justify-between so the selector hugs the
right edge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sonnet 4.6 was too slow for the streamed reviews section. Swap to
gpt-5.4-nano via the AI Gateway — same generateText + Output.object
call, just a different provider/model string.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts:
#	apps/template/lib/i18n/messages/en.d.json.ts
BannerSection now accepts a `backgroundVideo` field (MarketingVideo
type: { url, poster? }). When set, an autoplaying muted looped video
renders in place of the background image. The existing
backgroundImage doubles as a poster while the video buffers, so the
first frame isn't black.

Wire the homepage hero up with the supplied cdn.shopify.com mp4 — the
existing Outdoor Edit Shopify PNG stays as the poster.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the raw <video> with the existing AutoPlayVideo component
(originally written for the PDP gallery). It renders the
backgroundImage as a next/image poster underneath the <video> until
the video fires `canplay`, then crossfades the video on top —
same first-paint behavior the PDP relies on, no black flash while
the mp4 buffers. AutoPlayVideo also brings IntersectionObserver
play/pause so the hero stops decoding when scrolled past.

MarketingImage uses `alt`; AutoPlayVideo's `previewImage` expects
ImageType's `altText`, so the banner maps the fields locally before
passing them through.

Also swap the hero video URL to the boomerang upload on Shopify CDN.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Outdoor Edit PNG was unrelated to the boomerang loop, so it was
flashing a different shot before the video arrived. Shopify doesn't
expose a derived poster URL for direct file uploads (only product-
attached Video.previewImage via the Storefront API), so dropping the
image lets the browser render the video's own first frame once
metadata loads. The hero's dark gradient parent covers the brief
buffering window.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
laugharn and others added 3 commits April 30, 2026 11:07
Wires the homepage hero up with both backgroundImage and backgroundVideo
so AutoPlayVideo's poster-then-video pattern actually has a frame to
show. The poster is the source video's first frame, extracted locally
with ffmpeg and uploaded to Shopify Files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Default stays square. Bookcases slider on the home page uses portrait
so the slider fallback matches the rendered aspect.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ai-sdk/react 3.0.170 → 3.0.173
ai 6.0.168 → 6.0.171
lucide-react 1.11.0 → 1.14.0
next 16.3.0-canary.1 → 16.3.0-canary.6
next-intl 4.9.1 → 4.11.0
shadcn 4.5.0 → 4.6.0
zod 4.3.6 → 4.4.1

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@socket-security
Copy link
Copy Markdown

socket-security Bot commented Apr 30, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​ai-sdk/​react@​3.0.1731001007498100
Updatednpm/​lucide-react@​1.11.0 ⏵ 1.14.0100 +110098 +19680
Updatednpm/​shadcn@​4.5.0 ⏵ 4.6.098 +110090 +198 +1100
Updatednpm/​next-intl@​4.9.1 ⏵ 4.11.0100 +110093 +196 +3100
Addednpm/​zod@​4.4.110010010096100
Addednpm/​ai@​6.0.17110010010099100
Addednpm/​next@​16.3.0-canary.6100100100100100

View full report

laugharn and others added 8 commits April 30, 2026 16:30
The skeleton was rendering one title bar + a short price bar, but the
real card uses line-clamp-2 on the title — so the rendered card is ~one
line taller than the skeleton's reservation, causing layout shift when
the data resolved. Mirror the content-area sizing already used by
RelatedProductsSectionSkeleton.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The IntersectionObserver was the only autoplay trigger. On a cold cache
the observer's initial callback can fire before the video's metadata
loads — play() at readyState=0 races the load and silently rejects on
some browsers. Since the observer only re-fires on intersection
transitions, a failed initial play would never retry, leaving the poster
stuck.

Add a canplay listener that retries play() when the video is currently
visible. Pairs with the observer rather than replacing it so off-screen
gallery videos still don't auto-play.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts:
#	apps/template/components/product/related-products-section.tsx
… demo)

next.config.ts: explicit deviceSizes [640, 828, 1200, 1920] and
imageSizes [64, 128, 384], trimmed from the Next defaults of 8/8.
Largest realistic display is the lightbox (~1920w); smallest is the
64px cart thumbnail (128w for retina). Cuts ~half the optimized
variants per Shopify asset without visible quality loss.

Cart and complementary thumbnails: sizes 64px → 80px so all small
thumbnails (cart, complementary, PDP gallery thumb) land on the
single 128w variant. Quality bump on retina for the cart/complementary
case as a side effect.

Posting on the demo branch first to look at Vercel image-optimizer
hit/miss patterns and visual quality before opening a main PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three-group layout:
- Left: mobile menu + quick links
- Center: logomark, absolutely positioned at viewport center so it
  stays centered regardless of left/right group widths
- Right: search, account, cart

Logo type now matches SliderTitle (text-2xl sm:text-3xl, tracking-tighter,
font-display) so the wordmark reads at the same weight as section
headings on the page below it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Inline SVG drawn on a 24×24 viewBox:
- Roof: katakana ハ as two diagonal strokes diverging from (10,3) and
  (14,3) outward to (4,12) and (20,12). Symmetric, sans-serif, butt
  ends.
- Body: open-top square with corners (10,14) → (10,23) → (18,23) →
  (18,14). Width 8, slightly inset from the roof and offset 2 units
  right of the roof's centerline to give the house an asymmetric,
  minimalist feel.

Sized at size-[1em] so the logomark scales with the wordmark's
font-size. Stroke uses currentColor so it inherits the link color.
The Link container switches to flex items-baseline so the SVG's box
bottom aligns with the wordmark's text baseline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread apps/template/lib/params.ts Outdated
export const unstable_instant = {
samples: [
{
params: { handle: "__placeholder__" },
Copy link
Copy Markdown

@vercel vercel Bot May 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build fails because unstable_instant samples on products, collections, and search pages are missing the x-next-intl-locale header declaration that next-intl reads internally via requestLocale.

Fix on Vercel

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