New to Kestra?
Use blueprints to kickstart your first workflows.
List Figma file comments, alert Slack when unresolved design review feedback is older than a threshold, and log the result.
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.
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.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.route (io.kestra.plugin.core.flow.If):summary logs the count and severity, closing the governance cycle.errors alerts Slack if the flow itself fails, for example an expired access token.resolved_at field (absent until a comment is
resolved), not an inferred status.comments.List used for a
governance check rather than a one-off export.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.
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.
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.| 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.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.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.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.FIGMA_ACCESS_TOKEN and SLACK_WEBHOOK_URL secrets.file_key to a real file with at least one old, unresolved comment.summary logs a count.stale_days below that comment's age to confirm alert fires with its message text.weekly trigger once the threshold matches your team's review cadence.file_key values with io.kestra.plugin.core.flow.Loop to watch every
file in a design system project in one scheduled run.user in a downstream task to see whose comments go unanswered longest, not just
the aggregate count.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.