Claude
Skills
Sign in
โ† Back

cloudinary-react

Included with Lifetime
$97 forever

Provides opinionated React SDK patterns for configuration, common integration scenarios, and troubleshooting for frequent errors and TypeScript pitfalls. Use when writing code or answering questions related to the Cloudinary React SDK.

Web Dev

What this skill does


# Cloudinary React Skill

## When to Use

- When a user is building or debugging Cloudinary in a **React** app (Vite, Create React App, Parcel, etc.).
- When implementing or fixing: Upload Widget, AdvancedImage/AdvancedVideo, transformations, overlays, image galleries, video player, or signed/unsigned uploads.
- When the user sees errors like "createUploadWidget is not a function", wrong imports from `@cloudinary/url-gen`, upload preset issues, or video player DOM errors.


## Quick Start

**Most common operations:**
1. **Setup**: Create config file with `cld` instance (see Project setup section)
2. **Display image**: `const img = cld.image('id').resize(fill().width(800)); <AdvancedImage cldImg={img} />`
3. **Upload Widget**: Script in index.html + poll for `createUploadWidget` in useEffect
4. **Image overlay**: Use `source(text(...))` or `source(image(...))` - see Import reference table for exact paths
5. **Signed uploads**: See [references/signed-uploads.md](references/signed-uploads.md)
6. **Troubleshooting**: See [references/troubleshooting.md](references/troubleshooting.md)

**For TypeScript**: See [references/typescript-patterns.md](references/typescript-patterns.md)
**For Video Player**: See [references/video-player.md](references/video-player.md)



## Instructions

When helping with Cloudinary in React, follow the patterns and rules below. Use the **exact** import paths and code patterns specified; do not guess subpaths or invent APIs.

---

# Cloudinary React SDK Patterns & Common Errors

**Scope**: These rules apply to **React (web)** with the browser Upload Widget. The **default** is **Vite** (create-cloudinary-react uses Vite). They also work with **other bundlers** (Create React App, Next.js, Parcel, etc.): only **how you read env vars** changes; see **"Other bundlers (non-Vite)"** below. Rules-only users: see **"Project setup (rules-only / without CLI)"** for the reusable Cloudinary instance, env, Upload Widget (unsigned/signed), and video player. For **React Native** uploads (including signed upload), see: https://cloudinary.com/documentation/react_native_image_and_video_upload?install_source=skillspack&referrer=react-skill#signed_upload โ€” same "never expose secret, generate signature on backend" principle, but React Native uses the `upload()` method and backend SDKs differently.

## Official Documentation

**For complete API references and all configuration options**, consult the Cloudinary documentation via **llms.txt**: https://cloudinary.com/documentation/llms.txt?install_source=skillspack&referrer=react-skill

This skill provides React patterns and common errors. For detailed API options (e.g., all Upload Widget config properties, Video Player API methods), use the documentation markdown files available through llms.txt.

### Key References
- **Transformation Rules**: https://cloudinary.com/documentation/cloudinary_transformation_rules.md?install_source=skillspack&referrer=react-skill
- **Transformation Reference**: https://cloudinary.com/documentation/transformation_reference.md?install_source=skillspack&referrer=react-skill
- **React Image Transformations & Plugins**: https://cloudinary.com/documentation/react_image_transformations.md?install_source=skillspack&referrer=react-skill#plugins
- **React Video Transformations**: https://cloudinary.com/documentation/react_video_transformations.md?install_source=skillspack&referrer=react-skill
- **Upload Widget Reference** (complete config options): https://cloudinary.com/documentation/upload_widget_reference.md?install_source=skillspack&referrer=react-skill
- **Upload Widget (signed uploads)**: https://cloudinary.com/documentation/upload_widget.md?install_source=skillspack&referrer=react-skill#signed_uploads
- **Cloudinary Video Player** (standalone player): https://cloudinary.com/documentation/cloudinary_video_player.md?install_source=skillspack&referrer=react-skill
- **Video Player API Reference** (complete API methods): https://cloudinary.com/documentation/video_player_api_reference.md?install_source=skillspack&referrer=react-skill
- **Video Player React Tutorial**: https://cloudinary.com/documentation/video_player_react_tutorial.md?install_source=skillspack&referrer=react-skill
- **Upload assets in Next.js (backend signature)**: https://cloudinary.com/documentation/upload_assets_in_nextjs_tutorial.md?install_source=skillspack&referrer=react-skill
- **Cloudinary Node.js SDK (server-side signing)** โ€” use **v2**: `import { v2 as cloudinary } from 'cloudinary'`; do not use v1 (e.g. 1.47.0). https://cloudinary.com/documentation/node_integration.md?install_source=skillspack&referrer=react-skill
- **React Native image and video upload (signed)**: https://cloudinary.com/documentation/react_native_image_and_video_upload.md?install_source=skillspack&referrer=react-skill#signed_upload
- Always consult the official transformation rules when creating transformations
- Use only officially supported parameters from the transformation reference

