# Brand Carousel Batch Renderer (`bread-kim/brand-carousel-batch-renderer`) Actor

Turn brand colors and supplied copy into ready-to-use social carousel cards. Batch-render consistent PNG slides, generate captions, and download the complete image set and assets as a ZIP package.

- **URL**: https://apify.com/bread-kim/brand-carousel-batch-renderer.md
- **Developed by:** [bread kim](https://apify.com/bread-kim) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$20.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Brand Carousel Batch Renderer

A private Apify Actor that turns supplied, approved Korean/English copy and four brand fields into real PNG carousel slides, a contact sheet, captions, mechanical QA evidence, a manifest, license notices, application guidance, and one deterministic ZIP. Rendering is local and deterministic; it does not generate copy, fetch customer assets, call AI, log into social networks, or post.

### Input and behavior

Submit one to five carousels, two to ten slides each, at most fifty slides total. Portrait is 1080×1350; square is 1080×1080. Text is normalized to NFC. The supported glyph domain is bounded Latin/ASCII, modern Korean, and common safe punctuation from bundled Nanum Gothic. Emoji, other CJK scripts, bidirectional controls, secrets, unsupported controls, unknown keys, weak text contrast, and copy that cannot fit are rejected without a success dataset row or partial ZIP.

The renderer uses a fixed 96 px safe margin, bundled Nanum Gothic regular/bold files, measured glyph ink bounds, fixed typography ranges, and a decorative-only accent. It never interprets HTML or HTTP-looking text. Facts, rights, spelling, and final approval remain the content owner's responsibility; no engagement or sales result is promised.

### Run locally

```bash
npm ci --ignore-scripts
npm run preflight
tmp_dir="$(mktemp -d)"
mkdir -p "$tmp_dir/key_value_stores/default"
cp canary_input.json "$tmp_dir/key_value_stores/default/INPUT.json"
CRAWLEE_STORAGE_DIR="$tmp_dir" node dist/main.js
```

The output is in `$tmp_dir/key_value_stores/default` and the single successful dataset row is in `$tmp_dir/datasets/default/items.jsonl`.

### Apify API example

Use placeholders only; do not commit a token.

```bash
ACTOR_ID="<YOUR_PRIVATE_ACTOR_ID>"
curl --fail-with-body --request POST \
  "https://api.apify.com/v2/acts/${ACTOR_ID}/runs?waitForFinish=120" \
  --header 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \
  --header 'Content-Type: application/json' \
  --data-binary @examples/input.json
```

Then use the run's default key-value-store links to download `ZIP` and `CONTACT_SHEET.png`. The authoritative `OUTPUT` record and the sole default dataset row are identical on success.

### Contracts and errors

`CAROUSELS_RENDERED` is emitted only after all render and package limits pass. Invalid JSON/input and known bounded product failures emit a generic typed `OUTPUT` and no dataset row. Storage transport, artifact upload, and dataset publication failures fail the process instead of being mislabeled as input/render success. `QA.json` preserves the owner's normalized literal text and measured per-line evidence; it is not fact checking or copy editing.

See [REQUIREMENTS.md](REQUIREMENTS.md), [ARCHITECTURE.md](ARCHITECTURE.md), [SECURITY_REVIEW.md](SECURITY_REVIEW.md), and [SUPPORT.md](SUPPORT.md).

# Actor input Schema

## `brand` (type: `object`):

Name and exact uppercase six-digit hexadecimal colors applied to every slide.

## `format` (type: `string`):

Portrait creates 1080 by 1350 slides; Square creates 1080 by 1080 slides.

## `carousels` (type: `array`):

One to five carousels, with two to ten approved-copy slides each and fifty slides total.

## Actor input object example

```json
{
  "brand": {
    "name": "ExampleStudio",
    "background": "#101827",
    "text": "#F8FAFC",
    "accent": "#FBBF24"
  },
  "format": "portrait",
  "carousels": [
    {
      "id": "weekly-tip",
      "caption": "Approved demo copy. Review before posting.",
      "slides": [
        {
          "title": "반복 제작은 자동화하세요",
          "body": "승인한 글을 브랜드 카드뉴스로 만듭니다.\n한글 문장을 그대로 유지합니다."
        },
        {
          "title": "브랜드 규칙은 한 번만",
          "body": "색상과 글꼴 규칙을 같은 묶음에 적용합니다.\n카드마다 다시 디자인하지 않습니다."
        },
        {
          "title": "검토 후 직접 게시하세요",
          "body": "PNG와 캡션을 ZIP으로 받습니다.\n자동 게시나 내용 생성은 수행하지 않습니다."
        }
      ]
    }
  ]
}
```

# Actor output Schema

## `results` (type: `string`):

Exactly one success record identical to OUTPUT.

## `outputRecord` (type: `string`):

Authoritative success or bounded error status.

## `carouselPack` (type: `string`):

Download the deterministic PNG, caption, QA, manifest, license, and application bundle.

## `preview` (type: `string`):

Download the rendered contact-sheet PNG.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "brand": {
        "name": "ExampleStudio",
        "background": "#101827",
        "text": "#F8FAFC",
        "accent": "#FBBF24"
    },
    "carousels": [
        {
            "id": "weekly-tip",
            "caption": "Approved demo copy. Review before posting.",
            "slides": [
                {
                    "title": "반복 제작은 자동화하세요",
                    "body": "승인한 글을 브랜드 카드뉴스로 만듭니다.\n한글 문장을 그대로 유지합니다."
                },
                {
                    "title": "브랜드 규칙은 한 번만",
                    "body": "색상과 글꼴 규칙을 같은 묶음에 적용합니다.\n카드마다 다시 디자인하지 않습니다."
                },
                {
                    "title": "검토 후 직접 게시하세요",
                    "body": "PNG와 캡션을 ZIP으로 받습니다.\n자동 게시나 내용 생성은 수행하지 않습니다."
                }
            ]
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("bread-kim/brand-carousel-batch-renderer").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "brand": {
        "name": "ExampleStudio",
        "background": "#101827",
        "text": "#F8FAFC",
        "accent": "#FBBF24",
    },
    "carousels": [{
            "id": "weekly-tip",
            "caption": "Approved demo copy. Review before posting.",
            "slides": [
                {
                    "title": "반복 제작은 자동화하세요",
                    "body": """승인한 글을 브랜드 카드뉴스로 만듭니다.
한글 문장을 그대로 유지합니다.""",
                },
                {
                    "title": "브랜드 규칙은 한 번만",
                    "body": """색상과 글꼴 규칙을 같은 묶음에 적용합니다.
카드마다 다시 디자인하지 않습니다.""",
                },
                {
                    "title": "검토 후 직접 게시하세요",
                    "body": """PNG와 캡션을 ZIP으로 받습니다.
자동 게시나 내용 생성은 수행하지 않습니다.""",
                },
            ],
        }],
}

# Run the Actor and wait for it to finish
run = client.actor("bread-kim/brand-carousel-batch-renderer").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "brand": {
    "name": "ExampleStudio",
    "background": "#101827",
    "text": "#F8FAFC",
    "accent": "#FBBF24"
  },
  "carousels": [
    {
      "id": "weekly-tip",
      "caption": "Approved demo copy. Review before posting.",
      "slides": [
        {
          "title": "반복 제작은 자동화하세요",
          "body": "승인한 글을 브랜드 카드뉴스로 만듭니다.\\n한글 문장을 그대로 유지합니다."
        },
        {
          "title": "브랜드 규칙은 한 번만",
          "body": "색상과 글꼴 규칙을 같은 묶음에 적용합니다.\\n카드마다 다시 디자인하지 않습니다."
        },
        {
          "title": "검토 후 직접 게시하세요",
          "body": "PNG와 캡션을 ZIP으로 받습니다.\\n자동 게시나 내용 생성은 수행하지 않습니다."
        }
      ]
    }
  ]
}' |
apify call bread-kim/brand-carousel-batch-renderer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bread-kim/brand-carousel-batch-renderer"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/rCDHHrwivMjMiRzeb/builds/Ztm9N66e8wbhqvEfx/openapi.json
