Custom Components
Manual Prop Mapping

Manual Prop Mapping

When Locofy turns Figma into code, it needs to know which values from the design should flow into which props on your real components. Manual prop mapping is how you teach Locofy that connection—through the Figma plugin, through locofy.config.json in your repo, or both.

Quick overview: push your components to Locofy

Most teams keep components in Git and sync them with the Locofy CLI:

  1. Install the CLI globally (npm install @locofy/cli -g).
  2. From your repo root, run locofy init to create locofy.config.json (see What is locofy.config.json? below).
  3. Run locofy push to upload your component library to Locofy.
  4. In the Locofy Figma plugin, open your project and use I have completed all the steps so the pushed components appear for mapping.

For the full CLI walkthrough, see Import components using the Locofy CLI. If you prefer videos or third-party walkthroughs, search the web for Locofy push—many results follow this same init → push → plugin flow.

Why manual prop mapping exists

Design and engineering often describe the same UI with different surfaces:

  • Your Figma team uses component properties in the right sidebar (variants, booleans, text, instance swap) and layers inside the component.
  • Your code team defines props on React, Angular, or other components.

Locofy has to bridge the two. When a value is exposed as a Figma component property, mapping is usually straightforward: you point a code prop at that property by name. When a value only lives as nested layers, repeated frames, or patterns Figma cannot express as a single property (for example, lists), you teach Locofy with config.layer, layer naming conventions, or—for custom logic—mapFn.

Map props in five steps

  1. Import or push your code components (CLI or GitHub).
  2. Match each code component to a Figma component (Locate Mode in the plugin, or figmaComponentName in config).
  3. For props backed by Figma’s Properties panel, set figmaPropName (and valueMapping when labels differ from code).
  4. For props that come from the layer tree, align Figma layers with your props (layer naming), use config.layer, or mapFn for derived or array data.
  5. Sync and generate screens; adjust in Builder or the plugin until previews match your design system.

On this page: What is locofy.config.json? · AI mapping (plugin export) · Vocabulary · Code & Figma setup · Plugin UI · Config reference · How detection works · Full ProductCard example · Complex mapFn

What is locofy.config.json?

locofy.config.json is a JSON file at the root of your repository that tells Locofy which files are components and what each prop looks like (name, type, and how to read values from Figma).

Typical structure:

  • Top level: optional framework, projectId, projectName, optional wrapper, webpack, publicPath, and a components array.
  • Each component entry: path (source file), name (exported component), optional figmaComponentName, figmaPageName, and a props array.
  • Each prop: name, type (string, number, boolean, enum, object, array, node, function, …), optional required, optional previewValue (sample value so Locofy can preview the component in the plugin Props mapping screen—skip it if you do not need that preview), plus mapping fields such as figmaPropName, valueMapping, config.layer, or config.mapFn.

How the file gets there

  • locofy init (Locofy CLI) creates the file and starter entries when you wire a repo to Locofy.
  • locofy push sends that config and your components to Locofy—keep the file in version control so design and engineering share one source of truth.
  • AI-assisted mapping uses an export from the Locofy plugin plus an AI assistant in your repo to draft or update prop entries (below).

Paths in the JSON must be relative to the project root. A concise table of top-level keys is in Locofy config file.

AI-assisted mapping (export from plugin)

Locofy can package Figma metadata (JSON) and a Markdown prompt so an AI in your local repo can generate or refine locofy.config.json mappings for you. You do not need Locofy MCP for this flow.

Prerequisites

  • locofy init has been run in your local repository so locofy.config.json exists at the project root.
  • The Locofy Figma plugin is open and the correct Locofy project is selected.
  • An AI coding assistant that can read the exported prompt and edit files in your repo—for example Cursor (Agent), Claude Code, GitHub Copilot / Codex, or another tool you use with your codebase.
  • A way to unzip the bundle the plugin downloads.

How it works

  1. Run locofy init in your repo if you have not already, and keep locofy.config.json under version control.
  2. In the Locofy Figma plugin, select your Locofy project.
  3. Click the folder icon next to the project name. You will see two options:
    • Custom component library — import/sync components and map props inside the plugin (see Mapping via UI in Plugin).
    • Export data for mapping — download a ZIP used for AI-assisted mapping (this section).

