# Create images and PDFs in JavaScript

> Generate an image, a PDF, or a hosted image URL from a template with the JavaScript SDK.

Canonical: https://bannerify.co/docs/sdk/js/apis/create-image

Each method takes a template id and an options object. Every option is optional.

## Create an image

`createImage` renders the template and returns the image bytes.

<ParamField body="templateId" type="string" required>
  The template id, for example `tpl_xxx`.
</ParamField>

<ParamField body="modifications" type="Modification[]">
  The values to put into the template's layers. Each entry names a layer with `name`. Layers you leave out keep the values from the template. [Modifications](https://bannerify.co/docs/essentials/modifications) lists the fields each layer accepts.
</ParamField>

<ParamField body="format" type="'png' | 'jpeg' | 'webp'" default="png">
  The image format.
</ParamField>

```ts
import { writeFile } from "node:fs/promises"

const { result, error } = await bannerify.createImage("tpl_xxx", {
  modifications: [
    { name: "headline", text: "Launch promo" },
    { name: "price", text: "$29" },
  ],
  format: "webp",
})

if (error) throw new Error(error.message)

await writeFile("launch-promo.webp", Buffer.from(result))
```

`result` is an `ArrayBuffer`. In a browser or an edge runtime, send it as the body of a `Response` and set the `Content-Type` header to the image type.

## Create a PDF

`createPdf` takes the same `templateId` and `modifications`. It has no `format` option.

```ts
const { result, error } = await bannerify.createPdf("tpl_invoice", {
  modifications: [
    { name: "customer", text: "Acme Studio" },
    {
      name: "line-items",
      columns: ["Item", "Qty", "Total"],
      rows: [{ Item: "Automate plan", Qty: 1, Total: "$29.00" }],
    },
  ],
})

if (error) throw new Error(error.message)

await writeFile("invoice.pdf", Buffer.from(result))
```

## Create a stored image

`createStoredImage` renders the image, saves it, and returns a URL instead of the bytes. Use it when you want to put the link in an email, a database row, or a no-code tool.

It accepts the options of `createImage`, plus `s3Config`.

<ParamField body="s3Config" type="S3Config">
  Save the file to your own S3-compatible bucket. This needs the Scale or Enterprise plan. Without it, Bannerify saves the file on its CDN and returns a link that starts with `https://images.bannerify.co/files/`.
</ParamField>

```ts
const { result: url, error } = await bannerify.createStoredImage("tpl_xxx", {
  modifications: [{ name: "headline", text: "Welcome back" }],
})

if (error) throw new Error(error.message)

console.log(url)
```

An `S3Config` has these fields:

| Field | Required | Description |
| --- | --- | --- |
| `endPoint` | Yes | The S3 endpoint, without the protocol |
| `region` | Yes | The bucket region |
| `bucket` | Yes | The bucket name |
| `accessKey` | Yes | The access key |
| `secretKey` | Yes | The secret key |
| `port` | No | The endpoint port. Defaults to `443` |
| `useSSL` | No | Defaults to `true` |
| `pathStyle` | No | Use path-style URLs. Defaults to `false` |
| `customUrl` | No | A URL template for the returned link. Use `{key}` for the file key |

## Handle the result

All three methods return `{ result }` or `{ error }`. See [Handle errors](https://bannerify.co/docs/sdk/js/overview#handle-errors).

## Related

- [Previous: JavaScript SDK](https://bannerify.co/docs/sdk/js/overview)
- [Next: Render videos in JavaScript](https://bannerify.co/docs/sdk/js/apis/render-video)
- [Documentation index](https://bannerify.co/docs/llms.txt)
