List icon
OutputValues icon
If icon
SlackIncomingWebhook icon
Log icon
Schedule icon

Figma Unresolved Comment Backlog Sentinel

List Figma file comments, alert Slack when unresolved design review feedback is older than a threshold, and log the result.

Categories
BusinessCore

A design review comment that never gets resolved is feedback nobody acted on, a blocking question sitting unanswered, or a change request quietly forgotten. Figma's own file view shows every comment if someone scrolls through them; it does not page anyone when one has sat unresolved for weeks. This blueprint lists every comment on a file and flags the unresolved ones that have.

This blueprint was created by Mohit Jeswani.

How it works

  1. list_comments (io.kestra.plugin.figma.comments.List) fetches every comment on file_key via Figma's GET /v1/files/:key/comments endpoint. Read-only; nothing in Figma is changed. allowFailure: true covers an API or auth error without failing the flow outright.
  2. evaluate (io.kestra.plugin.core.output.OutputValues) filters to comments with no resolved_at (unresolved) and a created_at older than stale_days, counting them and collecting their messages with a jq filter.
  3. route (io.kestra.plugin.core.flow.If):
    • compliant: logs that nothing is stale.
    • alert: posts the count and messages to Slack.
  4. summary logs the count and severity, closing the governance cycle.
  5. errors alerts Slack if the flow itself fails, for example an expired access token.

What you get

  • A recurring answer to "which design feedback has gone unanswered the longest", quoted directly, not just a count.
  • A check built on Figma's own documented resolved_at field (absent until a comment is resolved), not an inferred status.
  • A read-only check with zero risk of resolving or altering a real comment.

Who it's for

  • Design and product teams running design reviews in Figma who want stale feedback surfaced automatically instead of found during a file cleanup.
  • Teams evaluating the Figma plugin who want a worked example of comments.List used for a governance check rather than a one-off export.

Why orchestrate this with Kestra

Figma has no native alert for comment age; the only way to know is to open the file and scroll the comment pane. Kestra keeps stale_days as a flow input, turns the check into a Slack page quoting the actual unresolved feedback, and keeps a full execution history of every run.

Prerequisites

  • A Figma file with comments enabled and a personal access token (Figma account settings > Personal access tokens) or a valid OAuth 2.0 access token.
  • At least one unresolved comment to confirm the filter logic against.
  • A Slack incoming webhook URL.

This flow calls the Figma REST API directly over HTTPS; there is no official local Figma emulator, so list_comments cannot be exercised against a local Docker container. Validate against a real file with a mix of resolved and unresolved comments.

Secrets

  • FIGMA_ACCESS_TOKEN: the Figma personal access token (or OAuth token) used by list_comments, sent as a bearer token. In Kestra OSS, provide it as the base64-encoded environment variable SECRET_FIGMA_ACCESS_TOKEN.
  • SLACK_WEBHOOK_URL: used by alert and the errors block. In Kestra OSS, provide it as the base64-encoded environment variable SECRET_SLACK_WEBHOOK_URL.

Inputs

Input Default Purpose
file_key <your-figma-file-key> Figma file to audit
stale_days 14 Age past which an unresolved comment is reported stale
max_stale_count 1 Matched-comment count that triggers the Slack alert

Outputs

  • {{ outputs.list_comments.rows }}: every comment (id, message, created_at, resolved_at, user, parent_id, and more).
  • {{ outputs.evaluate.values.stale_count }} / .stale_messages: how many comments are stale and their text, semicolon-joined.
  • {{ outputs.evaluate.values.severity }}: OK, STALE_COMMENTS_FOUND, or CRITICAL.

Pitfalls

  • resolved_at is absent from the JSON entirely for an unresolved comment, not set to an empty string; the filter checks for a missing/null value specifically, not an empty one.
  • A reply to a comment thread is itself a separate comment object with its own created_at and resolved_at (via parent_id); a long-unresolved thread with recent replies still counts by its root comment's own age, not the most recent reply's.
  • This task fetches every comment on the file in one call with no documented pagination; a file with an extremely long comment history returns everything on every run.

Quick start

  1. Add the FIGMA_ACCESS_TOKEN and SLACK_WEBHOOK_URL secrets.
  2. Set file_key to a real file with at least one old, unresolved comment.
  3. Run the flow with the defaults and confirm summary logs a count.
  4. Lower stale_days below that comment's age to confirm alert fires with its message text.
  5. Enable the weekly trigger once the threshold matches your team's review cadence.

How to extend

  • Loop over several file_key values with io.kestra.plugin.core.flow.Loop to watch every file in a design system project in one scheduled run.
  • Group by user in a downstream task to see whose comments go unanswered longest, not just the aggregate count.
  • Chain io.kestra.plugin.figma.comments.Create after an alert to post a reminder comment back on the thread, once you are comfortable writing to the file automatically.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.