Locofy plugin: folder menu with Custom component library and Export data for mapping
  1. Choose Export data for mapping.
  2. In the export screen, choose the scope of what to send—for example one or more components, the entire current page, or the whole Figma file—then click Export.

Locofy plugin: export scope options such as components, entire page, or whole file
  1. Unzip the download. Inside you will find Figma metadata as JSON plus a Markdown prompt file with instructions for generating mapping in locofy.config.json.
  2. Open your local repository in your AI tool, attach or @-mention that Markdown prompt (and any JSON the prompt tells you to include).
  3. Follow the prompt’s steps, then ask in plain language—for example: Map my Button component or Update mapping for ProductCard—so the assistant can read your code and Figma export and edit locofy.config.json.
  4. Review the diff, adjust if needed, commit, and run locofy push when you want Locofy to pick up the updated config.

The mapping vocabulary (how Figma meets code)

ConceptPlain languageWhere it lives
Code prop nameThe prop on your component (title, variant, item).props[].name
type (for example string)What kind of value Locofy should read or write (text, number, array, object, …).props[].type
figmaComponentNameThe exact name of the Figma component or component set this code component should attach to.Component entry
figmaPropNameOne row from Figma’s Properties sidebar (spelling, spaces, and capitalization must match).Prop entry
valueMappingWhen Figma’s labels differ from code (Primary vs primary), maps code values to the Figma labels Locofy should expect.Prop entry (common for enum / boolean)
config.layerBinds a prop to named layers inside the instance—especially when there is no Figma component property, or to disambiguate duplicate layer names.props[].config.layer
config.mapFnA small expression that walks the Figma tree—for example building an array from child TEXT layers.props[].config — see Complex prop mapping (mapFn)

String props usually come from Figma text properties, text layers, or images (use attr: "src" on the prop when binding image fills). Enum / variant props typically use figmaPropName plus valueMapping. Objects and arrays often combine config.layer, layer naming, or mapFn when Figma has no single “array property.”

The sections below are the full reference: field tables, React and Angular samples, detection order, and end-to-end examples.

Code component

import { FunctionComponent } from "react";
import styles from "./Card.module.css";
 
export type CardProp = {
  badge: string;
  item: {
    name: string;
    image: string;
    rating: number;
    locations: {
      name: string;
    }[];
  };
};
 
const Card: FunctionComponent<CardProp> = ({ badge, item }) => {
  return (
    <div className={styles.card}>
      <span className={styles.badge}>{badge}</span>
      <h3>{item.name}</h3>
      {/* ... */}
    </div>
  );
};
 
export default Card;

In these examples, the component and its properties are already defined. Next, create matching layers in your Figma component.

Figma component


Create Figma layers that correspond to your component props (e.g. badge, item name, rating, locations).

Mapping via UI in Plugin

  1. After pushing your components, click the folder icon next to the project name. Choose Custom component library to map props in the plugin (for Export data for mapping and AI, see AI-assisted mapping).


  2. Click the pencil icon, then Props mapping.


  3. Map your code component props to Figma component values.


Once all properties are mapped, you will see a green tick between each custom component prop and Figma component property. You do not need to map all props—optional ones can be left unmapped.

Note: Array props are fully supported. Figma does not have an equivalent array property, so use layer naming or config (see How Prop Detection Works below).

Mapping via locofy.config.json

Detailed locofy.config.json reference below—the overview and vocabulary sections above summarize the same ideas.

Each component has path, name, optional figmaComponentName / figmaPageName, and props. Optional top-level keys include framework, projectId, and projectName. Each prop sets type and any of figmaPropName, valueMapping, config.layer (with parent / grandParent when needed), attr, skip, config.nodeKind (Angular slots), optional previewValue (for Props mapping previews in the plugin only), or config.mapFn (mapFn guide). Use the plugin for quick mapping; use the file to keep mappings in Git.