**Golden rule for @cloudinary/url-gen:** When generating overlay or transformation code, use **only** the "Import reference" table and "Canonical overlay block" in these rules. Copy those import paths and usage patterns exactly; do not guess or derive paths (e.g. `text` and `image` are from `qualifiers/source`, not `actions/overlay`; `Position` is from `qualifiers/position`, not `positioning/Position`).

---

# ๐Ÿ“‹ PATTERNS (How to Do It Right)

## Project setup (rules-only / without CLI)

If the user is **not** using the create-cloudinary-react CLI and only has these rules, generate the following so they get correct config, env, and widget setup.

**1. Environment (.env)**  
Create a `.env` file in the project root with **Vite prefix** (required for client access):
- `VITE_CLOUDINARY_CLOUD_NAME=my_cloud` (required โ€” use your actual cloud name, **never** the literal string `your_cloud_name` which causes 401)
- `VITE_CLOUDINARY_UPLOAD_PRESET=my_preset` (optional; required for unsigned upload widget โ€” use your actual preset name)
- **Restart the dev server** after adding or changing `.env`. Use `import.meta.env.VITE_*` in code, not `process.env`.
- **If env var still empty in browser after restart**: Vite may cache the old value. Clear `node_modules/.vite/`, restart dev server, and do a hard refresh (Cmd+Shift+R / Ctrl+Shift+F5). If still empty, see "Vite env not reaching client" in Common Errors.

**2. Reusable Cloudinary instance (config)**  
Create a config file (e.g. `src/cloudinary/config.ts`) so the rest of the app can use a single `cld` instance:
```ts
import { Cloudinary } from '@cloudinary/url-gen';

const cloudName = import.meta.env.VITE_CLOUDINARY_CLOUD_NAME;
if (!cloudName) {
  throw new Error('VITE_CLOUDINARY_CLOUD_NAME is not set. Add it to .env with the VITE_ prefix.');
}

export const cld = new Cloudinary({ cloud: { cloudName } });
export const uploadPreset = import.meta.env.VITE_CLOUDINARY_UPLOAD_PRESET || '';
```
- Use **this** pattern for the reusable instance. Everywhere else: `import { cld } from './cloudinary/config'` (or the path the user chose) and call `cld.image(publicId)` / `cld.video(publicId)`.

**3. Upload Widget (unsigned, from scratch)**  

**Strict pattern (always follow this exactly):**
1. **Script in `index.html`** (required): Add `<script src="https://upload-widget.cloudinary.com/global/all.js" async></script>` to `index.html`. Do **not** rely only on dynamic script injection from React โ€” it's fragile.
2. **Poll in useEffect** (required): In `useEffect`, poll with `setInterval` (e.g. every 100ms) until `typeof window.cloudinary?.createUploadWidget === 'function'`. Only then create the widget. A single check (even in `onload`) is **not** reliable because `window.cloudinary` can exist before `createUploadWidget` is attached.
3. **Add a timeout**: Set a timeout (e.g. 10 seconds) to stop polling and show an error if the script never loads. Clear both interval and timeout in cleanup.
4. **Create widget once**: When `createUp
Files: 5
Size: 54.5 KB
Complexity: 52/100
Category: Web Dev

Related in Web Dev