# Bunny

Bijection component for file storage and CDN delivery with Bunny.net

- Package: @bijectionhq/bunny
- Category: Storage
- Status: Preview
- License: MIT
- Bijection source (repository access required): https://github.com/bijectionhq/bunny/tree/3575dd81fd63b0f84b2293ff6d5853f2a39c7e16
- Upstream: https://github.com/lipaonline/convex-bunny/tree/c256f83f11918847cd0bdcb9e6024f466a8026c7
- Documentation: https://docs.bijection.com/components/using
- Directory: https://bijection.com/components/bunny

## Get the source

Bijection repository access is required. Request access at https://bijection.com/contact.

```sh
git clone https://github.com/bijectionhq/bunny.git
cd bunny
git checkout 3575dd81fd63b0f84b2293ff6d5853f2a39c7e16
```

## Before using this component

Read the package README at the recorded revision for setup, dependencies, and API examples. Upstream documentation describes the original package and may differ from the Bijection adaptation. This is a source candidate for evaluation. Catalog inclusion does not establish npm availability or runtime qualification. Check compatibility with your SDK and deployment before adoption. External providers run their own compute.

## Upstream package documentation

Recorded 2026-10-23. This describes convex-bunny; check the Bijection adaptation separately.

A Convex component that integrates Bunny.net's global CDN and storage service with your Convex backend. Upload files through Convex actions, store metadata in your database for reactive queries, and serve content through Bunny's edge network. Supports all Bunny Storage regions and provides automatic CDN URL generation with file management capabilities.

### Use cases

- Building a media-heavy application where you need global CDN delivery with sub-100ms response times across multiple continents
- Creating a file upload system that requires reactive UI updates when files are added or removed, leveraging Convex's real-time database queries
- Developing an app that needs cost-effective storage with CDN capabilities, using Bunny.net as an alternative to traditional cloud storage solutions
- Building a content management system where you need to track file metadata in your database while serving actual files from a high-performance CDN
- Creating a multi-tenant application where different regions need optimized file delivery through Bunny's regional storage zones

### How it works

The component wraps Bunny.net's Storage API within Convex actions and queries. You configure a BunnyStorage instance with your storage zone credentials and CDN hostname, then use methods like `upload()` in actions and `listFiles()` in queries. When files are uploaded, the component stores them in Bunny Storage via HTTP API calls and saves metadata in your Convex database.

File operations follow Convex's function model: uploads and deletions happen in actions (which can call external APIs), while file listing and metadata queries use standard Convex queries for real-time reactivity. The component automatically generates CDN URLs using your configured hostname and provides methods like `getFileByKey()` for retrieving stored metadata.

Setup involves registering the component in `convex.config.ts`, creating a BunnyStorage instance with your API credentials, and setting environment variables for your storage zone and CDN hostname. The component supports all Bunny Storage regions (DE, NY, LA, SG, SYD, BR, JH) through the region configuration option.

### Upstream README

# convex-bunny

A [Convex](https://convex.dev) component for file storage and CDN delivery with [Bunny.net](https://bunny.net).

Upload, manage, and serve files through Bunny.net's global CDN directly from your Convex backend.

## Features

- **File Upload** — Upload files to Bunny Storage via Convex actions
- **CDN Delivery** — Automatic CDN URL generation for uploaded files
- **File Management** — List, query, and delete files with metadata tracking
- **Multi-Region** — Support for all Bunny Storage regions (DE, NY, LA, SG, SYD, BR, JH)
- **Metadata Tracking** — File metadata stored in Convex for reactive queries

## Installation

```bash
npm install convex-bunny
```

## Setup

### 1. Register the component

In your `convex/convex.config.ts`:

```typescript
import { defineApp } from "convex/server";
import bunny from "convex-bunny/convex.config";

const app = defineApp();
app.use(bunny);

export default app;
```

### 2. Create a component instance

In your `convex/bunny.ts`:

```typescript
import { BunnyStorage } from "convex-bunny";
import { components } from "./_generated/api";

export const bunnyStorage = new BunnyStorage(components.bunny, {
  storageZone: process.env.BUNNY_STORAGE_ZONE!,
  apiKey: process.env.BUNNY_API_KEY!,
  cdnHostname: process.env.BUNNY_CDN_HOSTNAME!,
  region: "default", // optional: de, ny, la, sg, syd, br, jh
});
```

### 3. Set environment variables

```bash
npx convex env set BUNNY_STORAGE_ZONE your-storage-zone
npx convex env set BUNNY_API_KEY your-storage-api-key
npx convex env set BUNNY_CDN_HOSTNAME your-zone.b-cdn.net
```

### 4. Use in your functions

```typescript
import { action, query } from "./_generated/server";
import { v } from "convex/values";
import { bunnyStorage } from "./bunny";

export const upload = action({
  args: {
    fileName: v.string(),
    fileData: v.string(), // base64 encoded
    contentType: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    return await bunnyStorage.upload(ctx, {
      fileName: args.fileName,
      fileData: args.fileData,
      contentType: args.contentType,
      path: "uploads",
    });
  },
});

export const listFiles = query({
  args: {},
  handler: async (ctx) => {
    return await bunnyStorage.listFiles(ctx);
  },
});

export const deleteFile = action({
  args: { key: v.string() },
  handler: async (ctx, args) => {
    return await bunnyStorage.deleteFile(ctx, args.key);
  },
});
```

## API Reference

### `BunnyStorage(component, config)`

| Config | Type | Required | Description |
|--------|------|----------|-------------|
| `storageZone` | `string` | Yes | Bunny Storage zone name |
| `apiKey` | `string` | Yes | Bunny Storage API key |
| `cdnHostname` | `string` | Yes | CDN hostname (e.g., `zone.b-cdn.net`) |
| `region` | `string` | No | Storage region (`default`, `ny`, `la`, `sg`, `syd`, `br`, `jh`) |

### Methods

| Method | Context | Description |
|--------|---------|-------------|
| `upload(ctx, options)` | Action | Upload a file to Bunny Storage |
| `getFile(ctx, fileId)` | Query | Get file metadata by ID |
| `getFileByKey(ctx, key)` | Query | Get file metadata by storage key |
| `listFiles(ctx, options?)` | Query | List all files |
| `deleteFile(ctx, key)` | Action | Delete a file from Bunny + metadata |
| `removeFileRecord(ctx, fileId)` | Mutation | Remove metadata only |
| `checkFile(ctx, key)` | Action | Check if file exists on Bunny |
| `getCdnUrl(key)` | Sync | Generate CDN URL for a key |

## Getting a Bunny.net API Key

1. Sign up at [bunny.net](https://bunny.net)
2. Create a **Storage Zone** in the dashboard
3. Copy the **Storage Zone Password** (this is your API key)
4. Note your **CDN hostname** (e.g., `your-zone.b-cdn.net`)

## Example App

See the `example/` directory for a complete demo app with file upload UI.

```bash
cd example
npm install
npx convex dev  # Start Convex backend
npm run dev     # Start Vite frontend
```

## License

MIT