{
  "components": [
    {
      "path": "./src/components/Card.tsx",
      "name": "Card",
      "props": [
        {
          "name": "className",
          "type": "string",
          "required": false
        },
        {
          "name": "badge",
          "type": "string",
          "required": false,
          "previewValue": "Superhost"
        },
        {
          "name": "item",
          "type": "object",
          "required": true,
          "previewValue": {
            "name": "Cozy Studio",
            "image": "https://images.unsplash.com/photo-1502672260266-1c1ef2d93688?w=800&q=80",
            "rating": 4.9,
            "locations": [{ "name": "Downtown" }]
          }
        }
      ]
    }
  ],
  "framework": "react",
  "projectId": "2mYKttmuPiV11gUqXAU7Krha1Pn",
  "projectName": "Website project"
}

Component- and prop-level fields

FieldScopePurpose
figmaComponentNameComponentMatch this code component to a Figma component (or component set) by exact name.
figmaPageNameComponentOptional. Figma page name (e.g. a design-system page). Locofy can look up a component such as Icon on that page when resolving the mapping.
figmaPropNamePropMatch a Figma component property (text, boolean, variant, etc.).
valueMappingProp (often enum / boolean)Map code values to Figma labels (e.g. "primary"["Primary"]).
config.layerPropDeclarative binding: array of layer specs { "name": "LayerName", "parent": "DirectParentFrame", "grandParent": "OptionalAncestorFrame" }. See config.layer: parent and grandparent below.
config.mapFnPropExpression-based mapping — see Complex prop mapping (mapFn).
config.nodeKindPropAngular only: for type: "node", "slot" marks the layer as an ng-content-style slot. Not used for React / Vue.
attrPropFor image-like values, e.g. "src" on a layer bound as an image.
skipProptrue skips automatic mapping for that prop (e.g. className).
previewValuePropOptional sample value Locofy uses only to render component previews in the plugin Props mapping screen.

For Angular node + attr: "slot" + mapFn (pick which child maps to a slot), see Angular: named slot on the mapFn guide.

config.layer parent and grandparent

Each entry in config.layer can use:

KeyWhen to use
nameRequired. Layer name to bind (exact match).
parentOptional. Name of a direct or containing frame/group so Locofy picks the right layer when the same name appears in multiple places (e.g. Label under Header vs under Footer).
grandParentOptional. Another ancestor name to narrow further when parent alone is not enough (e.g. Icon under Toolbar inside Sidebar).

name only — layer is unique in the instance:

"config": { "layer": [{ "name": "Label" }] }

With parent — disambiguate nested layers:

"config": { "layer": [{ "name": "Label", "parent": "Header" }] }

With parent and grandParent — deeper path (e.g. design system structure SidebarToolbarIcon):

"config": {
  "layer": [{ "name": "Icon", "parent": "Toolbar", "grandParent": "Sidebar" }]
}

Figma component properties and locofy.config.json

In Figma, open your component or component set and use the right sidebar Properties list. Each row (variant, text, boolean, instance swap, etc.) has a name Locofy can match. In config, set figmaComponentName to the Figma component or component set name, and set figmaPropName on each prop to the exact property label from that panel (spacing and capitalization matter). Use figmaPageName when the component name is not unique across the file—for example, to look for Icon on your Design System page only. Use valueMapping when Figma’s option labels differ from your code (Primary vs primary, True vs true, etc.).

Example 1 — Button: variants, boolean, and text property

Figma (component set Button)

Property in Figma panelTypeWhat the designer sees
VariantVariantPrimary, Ghost
Show iconBooleanTrue / False
LabelTextEditable string (drives the text layer wired to that property)

Same component in locofy.config.json

The code prop names (variant, showIcon, children) are yours; figmaPropName is what ties them to Figma. valueMapping maps code values to Figma’s variant/boolean labels.

{
  "path": "./src/components/Button.tsx",
  "name": "Button",
  "figmaComponentName": "Button",
  "props": [
    {
      "name": "variant",
      "figmaPropName": "Variant",
      "type": "enum",
      "enum": ["primary", "ghost"],
      "valueMapping": { "primary": ["Primary"], "ghost": ["Ghost"] }
    },
    {
      "name": "showIcon",
      "figmaPropName": "Show icon",
      "type": "boolean",
      "valueMapping": { "true": ["True"], "false": ["False"] }
    },
    {
      "name": "children",
      "figmaPropName": "Label",
      "type": "string",
      "config": { "layer": [{ "name": "Label" }] }
    },
    { "name": "onClick", "type": "function" }
  ]
}

