cimplify
Checkout integration

Appearance API

Every Cimplify Element iframe (`AuthElement`, `CheckoutElement`, `AccountElement`, the hosted Pay page) accepts an `appearance` object that controls theme, accent color, font, and corner radius. The same shape works across all integration tiers.

The type

Defined as ElementAppearance in @cimplify/sdk:

interface ElementAppearance {
  theme?: "light" | "dark";
  variables?: {
    primaryColor?: string;     // any CSS color
    fontFamily?: string;       // CSS font-family value
    borderRadius?: string;     // CSS length, e.g. "0.5rem"
  };
}

Defaults

From packages/link/src/lib/appearance.ts:

FieldDefault
theme"light"
primaryColor#059669 (Emerald 600)
fontFamily"Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif
borderRadius0.85rem

Validation

The Element runs values through CSS.supports() before applying them; invalid values silently fall back to the default rather than rendering broken styles. Specifically:

  • primaryColor must be a valid CSS color (CSS.supports("color", value)); otherwise the default emerald is used.
  • borderRadius must be a valid CSS length (CSS.supports("border-radius", value)); otherwise 0.85rem.
  • fontFamily is rejected if it's longer than 160 chars, blank, or contains ;, {, or } (basic CSS-injection guard).
  • Any value outside "light" | "dark" is treated as "light".

Setting it

React

Memoize the appearance object. Iframe options are locked in at mount; passing a new reference triggers a console warning and is ignored to avoid remount churn.

import { useMemo } from "react";
import { CimplifyCheckout } from "@cimplify/sdk/react";

export function Checkout() {
  const appearance = useMemo(
    () => ({
      theme: "dark" as const,
      variables: {
        primaryColor: "#7c3aed",        // violet-600
        fontFamily: "'Geist', sans-serif",
        borderRadius: "0.5rem",
      },
    }),
    [],
  );

  return (
    <CimplifyCheckout
      client={client}
      cartId={cartId}
      appearance={appearance}
      onComplete={(r) => { /* … */ }}
    />
  );
}

Vanilla / Elements

const elements = createElements(client, businessId, {
  appearance: {
    theme: "dark",
    variables: {
      primaryColor: "#7c3aed",
      borderRadius: "0.5rem",
    },
  },
});

Embedded iframe (raw)

Pass it inside the init postMessage:

iframe.contentWindow!.postMessage({
  type: "init",
  businessId, publicKey,
  appearance: {
    theme: "light",
    variables: { primaryColor: "#059669", borderRadius: "0.85rem" },
  },
}, "https://link.cimplify.io");

Hosted Pay session

Pass it on session create; Cimplify stores it and applies it when the page loads:

{
  "cart_id": "crt_…",
  "appearance": {
    "theme": "light",
    "variables": { "primaryColor": "#0a2540" }
  }
}

CSS variables exposed

Internally, the appearance is resolved into CSS custom properties on the iframe's root. The full set (for reference, not direct customization):

VariableDriven by
--cimplify-primary-colorvariables.primaryColor
--cimplify-primary-color-alpha10% alpha mix of the primary
--cimplify-border-radiusvariables.borderRadius
--cimplify-bg / --cimplify-texttheme + sane defaults
--cimplify-surface / --cimplify-bordertheme
--cimplify-error / --cimplify-warningfixed

These are bridged into shadcn / Tailwind tokens (--primary, --background, --ring, etc.) so the iframe's entire UI re-themes from a single primary color.

Limits

  • You can't inject custom CSS or class names into the iframe.
  • You can't reorder or hide individual fields; for that level of control, use headless checkout.
  • Font files have to be reachable from the customer's browser (i.e. system font stack or a webfont served from your own CDN with permissive CORS).

Next

On this page