Migrate Remix Store to Remix 3 - #251
Draft
brookslybrand wants to merge 61 commits into
Draft
Conversation
* Add the native Remix Assets runtime * Use the standard Remix demo port * Simplify dual-runtime platform setup * Remove server filename convention
* Set up continuous Fly deployment * Use blue-green Fly deployments * Deploy Fly staging in Dallas * Finalize the Fly deployment workflow
|
Oxygen deployed a preview of your
Learn more about Hydrogen's GitHub integration. |
* Remove stale dependency overrides * Use Oxlint and Oxfmt * Narrow release-age exceptions
* Port the storefront shell * Install Chromium for browser tests
* Port collections catalog and public assets * Polish collections implementation
* Port product detail pages * Fix product details after home navigation
* Port cart to Remix 3 * Align cart tests with v3 practices * Remove unused cart migration code * Match pending checkout state
* Complete product page parity * Prevent cold navigation layout shift * Remove cold navigation workaround * Render initial product gallery opacity * Use Remix destination SSR fix * Return to Remix main preview * Remove redundant storefront type aliases
* Port Shopify policy and contact pages * Match policy content spacing and typography * Preserve policy content structure * Match policy list and paragraph rhythm * Fix policy content stacking
* Match migrated storefront styles to production * Match product description typography * Add cached Tailwind preflight reset
* Add Shopify compatibility routes * Fix buyer IP and discount compatibility
Repin the Remix preview to 54982346, the current head of
preview/pr-11688 ("installable build from 0d4a158"), so the app tracks
the latest build of the boundary reconciliation PR.
Revert the Dockerfile pnpm cache mount to `id=pnpm`. The poisoned store
entries were keyed by the old db77511 tarball URL, so the new SHA cannot
collide with them and the id bump is no longer doing anything.
Drop `onlyBuiltDependencies: [remix]`. Global `ignoreScripts: true`
already disables lifecycle scripts, so the allowlist was inert, and it
expressed the opposite of the intent documented directly above it: the
preview ships prebuilt dist and must not be built.
Verified the committed lockfile installs correctly from a cold pnpm
store (`--prod --frozen-lockfile`), yielding remix@3.0.0-beta.5 with
dist, rather than the monorepo root.
pnpm writes one of two shapes for a git dependency that targets a
subdirectory, and which one you get depends on whether the tarball was
already in the local store when the lockfile was written:
resolution: {gitHosted: true, path: packages/remix, tarball: ...}
resolution: {gitHosted: true, integrity: sha512-..., tarball: ...}
The second shape drops the subdirectory, so pnpm unpacks the repository
root. For Remix that is remix-the-web@undefined, which ships no dist/,
and it took out install, typecheck, test, the Oxygen build, and the Fly
image in one go. A lockfile regenerated on a cold store reintroduces it
silently, and the working tree still looks fine on a warm machine, so
this is easy to merge by accident.
Check the committed lockfile instead of relying on that. Only entries
whose key requests a subdirectory are considered, so ordinary git
dependencies that legitimately carry an integrity hash still pass.
Wired into `lint` so the existing CI job covers it without a workflow
change. Verified against the real broken lockfile from ea111b3 (all 47
entries flagged) and against main plus a synthetic no-subpath git
dependency (no false positives).
Remove lockfile lint workaround and use the Remix preview PR branch, while pinning pnpm to 10.33.3.
Match shop.remix.run's image loading experience: show a blurred low-res (?width=32) preview while the full image loads, then fade the preview out as the full image transitions from blurred to sharp. - ProductImageFrame renders a data-preview-image <img> (blur(20px), object-fit: cover, scale(1.1)) behind the ShopifyImage - ref sets data-loaded on load/error; CSS fades the preview opacity to 0 and transitions the main image filter to blur(0) over 750ms - prefers-reduced-motion guards disable the transitions - test asserts the full image via user-facing alt text rather than the internal data-preview-image selector
* Add consent-aware storefront analytics * Fix pinned Remix installation in Docker * Isolate the pinned Remix Docker cache * Stabilize product navigation acceptance test * Clean up analytics: key by product.id, publish from queueTask, dedupe cart helpers - Key ProductViewed/CollectionViewed by GID instead of a redundant productHandle prop; add route-level keys so product/collection switches remount the tracker - Move ProductViewed/CollectionViewed publishes into handle.queueTask instead of publishing during render - Lift the duplicated pending-check and snapshot-apply blocks into shared hasPendingCartWork and createSnapshotApplier helpers in analytics.tsx; delete the three local copies in cart.tsx - Reuse publishCartViewedWhenSettled for the cart page view, removing the every-render queueTask and local publishCurrentCartView identity dedupe - Unexport toAnalyticsCart; drop prevCart from CART_VIEWED payload - Share the queueTask-flushing createTestComponent across both test files * Add dev-only console logger for storefront analytics events Subscribe to every AnalyticsEvent in development and log payloads with console.debug. Raw subscribers see events before consent gating, so events show up even before the visitor accepts the consent banner. * Fix dev analytics logger: gate on import.meta.hot, not import.meta.env import.meta.env is undefined in the browser entry with this fullstack Vite setup. import.meta.hot is already used for HMR in this file and is only present during Vite dev, so it's the correct dev-only gate. * Poll for analytics bus in dev logger The analytics bus is created by an inline ShopifyScripts script that loads asynchronously. The previous one-shot getAnalytics() call raced with the bus setup and silently no-op'd. Retry every 200ms until the bus is available, then log a confirmation message. * Remove dev analytics console logger
* Port store-wide sale experience * Simplify the store-wide sale port Keep the sale metafield on the existing navigation query, label only line-level automatic discounts, and drop the extra GraphQL toolchain, parsers, and construction-focused tests.
* Add secure storefront subscriptions * Match sold-out notify form to production layout Use the same 2/3 + 1/3 email and Notify me row as shop.remix.run, hide Shop Pay on unavailable variants, and keep newsletter consent on the dedicated subscribe page. * Match product typography and add-to-cart pending state Bold the product title, use production dropdown type, show a centered green check while add-to-cart is in flight, and keep discount-code warnings off the product form. * Match the subscribe page to production layout Use the compact 2/3 + 1/3 email row, production copy, hidden consent, and a green check success state. Keep Remix mime on the HTTPS tarball so CI can install without SSH. * Remove unused product add-to-cart pending style * Keep Shop Pay enabled while adding to cart * Scope product dropdown font-size assertion to the product form * Drop the e2e dropdown font-size check The fixture product is Default Title only, so the size menu never renders. Browser tests already cover the real option menu. * Drop pixel-layout e2e assertions Keep journeys and user-visible sale/cart contracts. Do not lock font sizes, paddings, or button heights in Playwright.
* Add US and Canada market routing * Drop leftover market nits Remove unused marketFromPathname, the deleted sale-query test fallback, and the stale single-market ShopifyScripts comment.
* Add seasonal storefront snow * Hide snow until the canvas is ready Size the overlay from the visible field, skip the dense static blizzard on first paint, and keep static dots for reduced motion.
* Add vendored anti-slop lint rules * refactor: validate boundaries with Remix data schemas * fix: resolve anti-slop lint violations * chore: remove temporary anti-slop tooling * chore: restore lint tooling baseline
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Long-lived integration PR for the Remix 3 migration. Feature and platform PRs continue to target
v3; this PR keeps the complete migration visible against productionmainand gives Oxygen a stable pull request for preview deployments.Current state
Review and merge policy
Do not merge until storefront parity and cutover checks are complete. Review migration increments through their smaller PRs into
v3; this draft updates automatically as those PRs merge.See
REMIX_STORE_MIGRATION_PLAN.mdandREMIX_STORE_PARITY_PLAN.mdfor scope, sequencing, and acceptance criteria.