---
title: "Manage and integrate Medias in Nuxt Content Studio CMS"
description: "Explore how to browse and manage media files, including external storage with NuxtHub blob storage, and integrate them into your projects."
canonical_url: "https://nuxt.studio/medias"
---
# Manage and integrate Medias in Nuxt Content Studio CMS

> Explore how to browse and manage media files, including external storage with NuxtHub blob storage, and integrate them into your projects.

## Browse

All medias located in the `/public` directory are available in the **Media** tab of the Studio interface.

It's an intuitive interface for non-technical users to manage their `/public` directory or external storage if set.

Users can easily browse folders, upload new media at any level, and drag and drop files, making media organization straightforward.

## Editor integration

The TipTap visual editor provides seamless media integration:

- **Drag and drop** - Simply drag and drop images directly into the editor. An upload modal will open to let you choose the destination folder <badge>

Coming Soon

</badge>
- **Slash commands** - Type `/` and search for `Image` to quickly insert a media. A modal will open to let you choose the media from your library
- **Alt text support** - From the media modal, you can set the [alt attribute](https://www.w3schools.com/tags/att_img_alt.asp) for SEO and accessibility
- **Attributes support** - From the media modal, you can set additional attributes like width, height, and custom properties for advanced use cases.

## Supported file types

The media library supports the following file types:

- **Images**: PNG, JPG/JPEG, SVG, WebP, AVIF, ICO, GIF
- **Videos**: MP4, MOV, AVI, MKV, WebM, OGG
- **Audio**: MP3, WAV, AAC, M4A

## Storage Comparison

<table>
<thead>
  <tr>
    <th>
      Feature
    </th>
    
    <th>
      Default storage
    </th>
    
    <th>
      External storage
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Setup
    </td>
    
    <td>
      Zero configuration
    </td>
    
    <td>
      Requires <code>
        @nuxthub/core
      </code>
      
       with blob storage enabled
    </td>
  </tr>
  
  <tr>
    <td>
      Storage location
    </td>
    
    <td>
      <code>
        /public
      </code>
      
       directory
    </td>
    
    <td>
      Cloudflare R2, Vercel Blob, or S3-compatible
    </td>
  </tr>
  
  <tr>
    <td>
      Git commits
    </td>
    
    <td>
      Files committed to Git
    </td>
    
    <td>
      Only URLs referenced
    </td>
  </tr>
  
  <tr>
    <td>
      Repository size
    </td>
    
    <td>
      Grows with media
    </td>
    
    <td>
      Stays small
    </td>
  </tr>
  
  <tr>
    <td>
      Best for
    </td>
    
    <td>
      Small projects
    </td>
    
    <td>
      Large media libraries
    </td>
  </tr>
</tbody>
</table>

## Default storage (`public` folder)

By default, media files are stored in your `/public` directory and committed to Git when you publish. This works great for most projects and requires zero configuration.

Studio tracks all changes to the public folder as drafts in the browser until you publish. A service worker intercepts media requests to serve draft versions instantly, so you see your changes in the preview before they are committed.

## External Storage

For larger projects or teams with many media files, you can configure **external storage** to upload files directly to cloud storage. Studio uses [NuxtHub Blob Storage](https://hub.nuxt.com/docs/blob) which supports Vercel Blob, AWS S3 and other S3-compatible providers.

<note>

Files uploaded to external storage are **not committed to Git**. They are stored permanently in your cloud storage bucket and accessed via their public URL.

</note>

### Configuration

<steps level="4">

#### Install the NuxtHub module

```bash [Terminal]
npx nuxi module add hub
```

#### Enable blob storage and Studio external media:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  modules: ['@nuxthub/core', 'nuxt-studio'],

  hub: {
    blob: true,
  },

  studio: {
    media: {
      external: true,
    },
  },
})
```

<warning>

`@nuxthub/core` must be listed **before** `nuxt-studio` in the `modules` array.

</warning>

#### Set a driver

<note>

By default, if NuxtHub cannot detect a driver, files are stored locally in the `.data/blob` directory.

</note>

<tabs sync="blob-provider">
<tabs-item icon="i-simple-icons-amazons3" label="S3 compatible storage">

To configure [Amazon S3](https://aws.amazon.com/s3/) or any other S3-compatible storage:

**Install the** `aws4fetch` **package:**

<pm-install name="aws4fetch">



</pm-install>

**Set the following environment variables:**

```bash [.env]
S3_ACCESS_KEY_ID=your-access-key-id
S3_SECRET_ACCESS_KEY=your-secret-access-key
S3_BUCKET=your-bucket-name
S3_REGION=your-region # (optional)
NUXT_PUBLIC_STUDIO_MEDIA_PUBLIC_URL=your-public-url # (optional, mandatory for Cloudflare R2 provider)
S3_ENDPOINT=your-endpoint
```

</tabs-item>

<tabs-item icon="i-simple-icons-vercel" label="Vercel Blob">

To configure [Vercel Blob Storage](https://vercel.com/docs/storage/vercel-blob):

**Install the** `@vercel/blob` **package:**

<pm-install name="@vercel/blob">



</pm-install>

**Then follow these steps according to the environment you are using:**

1. Assign a Vercel Blob Store to your project from the [Vercel dashboard](https://vercel.com/) -> Project -> Storage **in production**.
2. Use `VERCEL_BLOB_READ_WRITE_TOKEN` in **local development** to authenticate.

```bash [.env]
VERCEL_BLOB_READ_WRITE_TOKEN=your-token
```

</tabs-item>

<tabs-item icon="i-simple-icons-cloudflare" label="Cloudflare R2">

When deploying to Cloudflare, configure [Cloudflare R2](https://developers.cloudflare.com/r2/) by providing the bucket name. NuxtHub auto-generates the wrangler bindings at build time.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  hub: {
    blob: {
      driver: 'cloudflare-r2',
      bucketName: '<bucket-name>'
    }
  }
})
```

