Generates an image for every brief in your sheet against your brand guidelines, files it in Box and links it back to the row.
Uses
ClaudeBox
Google Sheets
Stability AI
Turn a list of image briefs into on-brand images
Keep the pictures you need as one brief per row on an 'Image briefs' tab, and run it when the list has grown. AI rewrites each brief into an image prompt that applies your brand guidelines, an image is generated from it, the file is uploaded to a Box folder under the row's name, and the link is written back beside the brief.
You end up with images that read as one brand, filed in Box and linked from their rows. The 'Image link' column is the only cell ever written to, and a row that already has a link is left alone, so you can add briefs and run it again without remaking anything. A brief that names or describes a real person is skipped. A brief that fails, whether the generator refuses it or the upload fails, is named in the run log while the rest carry on.
Before the first run you need a Google Sheet with an 'Image briefs' tab headed 'Image link', 'Name' and 'Brief' in that order, a Box folder, and a few sentences describing your brand's look.
spreadsheetUrl to blank.Set spreadsheetUrl to blank.briefsTabName to Image briefs.Set briefsTabName to Image briefs.brandGuidelines to blank.Set brandGuidelines to blank.boxFolderId to blank.Set boxFolderId to blank.aspectRatio to 16:9.Set aspectRatio to 16:9.imageStyle to digital-art.Set imageStyle to digital-art.maxImagesPerRun to 8.Set maxImagesPerRun to 8.spreadsheetUrl. Save it as briefs.Read the rows of spreadsheetUrl. Save it as briefs.headers to briefs.headers.Set headers to briefs.headers.headers is not Image linkIf the first item of headers is not Image linkheaders doesn't contain NameIf headers doesn't contain Nameheaders doesn't contain BriefIf headers doesn't contain Briefrows to briefs.rows.Set rows to briefs.rows.generatedCount to 0.Set generatedCount to 0.skippedBriefs to an empty list.Set skippedBriefs to an empty list.imageBudget to maxImagesPerRun multiplied by 1.Set imageBudget to maxImagesPerRun multiplied by 1.briefRow in rows:For each briefRow in rows:rowLabel to row briefRow.row_number as text.Set rowLabel to row briefRow.row_number as text.briefName to blank.Set briefName to blank.briefText to blank.Set briefText to blank.existingLink to blank.Set existingLink to blank.columnErrorIf a step below fails, save the error as columnErrorbriefRow.Name and save it as briefName.Trim briefRow.Name and save it as briefName.briefRow.Brief and save it as briefText.Trim briefRow.Brief and save it as briefText.briefRow["Image link"] and save it as existingLink.Trim briefRow["Image link"] and save it as existingLink.rowLabel to the end of skippedBriefs and save it as skippedBriefs.Add rowLabel to the end of skippedBriefs and save it as skippedBriefs.rowLabel - it is missing one of the 'Image link', 'Name' or 'Brief' columns.Show in the output: Skipped rowLabel - it is missing one of the 'Image link', 'Name' or 'Brief' columns.existingLink isn't emptyIf existingLink isn't emptybriefText is emptyIf briefText is emptyrowLabel to the end of skippedBriefs and save it as skippedBriefs.Add rowLabel to the end of skippedBriefs and save it as skippedBriefs.rowLabel - its 'Brief' column is empty.Show in the output: Skipped rowLabel - its 'Brief' column is empty.briefName is emptyIf briefName is emptyrowLabel to the end of skippedBriefs and save it as skippedBriefs.Add rowLabel to the end of skippedBriefs and save it as skippedBriefs.rowLabel - its 'Name' column is empty, and the name is what the image is filed under.Show in the output: Skipped rowLabel - its 'Name' column is empty, and the name is what the image is filed under.generatedCount is greater than or equal to imageBudgetIf generatedCount is greater than or equal to imageBudgetimageBudget as text image(s). Run it again to carry on from where it left off.Show in the output: Stopped at this run's limit of imageBudget as text image(s). Run it again to carry on from where it left off.brandSection to Brand guidelines:Set brandSection to Brand guidelines:
brandGuidelines.briefSection to Image brief:Set briefSection to Image brief:
briefText.writerPrompt to You are writing the prompt for an image generator.Set writerPrompt to You are writing the prompt for an image generator.
Turn the image brief below into ONE vivid prompt of at most 60 words describing the finished picture: subject, composition, colour, lighting and mood. Apply the brand guidelines to all of it, so every image reads as the same brand.
Rules:
- Reply with the prompt only. No preamble, no quotation marks, no explanation.
- Describe a scene, an object or an abstract composition. Never a real, identifiable person.
- If the brief names or describes a real person - a public figure, a customer, a colleague, anyone identifiable - reply with exactly CANNOT ILLUSTRATE and nothing else.
- Never put a personal name into the prompt.
- Do not ask for words, logos or lettering in the picture; image generators render text badly.
brandSection.writerPrompt to writerPromptChange writerPrompt to writerPrompt
briefSection.imagePrompt to blank.Set imagePrompt to blank.writerErrorIf a step below fails, save the error as writerErrorwriterPrompt. Save it as written.Ask Claude: writerPrompt. Save it as written.
Maximum response length: 400written.response_text and save it as imagePrompt.Trim written.response_text and save it as imagePrompt.rowLabel to the end of skippedBriefs and save it as skippedBriefs.Add rowLabel to the end of skippedBriefs and save it as skippedBriefs.rowLabel: writerError as text.Show in the output: Could not write an image prompt for rowLabel: writerError as text.imagePrompt contains CANNOT ILLUSTRATEIf imagePrompt contains CANNOT ILLUSTRATErowLabel to the end of skippedBriefs and save it as skippedBriefs.Add rowLabel to the end of skippedBriefs and save it as skippedBriefs.rowLabel - the brief describes a real person, and this workflow does not generate pictures of real people.Show in the output: Skipped rowLabel - the brief describes a real person, and this workflow does not generate pictures of real people.imagePrompt is emptyIf imagePrompt is emptyrowLabel to the end of skippedBriefs and save it as skippedBriefs.Add rowLabel to the end of skippedBriefs and save it as skippedBriefs.rowLabel - no image prompt came back for it.Show in the output: Skipped rowLabel - no image prompt came back for it.\ with - in briefName with / replaced by - and save it as safeName.Replace \ with - in briefName with / replaced by - and save it as safeName.fileName to safeName.png.Set fileName to safeName.png.imageRef to blank.Set imageRef to blank.imageErrorIf a step below fails, save the error as imageErrorimagePrompt. Save it as generated.Generate an image of imagePrompt. Save it as generated.real people, recognisable faces, portraits of identifiable individuals, celebrities, public figures, logos, watermarks, lettering, textgenerated.document_ref and save it as imageRef.Trim generated.document_ref and save it as imageRef.rowLabel to the end of skippedBriefs and save it as skippedBriefs.Add rowLabel to the end of skippedBriefs and save it as skippedBriefs.rowLabel: imageError as text.Show in the output: Could not generate the image for rowLabel: imageError as text.imageLink to blank.Set imageLink to blank.uploadErrorIf a step below fails, save the error as uploadErrorboxFolderId to Box folder imageRef. Save it as filed.Upload boxFolderId to Box folder imageRef. Save it as filed.filed.file_link and save it as imageLink.Trim filed.file_link and save it as imageLink.rowLabel to the end of skippedBriefs and save it as skippedBriefs.Add rowLabel to the end of skippedBriefs and save it as skippedBriefs.rowLabel but could not file it in Box: uploadError as text.Show in the output: Generated the image for rowLabel but could not file it in Box: uploadError as text.imageLink is emptyIf imageLink is emptyrowLabel to the end of skippedBriefs and save it as skippedBriefs.Add rowLabel to the end of skippedBriefs and save it as skippedBriefs.rowLabel but Box did not return a link to it.Show in the output: Filed the image for rowLabel but Box did not return a link to it.writeBackErrorIf a step below fails, save the error as writeBackErrorbriefRow of briefsTabName in spreadsheetUrl.Overwrite row briefRow of briefsTabName in spreadsheetUrl.rowLabel is in Box at imageLink but the link could not be written back to the sheet, so it will be generated again next run unless you paste it in.Show in the output: The image for rowLabel is in Box at imageLink but the link could not be written back to the sheet, so it will be generated again next run unless you paste it in.generatedCount.Add 1 to generatedCount.doneMessage to Filed '@fileName' in Box for .Set doneMessage to Filed '@fileName' in Box for .doneMessage to doneMessage@rowLabel: .Change doneMessage to doneMessage@rowLabel: .doneMessage plus imageLink.Show in the output: doneMessage plus imageLink.generatedCount as text image(s).Show in the output: Finished. Generated and filed generatedCount as text image(s).skippedBriefs isn't emptyIf skippedBriefs isn't emptyskippedBriefs joined by , .Show in the output: No image was generated for: skippedBriefs joined by , .