children here is bound to the Label text property and the layer named Label via config.layer, so generated code picks up text from the instance correctly.

Example 2 — Listing card: mix of Figma properties and layers

Figma (component Listing-item)

SourceNameTypeRole
Component propertyShow superhostBooleanMaps with figmaPropName + valueMapping
Component propertyTitleTextString prop
Component propertyAddressTextString prop
Component propertyLikedBooleanBoolean prop
Component propertyStateVariantString prop (variant value)
Layer in the instancelistingName, rating, price, …Bound with config.layer when not exposed as a top-level property
Image fill / layerlisting01ImageIconImage prop with "attr": "src"

Matching locofy.config.json (excerpt)

{
  "path": "./src/components/ListingItem.tsx",
  "name": "ListingItem",
  "figmaComponentName": "Listing-item",
  "props": [
    { "name": "className", "type": "string", "skip": true },
    {
      "name": "showSuperhostTag",
      "figmaPropName": "Show superhost",
      "type": "boolean",
      "valueMapping": { "true": ["True"], "false": ["False"] }
    },
    {
      "name": "listingName",
      "figmaPropName": "Title",
      "type": "string",
      "config": { "layer": [{ "name": "listingName" }] }
    },
    {
      "name": "listingAddress",
      "figmaPropName": "Address",
      "type": "string",
      "config": { "layer": [{ "name": "listingAddress" }] }
    },
    {
      "name": "rating",
      "type": "string",
      "config": { "layer": [{ "name": "rating" }] }
    },
    {
      "name": "price",
      "type": "string",
      "config": { "layer": [{ "name": "price" }] }
    },
    {
      "name": "listingImage",
      "type": "string",
      "attr": "src",
      "previewValue": "https://randomuser.me/api/portraits/men/32.jpg",
      "config": { "layer": [{ "name": "listing01ImageIcon" }] }
    },
    {
      "name": "liked",
      "figmaPropName": "Liked",
      "type": "boolean",
      "valueMapping": { "true": ["True"], "false": ["False"] }
    },
    {
      "name": "state",
      "figmaPropName": "State",
      "type": "string"
    }
  ]
}

Props that only exist as named layers inside the component still use config.layer (and optional figmaPropName when you also sync with a property).

Example 3 — Header links: no Figma “array” property

Figma has no array component property. You define nav items as layers (e.g. a frame nav links containing TEXT children) and derive the array in config with mapFn:

Figma (structure)

  • Instance of component Header
  • Layer path: nav links → child TEXT nodes = “Home”, “Listings”, …

Config

{
  "name": "links",
  "type": "array",
  "required": true,
  "previewValue": [{ "name": "Home", "href": "/" }],
  "config": {
    "mapFn": "query('nav links').children.filter(t => t.type === 'TEXT' && t.visible).map(t => ({ name: t.text, href: '/' + t.text.replaceAll(' ', '-').toLowerCase() }))"
  }
}

See Complex prop mapping (mapFn) for the helpers available inside mapFn.

LocoAI example

Locofy can automatically detect properties you have not manually mapped. For example, the image property may be inferred from layer content.

Previously imported your component library?

If you have previously imported your component library, remove all existing mappings by clicking the pencil icon and Remove mapping, then click Sync again.




How Prop Detection Works

Once you have a mapping config in place, Locofy detects prop values from your designs. This section explains what you need to do in Figma and in your config so props are detected correctly.

Detection order (per prop)

PriorityStrategy
0prop.config.mapFn — if set, only this runs for that prop (no fallback). See Complex prop mapping (mapFn).
1Layer-based binding (meaningful layer names, optional […] naming hints, predefined pairs)
2User config (config.layer, figmaPropName, Figma component properties)
3Node-id structural mapping

Strategies 1–3 apply when mapFn is not set for that prop. For the mapFn helpers and patterns, see Complex prop mapping (mapFn).

Component Matching

Figma components and instances: When your custom component is mapped to a Figma component (or component set), all instances of that Figma component map to your custom component. Locofy uses the shared tree structure to match layers across instances.

