Blog·

How to write custom lint rules for your Figma design system

Three kinds of custom Figma lint rules (naming, brand color, property), how to scope them to avoid false positives, and how to share them with the file.

Built-in checks catch what every file gets wrong: default layer names, unlinked fills, low contrast. They cannot know that your buttons start with btn-, that your CTA is #FF5C00, or that your cards only use 4, 8, or 16px corners. Those are team conventions, and a convention nobody checks is a suggestion.

A custom rule is a small, scoped assertion about a layer. There are three shapes worth knowing.

Naming rules: a regex the name must match

A naming rule has two regexes with different jobs:

  • Target: which layers the rule applies to (node types, plus an optional name pattern).
  • Pattern: what the name must look like.

Example: every frame or instance that looks like a button must start with btn-.

Field Value
Node types FRAME, INSTANCE
Target name pattern [Bb]utton
Pattern the name must match ^btn-

“Submit button” is checked and fails. btn-submit is not a target at all, so it is never flagged. The report shows expected vs actual so the fix is obvious.

Brand color rules: allowed here, required there

A brand color rule takes a hex value and a target selector for where that color is allowed.

  • The color on a layer outside the allowed targets is flagged. This catches a stray #FF5C00 on a decorative divider.
  • With require in targets on, a layer inside the allowed targets that is missing the color is flagged too. This catches the primary CTA someone recolored to a nearby orange.

Example: allowed on frames named ^btn-cta, required there. A button filled #FF6A1A fails. Exact match only, so “close enough” does not slip through.

Property rules: numbers against a constraint

Property rules compare a numeric property to a value: cornerRadius, opacity, width, height, or fontSize. The operators are eq, neq, lt, lte, gt, gte, in, and notIn.

  • Radius scale: cornerRadius in [4, 8, 16] on frames and rectangles.
  • No near-invisible layers: opacity gte 0.4 on frames and rectangles.
  • Body copy floor: fontSize gte 14 on text named ^body.

in and notIn take a list. The other operators take a single number. Layers where the property does not apply, or where it is mixed (a rectangle with four different corners), are skipped instead of flagged.

Scope rules so they stay trusted

A rule that fires 400 times on a contractor’s illustration gets disabled, and then it protects nothing. Three habits help:

  1. Always set node types. A naming rule with no node types applies to every layer, including vectors and boolean groups you never meant to name.
  2. Narrow with a name pattern when the convention only covers part of a type, like “frames whose names look interactive”.
  3. Match severity to cost. Use error for things that break handoff (wrong brand color), warning for drift (radius off the scale), and info for taste (preferred body size). People triage by severity, so keep errors rare.

Turn a rule off with its toggle before you delete it. A rule you can switch back on during a redesign is cheaper than one you have to rebuild.

Share the rules with the file

Rules are stored in the Figma file, so a teammate who scans the same file uses the same rules. There is no setup step and no separate config to drift.

To reuse a rule set in another file, export it as JSON and import it there:

{
  "schemaVersion": 1,
  "exportedAt": 1792000000000,
  "rules": [
    {
      "id": "custom:btn-prefix",
      "name": "Buttons use the btn- prefix",
      "type": "naming",
      "severity": "warning",
      "message": "Button layers must match ^btn-",
      "enabled": true,
      "target": { "nodeTypes": ["FRAME", "INSTANCE"], "namePattern": "[Bb]utton" },
      "pattern": "^btn-"
    }
  ]
}

Import merges by rule id, and invalid rules are skipped with a count, so a hand-edited file will not break the rest.

If you are not sure where to start, the Rules tab can ask the AI to suggest rules from a summary of the page: layer-type counts, top colors, font sizes, radii, and style names. Suggestions are advisory. You accept the ones that match how the team already works.

StyleGuard’s Rules tab builds all three rule types from a form. See features for the full list of checks, and the layer naming conventions post for what to put in your naming regex.

Ready to check your file?

Try StyleGuard directly in Figma.

Get the Figma plugin