A flow approval step that sends approvers to a fully branded approval page instead of the built-in one. The request is posted to Slack with a button to the page, and the decision is reported back in the Slack thread.
Everything runs on the Community Edition: the page is a public full-code app (React) talking to the two public approval endpoints, and the flow uses a plain approval step.
What's inside
expense_request flow: posts the request to Slack, suspends until approved or rejected, then replies with the outcome.approval_page app: the branded page approvers open. No Windmill account needed.slack resource: the bot token used to post, pointing at the variable the workspace Slack connection creates.How it works
getResumeUrls(), keeps the job id and approval token from the built-in page URL, and builds a link to the public app instead: /public/<workspace>/<secret>#job=<id>&token=<token>.description, the object the page displays.jobs_u/flow/approval_info to read the request and jobs_u/flow/resume_suspended to approve or reject, without their own credentials, so the approval token stays the only authorization.resume, and approvers lists who decided. Rejections continue the flow too, so they are reported in the thread.slack resource at any bot token with chat:write.Branding: edit brand.ts (name, tagline, logo, footer) and the :root block of index.css (colors, radius, font) in the app.
Steps that require approvers to be logged in need a Windmill session and cannot be approved from a public page; the page detects that case and says so.