cloudinary-react
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.
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 `createUpRelated in Web Dev
generating-lwc-components
IncludedLightning Web Components with PICKLES methodology and 165-point scoring. Use this skill when the user creates or edits LWC components, builds wire service patterns, or writes Jest tests for LWC. TRIGGER when: user creates/edits LWC components, touches lwc/**/*.js, .html, .css, .js-meta.xml files, or asks about wire service, SLDS, or Jest LWC tests. DO NOT TRIGGER when: Apex classes (use generating-apex), Aura components, or Visualforce.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Set up queries with useQuery, mutations with useMutation, configure QueryClient caching strategies, implement optimistic updates, and handle infinite scroll with useInfiniteQuery. Use when: setting up data fetching in React projects, migrating from v4 to v5, or fixing object syntax required errors, query callbacks removed issues, cacheTime renamed to gcTime, isPending vs isLoading confusion, keepPreviousData removed problems.
document-processor-api
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
nutrient-document-processing
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Covers useMutationState, simplified optimistic updates, throwOnError, network mode (offline/PWA), and infiniteQueryOptions. Use when setting up data fetching, fixing v4โv5 migration errors (object syntax, gcTime, isPending, keepPreviousData), or debugging SSR/hydration issues with streaming server components.
accelint-nextjs-best-practices
IncludedNext.js performance optimization and best practices. Use when writing Next.js code (App Router or Pages Router); implementing Server Components, Server Actions, or API routes; optimizing RSC serialization, data fetching, or server-side rendering; reviewing Next.js code for performance issues; fixing authentication in Server Actions; or implementing Suspense boundaries, parallel data fetching, or request deduplication.