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

HomeComponentData and home block item types

interfaceAdvancedlive demo

Describes the home page blocks a merchant arranges, and the brand, feature, testimonial and slide items some blocks list.

import { HomeComponentData, HomeComponent, Brand, Feature, Testimonial, Slider, HomeComponentConfig } from '@salla.sa/twilight-theme-engine/types';

In plain words

A store's home page is a list of blocks the merchant arranges in the Salla dashboard: a slider, a row of brands, a list of store features. HomeComponentData is one block: path says which block it is, and the block's own settings sit next to it.

Brand, Feature, Testimonial and Slider describe items inside some blocks, and HomeComponent the fields of a products block. Check each one against the live demo before relying on it: only some of them match what the API sends.

Signature

interface HomeComponentData {
  path: string;                     // e.g. 'home.brands', 'store-features'
  key?: string | number | null;
  view_style?: string | null;
  component?: JsonObject;
  [key: string]: string | number | boolean | null | JsonObject | undefined;
}

interface HomeComponent {           // the fields of a products block
  title?: string;  description?: string;  background?: string;
  products?: Product[];  display_all_url?: string;
}

interface Brand { id: number; name: string; logo: string; url: string }

interface Feature { icon: string; title: string; description?: string }

interface Testimonial { id: number; name: string; content: string; rating?: number; image?: string }

interface Slider { id: number; image: string; link?: string; title?: string; description?: string }

interface HomeComponentConfig {     // not the type registerHomeComponentConfig takes
  key: string;  title?: string;  path: string;  position: number;  data: JsonObject;
}

Try it live

The first item of a real home block from the demo store, against the type meant to describe it. ✗ marks a value the type does not allow.Try this: switch to Testimonial: id and content never arrive, and the text, rating and image come as text, stars and avatar.
Storefront canvas · en · LTR

Loading the home page blocks…

Controls
What a theme writes
import type { Brand } from '@salla.sa/twilight-theme-engine/types';

// Registered as 'brands': the home loader strips "home." from the block path.
export function BrandsBlock({ data }: { data: { brands: Brand[]; [key: string]: unknown } }) {
  return (
    <ul className="brands-block">
      {data.brands.map((brand) => (
        // brand.id is a string path on the wire: fine as a key, never for math.
        <li key={brand.id}>
          <img src={brand.logo} alt={brand.name} width={160} height={120} />
        </li>
      ))}
    </ul>
  );
}

Example

app/components/home/BrandsBlock.tsx
import type { Brand } from '@salla.sa/twilight-theme-engine/types';
import { Link } from '@salla.sa/twilight-theme-engine/components/common';

export interface BrandsBlockProps {
  // Declare the block's own data: HomeComponentData's index signature rejects arrays.
  data: { brands: Brand[]; title?: string; [key: string]: unknown };
}

export function BrandsBlock({ data }: BrandsBlockProps) {
  if (!data.brands.length) return null;

  return (
    <section className="s-block container">
      {data.title && <h2>{data.title}</h2>}
      <div className="brands-grid">
        {data.brands.map((brand) => (
          <Link key={brand.id} to={brand.url}>
            <img src={brand.logo} alt={brand.name} width={160} height={120} />
          </Link>
        ))}
      </div>
    </section>
  );
}

// app/router.tsx: the home loader strips "home." from paths, so 'home.brands' registers as 'brands'.
// registerHomeComponents({ ...DefaultHomeComponents, brands: BrandsBlock });

How it behaves

  • home.components() and home.queries.components() (@salla.sa/twilight-theme-engine/api/home) return HomeComponentData[] exactly as the API sends them. The engine home loader then removes the first home. from each path, and HomeComponentRenderer looks up home:<path>:<view_style>, then home:<path>, in the component registry.

  • The reference theme types its blocks the way the example does: Brands takes { brands: Brand[]; title?: string; [key: string]: unknown }, and CustomTestimonials declares its own TestimonialItem instead of using Testimonial.

  • In the engine, StoreFeatures reads Feature and the home loader and renderer read HomeComponentData. Nothing reads Brand, HomeComponent, Testimonial, Slider or this HomeComponentConfig.

Gotchas

  • Two types are called HomeComponentConfig. This one (key, path, position, data) is used by nothing. registerHomeComponentConfig takes the one from @salla.sa/twilight-theme-engine/components/home (height, className, id, placeholder); passing this one fails with TS2559, "has no properties in common".

  • interface MyBlock extends HomeComponentData { brands?: Brand[] } fails with TS2411: the index signature allows JsonObject values, not arrays. Declare the block's props yourself, with [key: string]: unknown, as the example does.

  • path from the API keeps the home. prefix on theme blocks (home.brands), but the registry key is home:brands. Register brands, not home.brands.

  • Two types are called Brand. This one has a numeric id; the brands API (brand.list(), and Brand from /routes/brands) uses the other, with a string id, label, banner and more. In the demo store's home.brands block, id is a text path ending in /brand-729170207.

  • Testimonial and Slider do not match the demo store's blocks: home.custom-testimonials items are { name, text, stars, avatar }, and home.enhanced-slider slides are { image, title, description }, with no id or link. Declare the shape you receive.

  • The JSDoc on Feature.description says it is mapped from the API field text inside StoreFeatures.tsx. There is no such mapping there, and the demo store already sends description.

Related

Source and docs