> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ogify.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# defineTemplate

Helper function to define a template with type safety. Use this when creating custom templates for your Open Graph images.

<Note>
  For the full rendering pipeline and all renderer context options, see
  [Rendering Pipeline](/api-reference/core/rendering-pipeline). For type definitions,
  see [Type Definitions](/api-reference/core/type-definitions).
</Note>

## Function Signature

```typescript theme={null}
function defineTemplate<T extends OgTemplateParams>(
  config: OgTemplate<T>
): OgTemplate<T>;
```

## Parameters

<ParamField path="config" type="object" required>
  Template configuration

  <Expandable title="properties">
    <ParamField path="renderer" type="function" required>
      Function that returns a **React node tree** (recommended) or an HTML string. Receives the full renderer context:

      ```typescript theme={null}
      (
        props: OgTemplateOptions & { params: T }
      ) => string | ReactNode | Promise<string | ReactNode>;
      ```

      **Context props:**

      | Prop            | Type              | Default          | Description                                                                      |
      | --------------- | ----------------- | ---------------- | -------------------------------------------------------------------------------- |
      | `params`        | `T`               | —                | Merged template parameters                                                       |
      | `width`         | `number`          | `1200`           | Canvas width (original, not scaled)                                              |
      | `height`        | `number`          | `630`            | Canvas height (original, not scaled)                                             |
      | `fonts`         | `OgFontConfig[]`  | template fonts   | Font override from render options                                                |
      | `emojiProvider` | `OgEmojiProvider` | template default | Emoji provider override                                                          |
      | `isRTL`         | `boolean`         | `false`          | Right-to-left layout                                                             |
      | `scale`         | `number`          | `1`              | Supersampling — [do not use for layout](/api-reference/core/scale-supersampling) |
    </ParamField>

    <ParamField path="fonts" type="OgFontConfig[]" required>
      Array of font definitions required by the template. Validated at registration —
      throws if `fonts` is not an array.
    </ParamField>

    <ParamField path="emojiProvider" type="OgEmojiProvider" default="noto">
      Emoji provider to use. Options: `'twemoji'`, `'fluent'`, `'fluentFlat'`, `'noto'`, `'blobmoji'`, `'openmoji'`
    </ParamField>
  </Expandable>
</ParamField>

## Returns

<ResponseField name="template" type="OgTemplate<T>">
  The validated template object that can be used with `createRenderer`
</ResponseField>

## Examples

<CodeGroup>
  ```tsx JSX Template (Recommended) theme={null}
  import { defineTemplate, clsx, htmlSnippet } from "@ogify/core";

  export type MyTemplateParams = {
    title: string;
    description: string;
  };

  const myTemplate = defineTemplate<MyTemplateParams>({
    fonts: [
      { name: "Inter", weight: 400 },
      { name: "Inter", weight: 700 },
    ],
    emojiProvider: "twemoji",
    renderer: ({ params, isRTL, width, height }) => (
      <div
        tw={clsx(
          "flex flex-col w-full h-full bg-white p-16",
          isRTL ? "items-end text-right" : "items-start text-left"
        )}
        style={{ width, height }}
      >
        <div tw="text-[64px] font-bold">
          {htmlSnippet(params.title, { fontSize: 64 })}
        </div>
        <div tw="text-[28px] mt-4 opacity-80">{params.description}</div>
      </div>
    ),
  });

  export default myTemplate;
  ```

  ```tsx Advanced Template theme={null}
  import { defineTemplate, clsx, htmlSnippet } from "@ogify/core";

  export type AdvancedTemplateParams = {
    title: string;
    subtitle?: string;
    backgroundColor: string;
    textColor: string;
  };

  const advancedTemplate = defineTemplate<AdvancedTemplateParams>({
    fonts: [
      { name: "Roboto", weight: 400 },
      { name: "Roboto", weight: 700 },
    ],
    emojiProvider: "fluent",
    renderer: ({ params, isRTL }) => (
      <div
        tw={clsx(
          "flex flex-col w-full h-full p-[60px]",
          isRTL ? "items-end text-right" : "items-start text-left"
        )}
        style={{
          backgroundColor: params.backgroundColor,
          color: params.textColor,
        }}
      >
        <div tw="text-[72px] font-bold">
          {htmlSnippet(params.title, { fontSize: 72 })}
        </div>
        {params.subtitle ? (
          <div tw="text-[36px] mt-5 opacity-80">
            {htmlSnippet(params.subtitle, { fontSize: 36 })}
          </div>
        ) : null}
      </div>
    ),
  });

  export default advancedTemplate;
  ```

  ```typescript HTML String (Alternative) theme={null}
  import { defineTemplate } from "@ogify/core";

  const htmlTemplate = defineTemplate({
    fonts: [{ name: "Inter", weight: 400 }],
    renderer: ({ params, isRTL, width, height }) => `
      <div class="flex flex-col w-full h-full p-16 bg-white"
           style="width: ${width}px; height: ${height}px; direction: ${isRTL ? "rtl" : "ltr"};">
        <div class="text-[64px] font-bold">${params.title}</div>
      </div>
    `,
  });
  ```

  ```tsx Async Renderer theme={null}
  const asyncTemplate = defineTemplate({
    fonts: [{ name: "Inter", weight: 400 }],
    renderer: async ({ params }) => {
      const data = await fetchMetadata(params.id);
      return (
        <div tw="flex w-full h-full items-center justify-center">
          <div tw="text-[48px] font-bold">{data.title}</div>
        </div>
      );
    },
  });
  ```
</CodeGroup>
