Skip to main content
Version: 3.x

3.19 -> 3.20

This page lists the highlights for upgrading a project from Front-Commerce 3.19 to 3.20

Update dependencies

Update all your @front-commerce/* dependencies to this version:

pnpm update "@front-commerce/*@3.20.0"

Automated Migration

We provide a codemod to automatically update your codebase to the latest version of Front-Commerce. This tool will update your code when possible.

pnpm run front-commerce migrate --transform 3.20.0

Manual Migration

ESLint: migrate to ESLint 10 with @front-commerce/eslint-config

Front-Commerce now ships a shared ESLint configuration package that replaces the previous @remix-run/eslint-config dependency (which is not compatible with ESLint 10).

The new @front-commerce/eslint-config package provides all the rules you need for a Front-Commerce project in a flat config format:

  • Core JavaScript rules
  • React and React Hooks
  • JSX accessibility (jsx-a11y)
  • Import rules (import-x)
  • TypeScript (typescript-eslint)
  • Vitest globals for test files
  • Front-Commerce-specific import restrictions (Remix wrappers, Storybook)

1. Update your dependencies

package.json
  "devDependencies": {
- "@remix-run/eslint-config": "2.17.4",
- "eslint": "8.57.1",
+ "@front-commerce/eslint-config": "3.20.0",
+ "eslint": "10.0.3",
}

Then run pnpm install to update your lockfile.

2. Replace your ESLint configuration

Delete your .eslintrc.cjs (and .eslintignore if you have one) and create an eslint.config.mjs at the root of your project:

eslint.config.mjs
import frontCommerce from "@front-commerce/eslint-config";

export default [
{
ignores: [
".cache/**",
".front-commerce/**",
"build/**",
"logs/**",
"public/build/**",
],
},

...frontCommerce,
];
tip

You can add your own rules or overrides after ...frontCommerce in the array. See the ESLint flat config documentation for more details.

3. Update eslint-disable comments

If your code contains eslint-disable comments referencing the old plugin names, update them:

Old rule nameNew rule name
react/jsx-key@eslint-react/no-missing-key
react/style-prop-object@eslint-react/dom/no-string-style-prop
react/display-name@eslint-react/no-missing-component-display-name
react/forbid-foreign-prop-types(removed, no equivalent needed)
react/no-typos(removed, no equivalent needed)
import/no-default-exportimport-x/no-default-export

Spread props are now applied before fixed props

Several components in theme-chocolatine now apply spread props before fixed props. This means that fixed props (such as appearance or type) can no longer be overridden by consumers via spread attributes.

If your overrides of these components relied on passing a prop that the wrapper was already fixing (e.g., passing appearance to a PrimaryButton), that prop will now be silently ignored at runtime. TypeScript types already prevent this (Omit<ButtonProps, "appearance">), but loosely typed spreads could bypass the check.

Affected components:

  • Button/LinkButtonappearance is always "link"
  • Button/PrimaryButtonappearance is always "primary"
  • Button/SubmitButtontype is always "submit"
  • Button/WarningButtonappearance is always "warning"
  • Forms/Input/RatingerrorAppearance, input, and help are always fixed
  • Typography/Link/ButtonLinkbuttonAppearance is always "default"
  • Typography/Link/PrimaryLinkbuttonAppearance is always "primary"
  • Typography/Link/SmallLinkappearance is always "small"
  • Typography/Link/TrackingLinkonClick is always the tracking handler

What to do: if you were relying on overriding these fixed props via spread, restructure your code to use the base component (Button or Link) directly instead.

Order: deprecated shipping fields

Order.isShippable, Order.shipping_address, and Order.shipping_method_title are deprecated in favor of Order.shipments. Orders now support multiple shipments, each with its own shipping address and carrier. The deprecated fields continue to work at runtime but will be removed in a future major version.

Replace usages as follows:

Deprecated fieldReplacement
Order.isShippableOrder.shipments.length > 0
Order.shipping_addressShipment.shippingAddress
Order.shipping_method_titleShipment.shippingMethodTitle

If you use these fields in GraphQL fragments on Order, remove them and spread the ShipmentFragment (or your own sub-fragment) on Order.shipments instead.

PropTypes removed from theme-chocolatine components

All theme-chocolatine components have been migrated from PropTypes to TypeScript. Components no longer export a .propTypes property.

If your overrides reference .propTypes from theme-chocolatine components (for example, MyButton.propTypes = Button.propTypes) or define their own PropTypes, those references will break at runtime.

What to do:

  1. Remove import PropTypes from "prop-types" statements.
  2. Replace .propTypes definitions with a TypeScript interface or type for your component's props.
  3. Remove .defaultProps and use default parameter values in the component's destructured arguments instead.
Automated Migration

The pnpm run front-commerce migrate --transform 3.20.0 codemod handles the mechanical cleanup: it removes prop-types imports, comments out .propTypes and .defaultProps blocks (preserving them as a reference), and inserts // TODO Codemod markers where you need to add TypeScript types.

Before (PropTypes):

app/theme/modules/MyComponent/MyComponent.jsx
-import PropTypes from "prop-types";
-
const MyComponent = ({ title, count }) => {
return (
<div>
<h1>{title}</h1>
<span>{count}</span>
</div>
);
};

-MyComponent.propTypes = {
- title: PropTypes.string.isRequired,
- count: PropTypes.number,
-};
-
-MyComponent.defaultProps = {
- count: 0,
-};

export default MyComponent;

After (TypeScript):

app/theme/modules/MyComponent/MyComponent.tsx
interface MyComponentProps {
title: string;
count?: number;
}

const MyComponent = ({ title, count = 0 }: MyComponentProps) => {
return (
<div>
<h1>{title}</h1>
<span>{count}</span>
</div>
);
};

export default MyComponent;