Manage component maps for client and server components

The Content SDK Next.js App Router template generates two component map files to keep server and client concerns isolated. This avoids shipping server‑only logic to the browser, and enables lean client bundles. See the official Next.js documentation to learn more about server and client components.

Generated files

The Content SDK Next.js App Router template generates both maps by default:

  • component-map.ts – Includes all components (server and client) and is used in server-side code.

  • component-map.client.ts – Includes only client components and is used in client-side code.

Pages Router projects generate a single component-map.ts unless you force dual maps.

Import patterns

You must import component maps differently depending on whether you're in a server or client component.

Import component map in server components

Use the full map in server components (the default environment in the App Router) as shown:

RequestResponse
import { AppPlaceholder, Page } from '@sitecore-content-sdk/nextjs';
import componentMap from '.sitecore/component-map';

export default function Layout({ page }: { page: Page }) {
  return (
    <AppPlaceholder
      page={page}
      componentMap={componentMap}
      name="headless-main"
      rendering={page.layout.sitecore.route}
    />
  );
}

Import component map in client components

Use the client-safe version in client components as shown:

RequestResponse
'use client';
import components from '.sitecore/component-map.client';
import scConfig from 'sitecore.config';

export default function Providers({ children, page }) {
  return (
    <SitecoreProvider api={scConfig.api} componentMap={components} page={page}>
      {children}
    </SitecoreProvider>
  );
}

Component classification

Content SDK classifies components during build. Based on specific conditions, it classifies them into three as shown:

  • Client – File begins with 'use client'.

    RequestResponse
    'use client';
    
    export default function InteractiveButton() {
      const [count, setCount] = React.useState(0);
      return <button onClick={() => setCount(count + 1)}>{count}</button>;
    }
  • Server – Uses server‑only modules (for example, next/headers, fs, path).

    RequestResponse
    import { headers } from 'next/headers';
    
    export default async function ServerComponent() {
      const headersList = headers();
      return <div>User Agent: {headersList.get('user-agent')}</div>;
    }
  • Universal – Uses only code safe in both environments. Universal components appear in both maps.

You can also explicitly define the component type using the componentType const as shown.

RequestResponse
export const componentType = 'client';

export default function MyComponent() {
  return <div>Explicitly marked as client</div>;
}

Valid values for componentType are:

  • 'server'

  • 'client'

  • 'universal'

Component map generation

You can generate component maps with the following CLI command:

RequestResponse
sitecore-tools:generate-map

The result is based on your configuration and can contain one or both of the following:

  • component-map.ts - Contains server, client (client entries explicitly declare type), and universal components as shown:

    RequestResponse
    export const componentMap = new Map<string, NextjsContentSdkComponent>([
      ['ServerHero', ServerHero],
      ['ClientButton', { component: ClientButton, componentType: 'client' }],
      ['Card', Card],
    ]);
  • component-map.client.ts - Contains only client and universal components as shown:

    RequestResponse
    export const componentMap = new Map<string, NextjsContentSdkComponent>([
      ['ClientButton', ClientButton],
      ['Card', Card],
    ]);
Note

Server‑only components never appear in the client map, preventing runtime errors and larger bundles.

Configure component map generation behavior

Content SDK provides the following two flags that you can use to control how component maps are generated:

  • clientComponentMap

  • includeVariants

clientComponentMap flag

Use this to control the component map generation behavior. If the flag isn't specified, Content SDK automatically detects your Next.js router type and generates component maps as shown:

  • For App Router (projects with the app or src/app directory) - generates both component-map.ts and component-map.client.ts files.

  • For Pages Router (projects with the pages or src/pages directory) - generates only the component-map.ts file.

You can also override the auto-detection in sitecore.cli.config.ts by setting the clientComponentMap as shown:

RequestResponse
export default defineCliConfig({
  componentMap: {
    paths: ['src/components'],
    clientComponentMap: true,  // force dual maps with custom components
    // or
    clientComponentMap: false, // force single map
    ...
  },
});

includeVariants flag

Content SDK can include component variants along with their base components during map generation. To control variant inclusion, you can use the includeVariants flag. It defaults to true. A variant is any component file whose name follows BaseComponent.<variantName>.(ts|tsx|js|jsx). Variants also use the same naming convention as base components.

For example, consider PromoBlock.tsx to be a base component. A variant of this could be PromoBlock.green-bg.tsx.

By default, when includeVariants is true, the component map for this combination of base component and variant is generated as shown:

RequestResponse
import PromoBlock from '@/components/PromoBlock';
import PromoBlockgreenbg from '@/components/PromoBlock.green-bg';

export const componentMap = new Map<string, NextjsContentSdkComponent>([
  // base + variant merged into the SAME key
  ['PromoBlock', { ...PromoBlockgreenbg, ...PromoBlock }],
]);

You can also override the default in sitecore.cli.config.ts by setting includeVariants to false as shown:

RequestResponse
export default defineCliConfig({
  componentMap: {
    paths: ['src/components'],
    ...
    includeVariants: false,
  },
});

When set to false, base components are included while variants are omitted from all generated map(s). Client/server filtering still applies to the remaining base components.

Do you have some feedback for us?

If you have suggestions for improving this article,