Skip to content
Twilight React Playground
ثيم رائدaren

registerHomeComponents

functionBeginnerserverbrowserlive demo

Tells the engine which component draws each home page block, by the block path the Salla API sends. Call it once at startup.

import { registerHomeComponents, AnyHomeComponent, HomeComponentsProps } from '@salla.sa/twilight-theme-engine/components/home';

In plain words

A merchant builds the home page in the Salla dashboard from blocks: a banner, a product slider, reviews. The API sends that list, and each block has a path naming its kind, such as fixed-banner.

registerHomeComponents is the lookup table from path to component. Call it once when the theme starts (in app/router.tsx) with the engine's defaults spread in and your own blocks added. A block whose path has no component draws nothing on a live store.

Signature

function registerHomeComponents(
  components?: Record<string, AnyHomeComponent | null>,   // DefaultHomeComponents
  prefix?: string                                         // 'home:'
): void

type AnyHomeComponent = React.ComponentType<{ data: any; priority?: boolean }>;

type HomeComponentsProps = {
  data: HomeComponentData & { position?: number; [key: string]: unknown };
};

Try it live

A block list entry with path "playground:notice", drawn by HomeComponentRenderer before and after its component is registered.Try this: untick registered: the renderer finds nothing under home:playground:notice and shows its fallback (empty in production).
Storefront canvas · en · LTR

registry.has('home:playground:notice'): false

Controls
registered
What a theme writes
import { createRouter } from '@salla.sa/twilight-theme-engine/tanstack';
import {
  DefaultHomeComponents,
  registerHomeComponents,
  type HomeComponentsProps,
} from '@salla.sa/twilight-theme-engine/components/home';
import { routeTree } from './routeTree.gen';

// A block the merchant adds with path "notice" gets its settings in `data`.
function Notice({ data }: HomeComponentsProps) {
  return <p className="container">{String(data.text ?? 'Free delivery this week')}</p>;
}

// app/router.tsx, at module scope: runs on the server and in the browser.
registerHomeComponents({
  ...DefaultHomeComponents,
  notice: Notice,
});

export function getRouter() {
  return createRouter(routeTree);
}

Example

app/router.tsx
import { createRouter } from '@salla.sa/twilight-theme-engine/tanstack';
import {
  DefaultHomeComponents,
  registerHomeComponents,
} from '@salla.sa/twilight-theme-engine/components/home';
import { Brands } from './components/home/Brands';
import { routeTree } from './routeTree.gen';

registerHomeComponents({
  ...DefaultHomeComponents,
  brands: Brands,
});

export function getRouter() {
  return createRouter(routeTree);
}

How it behaves

  • For each entry with a component it calls registry.register(prefix + path, component). HomeComponentRenderer looks blocks up as home:<path>:<view_style> first, then home:<path>.

  • A block component receives one prop, data: the block exactly as the API sent it (with home. removed from theme block paths by the home loader), plus position (1-based) and priority (true for the first three blocks). Type it with HomeComponentsProps, or your own interface.

  • AnyHomeComponent types data as any on purpose, so components with precise data types fit in the same map. Check the fields inside your component: the registry cannot.

  • The same function, DefaultHomeComponents and the three types are also exported from @salla.sa/twilight-theme-engine/routes/home, which is where the reference theme imports them.

Gotchas

  • Home blocks are not registered automatically. Without this call the engine's home page draws no block at all (a yellow "Unknown component" card per block in development, nothing in production).

  • A null value is skipped, not removed: { ...DefaultHomeComponents, youtube: null } keeps the default YouTube block if it was registered before. Remove one with registry.remove('home:youtube').

  • Register at module scope, not in a component: the registry lives as long as the server, across every request.

Related

Source and docs