Customization Best Practices and Upgrades

When you customize the built-in storefront template code, including React components, hooks, and functions, and Salesforce later releases a new template version, you need a strategy to adopt the improvements while preserving your customizations. Select the approach that best fits your team’s workflow and the extent of your customizations.

Customizing Existing Components and Code 

If you customized storefront template code, use one of these approaches for upgrading the storefront template.

Minor Updates: Merge Updates in Storefront Code 

If you’ve made minor modifications to existing storefront code, including components, hooks, and functions, and want to adopt Salesforce updates, merge the changes directly. For straightforward cases with minimal code conflicts, a supervised Git merge can be sufficient. Carefully review all changes during the merge process to ensure your customizations are preserved while incorporating Salesforce improvements.

When to Use This Method 

  • Customizations are minimal and code conflicts are straightforward to resolve.
  • Maintain a single version of each component, hook, or function.
  • Comfortable with Git merge workflows.

Trade-offs 

Advantages:

  • Automatically receive Salesforce improvements and bug fixes.
  • Maintain a single code version without duplication.
  • Stay in sync with upstream changes.
  • Simpler project structure with fewer files to manage.

Disadvantages:

  • Potential merge conflicts when Salesforce releases updates.
  • Requires immediate conflict resolution to adopt updates.
  • Can require rework of customizations if Salesforce makes significant structural changes.
  • Less predictable upgrade process.

Major Updates: Maintain Separate Code Copies 

For drastic customizations or full replacements, maintain customized copies of code, including components, hooks, and functions, in a separate directory and use Vite’s path aliases to override the built-in implementations site-wide. This approach prevents Git conflicts and simplifies adoption of upstream template updates.

When to Use This Method 

  • Extensive customizations exist.
  • Merge conflicts are complex or frequent.
  • Prefer explicit control over when to adopt Salesforce updates.
  • Minimize disruption during Storefront Next releases.

Implementation Steps 

  1. Create a separate directory for your customized code (for example, /customizations).
  2. Copy the code you want to customize to this directory.
  3. Modify your copy as needed.
  4. Configure Vite to use your custom code instead of the original.

Vite Configuration Example 

Use Vite’s resolve.alias configuration to replace the original component with your customized version.

1// vite.config.ts
2import { defineConfig } from "vite";
3import { reactRouter } from "@react-router/dev/vite";
4import tailwindcss from "@tailwindcss/vite";
5import tsconfigPaths from "vite-tsconfig-paths";
6import storefrontNextPlugin from "@salesforce/storefront-next-dev";
7import path from "path";
8
9export default defineConfig({
10  plugins: [reactRouter(), tailwindcss(), tsconfigPaths(), storefrontNextPlugin()],
11  resolve: {
12    alias: {
13      // Replace the original component with your customized version
14      "@/components/ProductCard": path.resolve(__dirname, "./customizations/ProductCard"),
15    },
16  },
17});

For more information about Vite’s aliasing capabilities, see the Vite resolve.alias documentation.

Trade-offs 

Advantages:

  • Eliminates Git merge conflicts when Salesforce updates the storefront template.
  • Original code remains untouched.
  • Clear separation between built-in and customized code.

Disadvantages:

  • You don’t automatically receive Salesforce improvements.
  • You must manually merge Salesforce updates into your customized copies.
  • Requires maintaining awareness of upstream changes.

Adding Net New Custom Components 

When building entirely new components that don’t replace existing ones, import your custom component to a page for use in a single storefront. Alternatively, to use the component in multiple storefronts or distribute it to customers, build an extension for the component.

Single-Use Component: Import the Component 

For a custom component that’s used only in one storefront, import it and add it to the containing page.

1// In your page component
2import { MyCustomComponent } from "@/components/MyCustomComponent";
3
4export default function ProductPage() {
5  return (
6    <>
7      <ProductCard />
8      <MyCustomComponent />
9    </>
10  );
11}

When to Use This Method 

  • A new component is used in one storefront only.
  • Comfortable with the additional task of importing the component after an upgrade.

Trade-offs 

Advantages:

  • Simple approach with no additional tooling, configuration, or build pipeline required.
  • Full control over the component’s lifecycle and rendering behavior.
  • Straightforward to debug because the component is a standard React import in your codebase.
  • Changes are immediately visible and traceable in your project’s file structure.
  • No dependency management or versioning overhead beyond your existing project setup.

Disadvantages:

  • Not scalable when the same component is needed in multiple storefronts—each storefront requires its own copy and manual sync.
  • The import must be re-added to any new or restructured pages after a template upgrade, which is easy to miss.
  • No centralized version control for the component across storefronts, which can lead to diverging implementations over time.
  • If the component eventually needs to be shared, migrating to the extension model requires significant rework.

Multi-Use Component: Use the Extension Model 

Use the Storefront Next extension mechanism and UI target functionality when building reusable solutions that you want to package and deploy across multiple customers. This approach is designed for independent software vendors (ISVs) and partners. To learn about extensions, see the Extensions Directory readme in GitHub.

The extension model isn’t intended for customizing individual built-in templates in your storefront. For template customization, use the other methods described in this guide.

Important

When to Use This Method 

  • A new component is used in multiple storefronts or is distributed to customers.
  • Willing to implement extensions.

Trade-offs 

Advantages:

  • Clean upgrade process because custom components are fully separated from the built-in storefront template code—template upgrades don’t affect your extension.
  • No Git merge conflicts when Salesforce releases new versions of the storefront.
  • A single extension can be deployed consistently across multiple storefronts or distributed to customers, eliminating duplicated code.
  • Extensions are versioned and packaged independently, making it easier to roll out updates and maintain backward compatibility.
  • The UI target mechanism provides stable integration points that are explicitly maintained by Salesforce across releases.

Disadvantages:

  • Requires learning the Storefront Next extension model and UI target API, which adds upfront complexity before you can build anything.
  • More files and configuration to manage compared to a simple import.
  • Extension packaging and deployment adds steps to your release workflow that aren’t present when using direct imports.
  • Debugging can be harder because the extension is transpiled dynamically and is further removed from the page component.