Skip to content

Syncing with a repository

GuidePartial2026-07-27

Connect the document to a Git repository or an HTTP endpoint so tokens live next to the code that consumes them.

Read this before you start

Sync is the least finished area of the plugin.

  • GitHub works. GitLab and custom HTTP endpoints are implemented but their domains are not in the plugin’s network allowlist, so Figma blocks those requests at runtime. Treat GitLab and URL as not usable today.
  • There is no merge. A pull replaces your local tokens; a push overwrites the remote file.
  • Access tokens are stored unencrypted in Figma’s local client storage.
  • Some sync controls are only reachable through Settings — see below.

Adding a provider

Footer → Settings (gear) → sync provideradd sync provider.

GitHub Works

FieldDefault
Display name
Personal access token
Repository (owner/name)
Branchmain
Path or foldertokens.json
API base URLhttps://api.github.com

The token needs repository read and write access on the target branch.

GitLab Blocked

Fields mirror GitHub (project group/name, base URL https://gitlab.com, with /api/v4 appended automatically), but gitlab.com is not in the plugin’s allowed-domains list, so requests fail.

HTTP endpoint Blocked

An endpoint URL plus an optional Authorization header value. Pull is a GET, push is a PUT of the whole document. Arbitrary domains are not in the allowlist.


Single file vs directory mode

The path field decides the mode:

PathModeResult
Ends in .jsontokens/tokens.jsonSingle fileOne file holding the entire document
Anything else — tokens/DirectoryOne JSON file per token set, plus $themes.json

Directory mode is what you want in a repository — a change to button tokens touches comp/button.json, not a 4,000-line blob.


Pull

Reads the remote and replaces the local tokens.

  • Directory mode walks the path recursively and collects every .json file.
  • The payload is validated and converted to DTCG before being stored.
  • Result: “Pulled N tokens from <name> ✨”. An empty result reports “No tokens found”.

While pulling, a full-screen overlay blocks interaction: “Pulling tokens from <name>… This may take a few seconds”.

Pull is destructive

Your local tokens are replaced, not merged. Export a backup first if the document holds work that is not in the repository.

On connect

Adding a provider immediately checks whether the remote already has tokens. If it does, a Remote tokens detected dialog offers Pull tokens or Not now, and states plainly that pulling replaces local data.


Push

Writes the current document to the remote.

  • Single file — the whole { tokens, themes, tokenSets } object, pretty printed, committed with the message “Update design tokens via Figma plugin”.
  • Directory — one commit per token-set file, plus $themes.json when themes exist.

There is no conflict detection: a push overwrites whatever is at that path on that branch. Push to a working branch, not to main directly.


Known gaps

GapConsequence
GitLab and URL domains are not in the network allowlistThose providers cannot connect
No merge or conflict detectionConcurrent edits are lost, last write wins
Pull does not restore token set metadataSet structure can be reconstructed from folder paths, but explicitly created empty sets are lost
Tokens are stored as plain JSON in client storageAnyone with access to the machine’s Figma data can read them
Provider editing and removal are not exposed in SettingsRemoving a connection is only possible from a panel that is not currently reachable in the UI
The push format switch (flat vs nested) has no UIDirectory push always uses the flat format

A workable setup today

  1. Repository with a tokens/ directory on a design-tokens branch.
  2. GitHub provider, path tokens/, branch design-tokens.
  3. Pull at the start of a session, push at the end.
  4. Review and merge to main through a pull request.
  5. One person pushes per document — the lack of merge makes concurrent pushes unsafe.