Normal layers (frames and groups): You can map custom components to non-component layers using a naming convention:

Layer nameMaps to
<Button>Custom component named Button
<Card>Custom component named Card
<card>Custom component named Card (case-insensitive)

Limitation: Normal layer matching only works for components with simple props (children, className).

Mapping Props from Figma Component Properties

The most direct way to pass props is through Figma component properties:

Figma property typeCustom prop typeHow it works
TextstringText value from the Figma property
Variantstring / enumSelected variant value
BooleanbooleanTrue/false state
Instance SwapReactNode / ng-contentSwapped instance content maps to a slot

Worked examples that list Figma property panel names next to the matching figmaPropName / valueMapping / config.layer entries are in Figma component properties and locofy.config.json (earlier on this page).

See Structuring Components for aligning Figma properties with your code props.

Layer naming conventions

Layer naming is about the Figma layer in your component tree—the layer name (and how that layer is wired in Locofy) tells the tool which layer to read from. Locofy then picks up whatever data lives on that layer, not only values listed as Figma component properties in the right sidebar.

Typical layer-backed data includes:

  • Text — characters on a TEXT layer (for example a button label that is not exposed as its own component property, but exists as a child text layer).
  • Layout and sizewidth, height, and related layout from the layer’s geometry when detection maps them to your schema.
  • Visual state — fills, visibility, and other attributes Locofy’s detection rules can map to props (alongside explicit component properties when those exist).

Example: A Button in Figma might not give label as a dedicated Text component property, yet there is still a Label text layer inside the instance. By binding that layer to your code’s label prop—through a clear layer name, an optional [label]-style hint on the layer, or config.layer pointing at Label—Locofy can read the text from that layer (and other layer-level details detection supports), without requiring every string to be a top-level Figma property.

Optional bracket patterns (when you want an explicit hint in the layer name):

PatternRole
[name]Tie this layer’s content (text, image fill, etc.) to the prop called name.
[name >]Tie this layer’s children to the prop name (for example children or list-like props).

Predefined values in the layer name (fixed literals for previews or static mapping):

[firstName=John][lastName=Doe]

Each [key=value] segment sets the matching nested key to that literal when you use this pattern.

Value Mapping

When Figma uses different labels than your code (e.g. Sky vs sky, or Severity - Low vs green), define value mapping. Keys are values in your code; values are Figma variant/property names that map to them.

// src/components/Badge.tsx
import { FunctionComponent } from "react";
 
export type BadgeProps = {
  label: string;
  color?: "sky" | "purple" | "green";
};
 
export const LocofyConfig = {
  props: [
    {
      name: "color",
      type: "enum",
      enum: ["sky", "purple", "green"],
      previewValue: "green",
      valueMapping: {
        sky: ["Sky"],
        purple: ["Purple"],
        green: ["Green", "Severity - Low"]
      }
    }
  ]
};
 
const Badge: FunctionComponent<BadgeProps> = ({ label, color = "sky" }) => (
  <span className={`badge badge-${color}`}>{label}</span>
);
 
export default Badge;

Figma might use Severity - Low as a variant; with valueMapping, it maps to color="green" in code.

Expected Values

For enum-like props, restrict detected values with expectValues:

{
  expectValues: ["small", "medium", "large"];
}

If the detected value is not in this list, the first expected value is used instead.

Object Props

Object props are detected by treating each key as a separate prop. Map nested keys in your config, bind the right Figma layers to each key, or encode fixed samples in layer names such as [user.firstName=John][user.lastName=Doe].

// src/components/ListingCard.tsx
import { FunctionComponent } from "react";
 
export type Listing = {
  name: string;
  image: string;
  rating: number;
  locations: { name: string }[];
};
 
export type ListingCardProps = {
  badge: string;
  item: Listing;
};
 
const ListingCard: FunctionComponent<ListingCardProps> = ({ badge, item }) => (
  <div className="card">
    <span className="badge">{badge}</span>
    <h3>{item.name}</h3>
    <img src={item.image} alt="" />
    <span>{item.rating}★</span>
    {item.locations.map((loc) => (
      <span key={loc.name}>{loc.name}</span>
    ))}
  </div>
);
 