<note>

To use Cloudflare R2 without hosting on Cloudflare Workers, use S3 compatible storage with the appropriate environment variables.

</note>
</tabs-item>

:::

</tabs>
</steps>

<tip to="https://hub.nuxt.com/docs/storage/blob">

See the NuxtHub blob documentation for detailed provider setup and environment variable configuration.

</tip>

### Options

<note>

Studio only manages files stored under the configured prefix in your bucket. Files uploaded through the Studio interface are stored as `<prefix>/<path>` (default: `studio/<path>`) and only those files are listed, browsed, or deleted from within Studio. Any other files already in your bucket are left untouched.

</note>

<table>
<thead>
  <tr>
    <th>
      Option
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        external
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Enable external storage via NuxtHub blob
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        maxFileSize
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        10485760
      </code>
      
       (10 MB)
    </td>
    
    <td>
      Maximum upload size in bytes, enforced server-side
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        allowedTypes
      </code>
    </td>
    
    <td>
      <code>
        string[]
      </code>
    </td>
    
    <td>
      <code>
        ['image/*', 'video/*', 'audio/*']
      </code>
    </td>
    
    <td>
      Allowed MIME types. Wildcards supported (e.g. <code>
        image/*
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        prefix
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'studio'
      </code>
    </td>
    
    <td>
      Bucket key prefix for uploaded files. Files are stored as <code>
        <prefix>/<path>
      </code>
    </td>
  </tr>
</tbody>
</table>

## Examples

List of examples for different storage providers.

### Vercel Blob

<steps level="4">

#### Create a Blob store

1. Go to your [Vercel Dashboard](https://vercel.com/dashboard) and open the **Storage** tab
2. Click **Create Database**, select **Blob**, and give it a name
3. Copy the `BLOB_READ_WRITE_TOKEN` value shown after creation

#### Set environment variables

```bash [.env]
BLOB_READ_WRITE_TOKEN=vercel_blob_rw_************
```

#### Link to your project in production

From your Vercel project, go to **Storage** and connect the blob store you just created. Vercel will automatically inject the `BLOB_READ_WRITE_TOKEN` environment variable at runtime.

#### Enable and configure NuxtHub

Install the NuxtHub module and enable blob storage:

```bash [Terminal]
npx nuxi module add hub
```

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  modules: ['@nuxthub/core', 'nuxt-studio'],

  hub: {
    blob: true,
  },

  studio: {
    media: {
      external: true,
    },
  },
})
```

</steps>

### Cloudflare R2

<steps level="4">

#### Create an R2 bucket

1. Go to [Cloudflare Dashboard](https://dash.cloudflare.com) and navigate to **R2 Object Storage**
2. Click **Create bucket** and give it a name (e.g., `my-studio-media`)
3. In your bucket **Settings**, enable **Public access** (via an `r2.dev` subdomain or a custom domain) so uploaded files are publicly accessible

#### Create an R2 API token

1. From the [R2 overview](https://dash.cloudflare.com/?to=/:account/r2/overview) page, click **Manage R2 API Tokens**
2. **Create API token** and set the permission to **Object Read & Write** — this allows Studio to read, write, and list objects
3. Under **Specify bucket(s)**, select your bucket (e.g., `my-studio-media`) to restrict the token's scope

#### Set environment variables

Your **Account ID** is visible in the right sidebar of the R2 overview page or in your Cloudflare account URL.

```bash [.env]
S3_ACCESS_KEY_ID=<r2_access_key_id>
S3_SECRET_ACCESS_KEY=<r2_secret_access_key>
S3_ENDPOINT=https://<account_id>.r2.cloudflarestorage.com
S3_BUCKET=my-studio-media
NUXT_PUBLIC_STUDIO_MEDIA_PUBLIC_URL=https://pub-<hash>.r2.dev   # or your custom domain
```

#### Enable and configure NuxtHub

Install the NuxtHub module and enable blob storage:

```bash [Terminal]
npx nuxi module add hub
```

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  modules: ['@nuxthub/core', 'nuxt-studio'],

  hub: {
    blob: true,
  },

  studio: {
    media: {
      external: true,
    },
  },
})
```

</steps>


## Sitemap

See the full [sitemap](https://nuxt.studio/sitemap.md) for all pages.
