FacetDocs

Kit

The kit holds what a file's designs share. Send it with any build, or alone; it merges into the file's kit by name and is saved with the file.

raag-kit.json≈ 698 tokens
{
  "kit": {
    "font": "Inter 15/22",
    "colors": {
      "ink": "#1A1423",
      "paper": "#F6F1EA",
      "saffron": "#F29F05",
      "rose": "#D9485F",
      "mute": "#6F6879",
      "board": "#ECE6DD"
    },
    "type": {
      "display": "Fraunces 40/44 600 -1",
      "title": "Fraunces 22/26 600",
      "deva": "Tiro Devanagari Hindi 14/20",
      "deva-xl": "Tiro Devanagari Hindi 40/44",
      "eyebrow": "Inter 12/16 700 +1.6 caps",
      "small": "Inter 13/18 500"
    },
    "parts": {
      "swara": {
        "params": {"note": "", "tone": "@saffron"},
        "node": {
          "row": [{"text": "{note}", "style": "deva"}],
          "padding": [2, 8],
          "cornerRadius": 8,
          "fill": "{tone}/20%"
        }
      },
      "sticker": {
        "params": {"label": "", "tone": "#FBE3B5", "turn": 0},
        "node": {
          "row": [{"text": "{label}", "font": "Inter 13/18 700"}],
          "padding": [6, 12],
          "cornerRadius": 14,
          "fill": "{tone}",
          "rotation": "{turn}"
        }
      },
      "status": {
        "params": {"ink": "@ink"},
        "node": {
          "row": [
            {"text": "9:41", "font": "Inter 15/20 600", "color": "{ink}"},
            {"space": "fill"},
            {"icon": "lucide:signal", "size": 16, "color": "{ink}"},
            {"icon": "lucide:battery-full", "size": 16, "color": "{ink}"}
          ],
          "gap": 6,
          "align": "center",
          "width": "fill",
          "padding": [16, 26, 6, 26]
        }
      },
      "phone": {
        "params": {"name": "Phone", "bg": "@paper", "children": []},
        "node": {
          "name": "{name}",
          "column": [
            {"status": {}},
            {
              "column": "{children}",
              "padding": [10, 22, 28, 22],
              "gap": 18,
              "width": "fill",
              "height": "fill"
            }
          ],
          "width": 390,
          "height": 844,
          "cornerRadius": 44,
          "fill": "{bg}"
        }
      }
    }
  }
}

The kit behind the Raag examples: a default font, six colors, six type presets and four parts.

SectionHoldsUsed as
fontthe default font of every textnothing to write: texts start from it
colorsnamed colors, one value or one per mode@ink, @ink/40%
modesmode names for the colors (["Light", "Dark"])"mode": "Dark" on a layer
typenamed text presets (a font or text keys){"title": "Today"}, "style": "title"
partsnodes with parameters{"chip": "May 2027"}

Colors become variables

Kit colors are variables in the collection Kit, so a layer painted @ink stays bound: change ink in the kit and every layer follows, and a layer shown in another mode takes that mode's value. A tint such as @rose/20% is a variable of its own (Kit/rose-20, made the first time it is used), so tints follow modes too. See Color.

Presets become text styles

Each preset is a text style of the same name. {"title": "Today"} makes a text that follows the style; send the preset again with new values and every text using it changes at once, with no rebuild.

Parts

A part is a node with parameters. Inside it, {name} stands for a parameter: a string that is only {name} takes the argument as it is (a number, a color, a list), and {name} inside longer text is replaced by its text.

{
  "kit": {
    "parts": {
      "chip": {
        "params": {"label": "", "tone": "@saffron"},
        "node": {
          "row": [{"text": "{label}"}],
          "padding": [2, 8],
          "cornerRadius": 8,
          "fill": "{tone}/20%"
        }
      }
    }
  }
}
  • {"chip": "May 2027"} passes one value to the first parameter.
  • {"chip": {"label": "May 2027", "tone": "@rose"}} names them.
  • Keys beside the name apply to the part's root: {"chip": "Late", "rotation": -4}.
  • A parameter called children takes the children written at the use: put "{children}" where they go.
  • A list parameter whose default is [], written alone among children ("{status}"), adds nothing when the use leaves it out and its items when it is given.
  • An argument may be a node or a list of nodes, not only text: {"card": {"title": "Today", "children": [{"chip": "Late"}]}}.
  • The part's root is named after the part unless its node names it: "name": "{title}" names each use by its argument.
  • Parts use presets, other parts and components. A part that uses itself is stopped at 24 levels.

A part is not a component: it expands where it is used and leaves no link. When the same thing must stay in sync across a file, make it a component.

Seeing and changing the kit

$ facet kit
{"font":"Inter 15/22","colors":{"ink":"#1A1423","paper":"#F6F1EA","saffron":"#F29F05","rose":"#D9485F","mute":"#6F6879","board":"#ECE6DD"},"type":{"display":{"fontFamily":"Fraunces","fontSize":40.0,"lineHeight":44.0,"fontWeight":600,"letterSpacing":-1.0},"title":{"fontFamily":"Fraunces","fontSize":22.0,"lineHeight":26.0,"fontWeight":600},"deva":{"fontFamily":"Tiro Devanagari Hindi","fontSize":14.0,"lineHeight":20.0},"deva-xl":{"fontFamily":"Tiro Devanagari Hindi","fontSize":40.0,"lineHeight":44.0},"eyebrow":{"fontFamily":"Inter","fontSize":12.0,"lineHeight":16.0,"fontWeight":700,"letterSpacing":1.6,"textCase":"upper"},"small":{"fontFamily":"Inter","fontSize":13.0,"lineHeight":18.0,"fontWeight":500}},"parts":{"swara":{"params":{"note":"","tone":"@saffron"},"node":{"row":[{"text":"{note}","style":"deva"}],"padding":[2,8],"cornerRadius":8,"fill":"{tone}/20%"}},"sticker":{"params":{"label":"","tone":"#FBE3B5","turn":0},"node":{"row":[{"text":"{label}","font":"Inter 13/18 700"}],"padding":[6,12],"cornerRadius":14,"fill":"{tone}","rotation":"{turn}"}},"status":{"params":{"ink":"@ink"},"node":{"row":[{"text":"9:41","font":"Inter 15/20 600","color":"{ink}"},{"space":"fill"},{"icon":"lucide:signal","size":16,"color":"{ink}"},{"icon":"lucide:battery-full","size":16,"color":"{ink}"}],"gap":6,"align":"center","width":"fill","padding":[16,26,6,26]}},"phone":{"params":{"name":"Phone","bg":"@paper","children":[]},"node":{"name":"{name}","column":[{"status":{}},{"column":"{children}","padding":[10,22,28,22],"gap":18,"width":"fill","height":"fill"}],"width":390,"height":844,"cornerRadius":44,"fill":"{bg}"}}}}

Send a kit section again to change it; names you send replace those entries and the rest stay. null removes an entry: {"kit": {"parts": {"badge": null}}}. A removed color keeps its variable, because layers may still use it; delete the variable with facet call variables '{"delete": "Kit/rose"}' once nothing does.

A name lives in one section: a preset and a part cannot share it, because {"badge": ...} could mean either. The kit refuses the second one and says which to rename.