export default ListingCard;

locofy.config.json – declare the item prop as type object; map nested keys (item.name, item.rating, item.locations[].name) to Figma layers via the plugin UI:

{
  "components": [
    {
      "path": "./src/components/ListingCard.tsx",
      "name": "ListingCard",
      "props": [
        {
          "name": "badge",
          "type": "string",
          "required": false,
          "previewValue": "Superhost"
        },
        {
          "name": "item",
          "type": "object",
          "required": true,
          "previewValue": {
            "name": "Cozy Downtown Apartment",
            "image": "https://images.unsplash.com/photo-1502672260266-1c1ef2d93688?w=800&q=80",
            "rating": 4.8,
            "locations": [{ "name": "Downtown, Seattle" }]
          }
        }
      ]
    }
  ]
}

In Figma, point nested keys at the right layers—for example name layers [item.name], [item.rating], [item.locations >], or use predefined literals: [item.name=My Listing][item.rating=4.5].

Array Props

Array props use type: "array" in locofy.config.json. Define how the first item is detected unless you derive the whole array with config.mapFn. Locofy finds additional items via indexed layer names ([items.0.title], [items.1.title], …) or structure-based discovery (sibling nodes with the same structure).

// src/components/ProductList.tsx
import { FunctionComponent } from "react";
 
export type ProductItem = {
  title: string;
  price: number;
};
 
export type ProductListProps = {
  items: ProductItem[];
};
 
const ProductList: FunctionComponent<ProductListProps> = ({ items }) => (
  <div className="product-list">
    {items.map((item, i) => (
      <div key={i} className="product-card">
        <h4>{item.title}</h4>
        <p>${item.price}</p>
      </div>
    ))}
  </div>
);
 
export default ProductList;

Figma structure (structure-based discovery):

Frame: "Product List"
├── Card (title: "iPhone", price: "$999")   ← items[0]
├── Card (title: "MacBook", price: "$1299") ← items[1]
└── Card (title: "iPad", price: "$799")     ← items[2]

Or use indexed layer names so each list slot lines up with a layer: [items.0.title], [items.1.title], [items.0.price], etc.

locofy.config.json:

{
  "components": [
    {
      "path": "./src/components/ProductList.tsx",
      "name": "ProductList",
      "props": [
        {
          "name": "items",
          "type": "array",
          "required": true,
          "previewValue": [
            { "title": "iPhone", "price": 999 },
            { "title": "MacBook", "price": 1299 },
            { "title": "iPad", "price": 799 }
          ]
        }
      ]
    }
  ]
}

Result when detected from the product list:

[
  { title: "iPhone", price: 999 },
  { title: "MacBook", price: 1299 },
  { title: "iPad", price: 799 }
];

How Values Are Extracted

Prop typeSource
StringText layer content, layer name (normalized), or image src
NumberParsed from text content or Figma prop values
BooleanLayer visibility, Figma boolean property, or variant (truthy/falsy)
StyleDerived from Figma: flexDirection, color, fontSize, fontWeight, and layout such as width / height when detection maps them
Node/slotFigma layer(s) rendered as React nodes or Angular ng-content

Best Practices

  1. Keep structure consistent – All instances of a Figma component should share the same tree structure.
  2. Use Figma component properties when possible – Text, Variant, Boolean, and Instance Swap map cleanly to props.
  3. Bind layers to props – When something is not a Figma component property, name or target the layer that holds the text, size, or other data Locofy should read; add […] hints or config.layer if auto-detection needs help.
  4. Define value mapping – When designers use different names than developers (e.g. S vs small), add valueMapping.
  5. For arrays – Define the first item clearly; use naming or structure-based discovery for the rest.

Complete Example: Full Component and Config

Below is a complete ProductCard component with multiple prop types, and the corresponding locofy.config.json for each framework.

React

// src/components/ProductCard.tsx
import { FunctionComponent } from "react";
import styles from "./ProductCard.module.css";
 
export type ProductCardProps = {
  title: string;
  price: number;
  badge?: string;
  onSale?: boolean;
  rating?: number;
  tags?: { label: string }[];
};
 
