template-builder

—Editor

Add a free WhatsApp template editor to your product

Let your users write WhatsApp templates inside your app, with the phone preview next to the form and Meta's review rules checked as they type. One component for React or Vue, themed with CSS variables.

$ npm i @talqui-oss/template-builder @talqui-oss/template-builder-react

01Live demo

The editor, with its default theme

01Basics

lowercase, numbers and _
Category

02Content

23/60
98/1024
10/60

Use {{name}} for variables and *bold*, _italic_, ~strike~ for formatting.

03Buttons 1/10

11/25

04Variables

position 1
position 2
Order 4512 shipped
Hi Maria, your order 4512 left our warehouse today and arrives within 3 business days.
Track order

02Frontend

React or Vue, the same HTML

Both components render the same markup from the same core, so the styles and the behavior match. The editor keeps placeholders and their examples in sync as people type.

React

import { useState } from "react";
import {
  TemplateEditor,
  TemplatePreview,
} from "@talqui-oss/template-builder-react";
import "@talqui-oss/template-builder/styles.css";
import "@talqui-oss/template-builder/editor.css";

export function TemplateForm({ initial }) {
  const [template, setTemplate] = useState(initial);
  return (
    <>
      <TemplateEditor template={template} onChange={setTemplate} />
      <TemplatePreview template={template} />
    </>
  );
}

Vue 3

<template>
  <TemplateEditor v-model:template="template" />
  <TemplatePreview :template="template" />
</template>

<script>
import {
  TemplateEditor,
  TemplatePreview,
} from "@talqui-oss/template-builder-vue";
import "@talqui-oss/template-builder/styles.css";
import "@talqui-oss/template-builder/editor.css";

export default {
  name: "TemplateForm",
  components: { TemplateEditor, TemplatePreview },
  props: { initial: { type: Object, required: true } },
  data() {
    return { template: this.initial };
  },
};
</script>

03Theme

Your design system, your colors

Every color, font and radius is a CSS custom property on .tb-editor. The playground uses the same component with a dark theme.

theme.css

.tb-editor {
  --tb-editor-font: "Inter", sans-serif;
  --tb-editor-accent: #7c3aed;
  --tb-editor-surface: #ffffff;
  --tb-editor-control: #fafafa;
  --tb-editor-radius: 12px;
}

04Backend

Create the template on Meta from your API

Validate again on the server and send the request the adapter builds. Your access token never reaches the browser.

api/templates.ts

import { validate, toRequests } from "@talqui-oss/template-builder";
import { meta } from "@talqui-oss/template-builder/adapters/meta";

// POST /templates: what the editor submits
export async function createTemplate(template) {
  const { valid, issues } = validate(template);
  if (!valid) return { status: 422, issues };

  const [request] = toRequests(
    template,
    meta({ wabaId: process.env.WABA_ID, accessToken: process.env.META_TOKEN }),
  );
  const response = await fetch(request.url, {
    method: request.method,
    headers: request.headers,
    body: JSON.stringify(request.body),
  });
  return { status: response.status, body: await response.json() };
}