Automate
Recipes
Six small integrations, each with a prompt to hand your agent.
Every recipe has the same three parts: something with context pushes a brief, a webhook or email carries the pitch to whoever decides, and the share link lands where the team already looks. Each one comes with a prompt you can paste into a coding agent to build it in your stack.
GitHub Action
A release publishes, a short release video is pitched, and the pitch shows up as a check that links to the production in Raylight. The Pitch ready email carries the login-free Greenlight, Send comments and Decline links. No app install, only the workflow file.
name: Launch videoon: release: types: [published]jobs: video: runs-on: ubuntu-latest permissions: contents: read checks: write steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: raylight-labs/video-action@v1 with: api-key: ${{ secrets.RAYLIGHT_API_KEY }} intent: "Announce ${{ github.event.release.name }} to existing customers" template: launch duration-seconds: 15 aspect: "16:9" greenlight-mode: manual code-globs: "src/**/*.tsx" wait-for-pitch: true post-check: trueRead https://www.raylight.app/llms.txt. Add a GitHub workflow to this repo that runs raylight-labs/video-action@v1 on every published release with template launch, 15 seconds, code-globs limited to our UI components, greenlight-mode manual, and post-check on. Tell me which secret to add.Slack relay
A small HTTP function receives production.pitch_ready (a pitch is ready), verifies the signature, and posts a message with three URL buttons through a Slack incoming webhook. On production.delivered (the production wrapped) it posts the share link as a new message. Nobody in Slack needs a Raylight login to greenlight. An incoming webhook cannot reply in a thread; to keep the share link under the pitch, post with a Slack app's bot token (chat.postMessage), save the first message's ts against the production id, and pass it as thread_ts later.
{ "text": "Pitch ready: Dark mode, finally", "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": "*Dark mode, finally*\n20 s, 16:9, 600 credits\nacme/web #412" } }, { "type": "actions", "elements": [ { "type": "button", "style": "primary", "text": { "type": "plain_text", "text": "Greenlight" }, "url": "<data.links.greenlight>" }, { "type": "button", "text": { "type": "plain_text", "text": "Send comments" }, "url": "<data.links.comment>" }, { "type": "button", "style": "danger", "text": { "type": "plain_text", "text": "Decline" }, "url": "<data.links.decline>" } ] } ]}Read https://www.raylight.app/llms.txt. Build a serverless function that receives Raylight webhooks, verifies Raylight-Signature with the secret in RAYLIGHT_WEBHOOK_SECRET, and on production.pitch_ready posts a Slack Block Kit message to SLACK_WEBHOOK_URL with the pitch title (data.production.pitch.title), duration, price and three url buttons labelled Greenlight, Send comments and Decline, wired to data.links.greenlight, data.links.comment and data.links.decline. On production.delivered post data.links.share as a new message. Answer 204 fast, reject bad signatures with 400, and answer 2xx to correctly signed events you do not handle. Then register the function URL as a Raylight webhook.Vercel deployments
Vercel sends a deployment.succeeded webhook when a deployment finishes (add one under the team's Settings, Webhooks, with that event). The relay checks Vercel's signature, ignores preview deployments, and turns a production deployment into a changelog production keyed by the deployment id, so Vercel's retries never double up. Pair it with the Slack relay to greenlight it.
import { createHmac, timingSafeEqual } from "node:crypto";export const POST = async (request: Request) => { const rawBody = await request.text(); const expected = createHmac("sha1", process.env.VERCEL_WEBHOOK_SECRET ?? "") .update(rawBody) .digest("hex"); const given = request.headers.get("x-vercel-signature") ?? ""; if ( given.length !== expected.length || !timingSafeEqual(Buffer.from(given), Buffer.from(expected)) ) { return new Response("bad signature", { status: 401 }); } const event = JSON.parse(rawBody); if ( event.type !== "deployment.succeeded" || event.payload?.target !== "production" ) { return new Response(null, { status: 204 }); } const { deployment, links } = event.payload; const url = `https://${deployment.url}`; const sha = deployment.meta?.githubCommitSha ?? deployment.id; await fetch("https://api.raylight.app/v1/productions", { method: "POST", headers: { Authorization: `Bearer ${process.env.RAYLIGHT_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ externalId: `vercel:${deployment.id}`, brief: { intent: "Show what just shipped to production", context: `Deployed ${url}\n\n${deployment.meta?.githubCommitMessage ?? ""}`, format: { template: "changelog", durationMs: 10000 }, }, origin: { provider: "vercel", label: `${deployment.name} deploy`, url: links?.deployment ?? url, ref: deployment.meta?.githubCommitRef ?? sha, }, }), }); return new Response(null, { status: 204 });};Read https://www.raylight.app/llms.txt. Write an endpoint that receives Vercel's deployment.succeeded webhook, verifies x-vercel-signature (HMAC-SHA1 of the raw body with VERCEL_WEBHOOK_SECRET), ignores deployments whose target is not production, and creates a Raylight production with template changelog, externalId set to the deployment id, the commit message as context, and origin provider vercel with the project name, the deployment's inspector URL and the branch. Use RAYLIGHT_API_KEY from the environment.Zapier
No code: a Zap with any trigger (a new sheet row, a published Notion page, a tagged Intercom article) and a Webhooks by Zapier action that POSTs to /v1/productions with a Bearer header. Set externalId to the trigger's record id and origin.provider to zapier. The pitch comes by email, with links to greenlight it.
Read https://www.raylight.app/llms.txt. Give me the exact Webhooks by Zapier POST configuration (URL, headers, JSON body with field mappings) to create a Raylight production from a new row in a Google Sheet with columns Title, Notes and Screenshot URL. Use the row id as externalId and zapier as the origin provider.Linear
When an issue labelled video is completed, a Linear webhook pushes a feature production. The Raylight webhook posts the pitch, and later the share link, back as comments on the issue through Linear's API, with the signed links inline. The relay holds the Linear token, not Raylight.
Read https://www.raylight.app/llms.txt. Build a relay with two routes. One receives Linear webhooks and, when an issue with the label video moves to Done, creates a Raylight production with template feature, the issue title as intent, its description as context, externalId set to the issue id and origin provider linear with the identifier and URL. The other receives Raylight webhooks, verifies the signature, and comments the pitch (data.pitchMarkdown) with its greenlight, comment and decline links on the issue; on production.delivered it comments the share link.Claude Code
No integration needed. Paste the quickstart prompt; the agent already editing your code gets a key, sends the files it touched, and shows you the pitch in the terminal.
Read https://www.raylight.app/llms.txt and make a launch video for the feature I am working on: use the device flow to get a key if RAYLIGHT_API_KEY is missing, send the relevant UI files in the brief, wait for the pitch, show it to me, and greenlight it only when I say so.With the MCP server connected, the same agent uses create_production and get_production instead of raw HTTP and never needs a key.