const ProductCard: FunctionComponent<ProductCardProps> = ({
  title,
  price,
  badge = "",
  onSale = false,
  rating = 0,
  tags = []
}) => {
  return (
    <div className={styles.card}>
      {badge && <span className={styles.badge}>{badge}</span>}
      {onSale && <span className={styles.saleTag}>Sale</span>}
      <h3 className={styles.title}>{title}</h3>
      <p className={styles.price}>${price}</p>
      {rating > 0 && <span className={styles.rating}>{rating}★</span>}
      {tags.length > 0 && (
        <div className={styles.tags}>
          {tags.map((t) => (
            <span key={t.label} className={styles.tag}>
              {t.label}
            </span>
          ))}
        </div>
      )}
    </div>
  );
};
 
export default ProductCard;

locofy.config.json

{
  "components": [
    {
      "path": "./src/components/ProductCard.tsx",
      "name": "ProductCard",
      "props": [
        {
          "name": "className",
          "type": "string",
          "required": false
        },
        {
          "name": "title",
          "type": "string",
          "required": true,
          "previewValue": "Wireless Headphones"
        },
        {
          "name": "price",
          "type": "number",
          "required": true,
          "previewValue": 99
        },
        {
          "name": "badge",
          "type": "string",
          "required": false,
          "previewValue": "Best Seller"
        },
        {
          "name": "onSale",
          "type": "boolean",
          "required": false,
          "previewValue": true
        },
        {
          "name": "rating",
          "type": "number",
          "required": false,
          "previewValue": 4.5
        },
        {
          "name": "tags",
          "type": "array",
          "required": false,
          "previewValue": [{ "label": "New" }]
        }
      ]
    }
  ],
  "projectId": "your-project-id",
  "projectName": "Your Project"
}

Angular

// src/app/components/product-card/product-card.component.ts
import { Component, Input } from "@angular/core";
 
export interface ProductTag {
  label: string;
}
 
@Component({
  selector: "app-product-card",
  standalone: true,
  templateUrl: "./product-card.component.html",
  styleUrls: ["./product-card.component.css"]
})
export class ProductCardComponent {
  @Input() title!: string;
  @Input() price!: number;
  @Input() badge?: string;
  @Input() onSale?: boolean;
  @Input() rating?: number;
  @Input() tags?: ProductTag[];
}
<!-- product-card.component.html -->
<div class="card">
  @if (badge) {
  <span class="badge">{{ badge }}</span>
  } @if (onSale) {
  <span class="sale-tag">Sale</span>
  }
  <h3 class="title">{{ title }}</h3>
  <p class="price">${{ price }}</p>
  @if (rating && rating > 0) {
  <span class="rating">{{ rating }}★</span>
  } @if (tags && tags.length > 0) {
  <div class="tags">
    @for (t of tags; track t.label) {
    <span class="tag">{{ t.label }}</span>
    }
  </div>
  }
</div>

locofy.config.json

{
  "components": [
    {
      "path": "./src/app/components/product-card/product-card.component.ts",
      "name": "ProductCardComponent",
      "props": [
        {
          "name": "title",
          "type": "string",
          "required": true,
          "previewValue": "Wireless Headphones"
        },
        {
          "name": "price",
          "type": "number",
          "required": true,
          "previewValue": 99
        },
        {
          "name": "badge",
          "type": "string",
          "required": false,
          "previewValue": "Best Seller"
        },
        {
          "name": "onSale",
          "type": "boolean",
          "required": false,
          "previewValue": true
        },
        {
          "name": "rating",
          "type": "number",
          "required": false,
          "previewValue": 4.5
        },
        {
          "name": "tags",
          "type": "array",
          "required": false,
          "previewValue": [{ "label": "New" }]
        }
      ]
    }
  ],
  "projectId": "your-project-id",
  "projectName": "Your Project"
}

Each prop in the config has a name, type (string, number, boolean, enum, object, array, node, function), optional required, optional previewValue (only for Props mapping previews in the plugin), and the mapping fields above. Map these props to your Figma layers via the plugin UI, or encode mapping in config.layer, figmaPropName, and valueMapping as described above; use mapFn when you need custom logic.