diff --git a/.cursor/rules/cloudinary.mdc b/.cursor/rules/cloudinary.mdc
new file mode 100644
index 0000000..b11abd5
--- /dev/null
+++ b/.cursor/rules/cloudinary.mdc
@@ -0,0 +1,8 @@
+---
+description: Cloudinary cloudinary-react-native — agent guide
+alwaysApply: true
+---
+
+Read and follow `AGENTS.md` in the repository root. It is the single
+authoritative guide for this package: build/test commands, conventions,
+gotchas, and when to use this SDK versus a sibling Cloudinary package.
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 0000000..949b5a2
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,5 @@
+# Cloudinary cloudinary-react-native — instructions for AI coding agents
+
+Read `AGENTS.md` in the repository root and follow it. It is the single
+authoritative guide for this package: build/test commands, conventions,
+gotchas, and when to use this SDK versus a sibling Cloudinary package.
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..16ad627
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,72 @@
+# AGENTS.md — cloudinary-react-native
+
+## What this package is (one line)
+Official Cloudinary React Native / Expo SDK: upload media from a device and render Cloudinary images and video in-app, built on `@cloudinary/url-gen`.
+
+## When to use this / when NOT to use this
+- **Use this when:** you are in a **React Native or Expo app** and need to upload assets from the device (unsigned via upload preset, or signed via a server-generated signature) or render media through the `AdvancedImage` / `AdvancedVideo` components.
+- **Do NOT use this when:** you only need to build delivery URLs with no native components — use `@cloudinary/url-gen` directly.
+- **Sibling packages:**
+ - Fully native iOS (Swift/Obj-C, no RN) → [`cloudinary_ios`](https://github.com/cloudinary/cloudinary_ios)
+ - Fully native Android (Kotlin/Java, no RN) → [`cloudinary_android`](https://github.com/cloudinary/cloudinary_android)
+ - Plain web React (not RN) → [`@cloudinary/react`](https://github.com/cloudinary/frontend-frameworks)
+ - URL building only → [`@cloudinary/url-gen`](https://github.com/cloudinary/js-url-gen)
+ - Rule of thumb: React Native / Expo app → this package; native iOS/Android or web React → the matching SDK above.
+
+## Setup
+```bash
+npm install cloudinary-react-native
+# Video playback (pick one for your Expo SDK): expo-av (through SDK 54) or expo-video (recommended, SDK 52+)
+# CLDVideoLayer controls also need: @expo/vector-icons expo-font
+```
+No env vars are required to build URLs — only a `cloudName`. Uploads need an upload preset (unsigned) or a server-generated signature (signed). **Never embed `api_secret` in the app.**
+
+## Minimal runnable example
+```tsx
+import { AdvancedImage } from 'cloudinary-react-native';
+import { Cloudinary } from '@cloudinary/url-gen';
+import { View } from 'react-native';
+
+const cld = new Cloudinary({ cloud: { cloudName: 'demo' } });
+const img = cld.image('sample');
+
+export default function App() {
+ return (
+
+
+
+ );
+}
+```
+
+## Build / test commands (run these after editing)
+```bash
+npm install # CI uses npm (`npm ci`). package.json carries a (malformed) "packageManager": "^yarn@1.22.15" field, but CI runs npm — use npm.
+npm test # jest — run after any change to src/
+npm run typecheck # tsc --noEmit (not in CI; run it anyway)
+npm run lint # eslint "**/*.{js,ts,tsx}" (not in CI; run it anyway)
+npm run prepack # bob build — produces lib/ (commonjs, module, typescript); CI runs this
+```
+CI (`.github/workflows/ci.yml`) runs exactly: `npm ci` → `npm run prepack` → `npm test` on Node 18. `lint` and `typecheck` are real scripts but are **not** gated in CI — run them locally before opening a PR.
+
+## Conventions & gotchas
+- **Built on `@cloudinary/url-gen`.** URL/transformation building comes from there (`new Cloudinary(...)`, `cld.image()`, `cld.video()`); this package adds native components and device upload. Import URL-building symbols from `@cloudinary/url-gen`, components from `cloudinary-react-native`.
+- **Source vs build output.** Edit `src/`; `lib/` is generated by `react-native-builder-bob` (`npm run prepack`) and is git/lint/jest-ignored. Never hand-edit `lib/`.
+- **Formatter is Prettier via ESLint** (config inline in `package.json`): single quotes, 2-space, `trailingComma: es5`, no tabs. `npm run lint` enforces it.
+- **Tests** are jest with the `react-native` preset; Expo modules (`expo-av`, `expo-video`, `expo-constants`, `expo-crypto`) are mocked under `mocks/`. Add mocks there if you depend on a new Expo native module.
+- **Peer ranges (v1.3.0):** React `^18 || ^19`, React Native `>=0.79.0`, Expo `^50 || ^51 || ^52 || ^53`; `expo-constants` and `expo-modules-core` are required peers. `@expo/vector-icons`, `expo-av`, and `expo-video` are **optional** peers — only `CLDVideoLayer` and video playback need them. (`expo-font` appears only under `peerDependenciesMeta`, not in `peerDependencies` — it is not a declared peer.) The SDK auto-detects `expo-av` vs `expo-video`. `expo-video` is the recommended player from SDK 52; the `expo-av` package is deprecated in SDK 53 and removed in SDK 55 (last shipped in SDK 54) → prefer `expo-video`.
+- **Mobile security:** uploads use unsigned presets or server-side signatures only; full account credentials must never ship in the bundle.
+
+## Canonical docs (leave the repo for depth)
+- Product docs: https://cloudinary.com/documentation/
+- Transformations: https://cloudinary.com/documentation/image_transformations
+- Upload presets / signed uploads: https://cloudinary.com/documentation/upload_presets
+- API & SDK references: https://cloudinary.com/documentation/cloudinary_references
+- MCP servers (agent/no-code path): https://github.com/cloudinary/mcp-servers
+
+## Agent / MCP note
+If the same capability is exposed via the Cloudinary MCP servers, prefer the MCP tool for autonomous task execution and use this SDK for code generation. See cloudinary/mcp-servers.
+
+## Commit / PR conventions
+- **Conventional Commits** — releases run via `release-it` with the angular conventional-changelog preset (commit format `chore: release ${version}`, tag `v${version}`). Use `feat:` / `fix:` / `chore:` etc.
+- Before opening a PR: `npm test`, `npm run typecheck`, `npm run lint`, and confirm `npm run prepack` builds clean.
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..65d5769
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,30 @@
+@AGENTS.md
+
+# CLAUDE.md — cloudinary-react-native
+
+## What this repo is
+
+`cloudinary-react-native` is the official Cloudinary SDK for React Native and Expo apps: device uploads (`upload`, `unsignedUpload`, `uploadBase64`) and in-app media rendering via `AdvancedImage`, `AdvancedVideo`, and `CLDVideoLayer`. It bundles `@cloudinary/url-gen` as a direct dependency — URL-building imports come from there; components and upload functions come from this package.
+
+## Key constraints and gotchas
+
+- **Edit `src/` only.** `lib/` is generated by `react-native-builder-bob` (`npm run prepack`) and is git/lint/jest-ignored — never hand-edit it.
+- **Use npm, not yarn.** CI runs `npm ci` → `npm run prepack` → `npm test` on Node 18. The `packageManager` field in `package.json` names yarn, but CI is npm.
+- **Video peers are optional and version-sensitive.** `expo-av` (Expo SDK 50–51) and `expo-video` (SDK 52+) are auto-detected; install the one matching your Expo SDK. `expo-av` is deprecated in SDK 53 and removed in SDK 55 — prefer `expo-video`.
+- **`CLDVideoLayer` needs extra setup.** Install `@expo/vector-icons` and `expo-font` explicitly (`expo-font` is not a declared `peerDependency`, so no manager warning appears). Preload with `useFonts({ ...Ionicons.font })` before mounting the component.
+- **Mobile security.** Never embed `api_secret` in the bundle. Use unsigned uploads with an upload preset, or signed uploads where the signature is generated server-side.
+- **Formatter.** Prettier via ESLint (single quotes, 2-space indent, `trailingComma: es5`, no tabs). `npm run lint` enforces it.
+- **New Expo native modules** require jest mocks added to `mocks/` — the preset (`react-native`) does not auto-mock Expo modules.
+- **Conventional Commits.** Releases run via `release-it` with the angular changelog preset. Use `feat:` / `fix:` / `chore:` prefixes.
+
+## Verified build/test commands
+
+```bash
+npm install # install deps (CI uses npm ci)
+npm test # jest with react-native preset — run after any src/ change
+npm run typecheck # tsc --noEmit — not CI-gated; run before opening a PR
+npm run lint # eslint "**/*.{js,ts,tsx}" — not CI-gated; run before opening a PR
+npm run prepack # react-native-builder-bob build → lib/ — CI runs this
+```
+
+CI gate (`.github/workflows/ci.yml`, Node 18): `npm ci` → `npm run prepack` → `npm test`. `lint` and `typecheck` are real scripts but are not CI-gated — run them locally before a PR.
diff --git a/README.md b/README.md
index e961ff7..f8d1cd9 100644
--- a/README.md
+++ b/README.md
@@ -1,339 +1,138 @@
-Cloudinary React Native SDK
-=========================
-[](https://app.travis-ci.com/github/cloudinary/cloudinary-react-native)
-## About
-The Cloudinary React Native SDK allows you to quickly and easily integrate your application with Cloudinary.
-Effortlessly optimize and transform your cloud's assets.
-
-### Note
-This Readme provides basic installation and usage information.
-
-## Table of Contents
-- [Key Features](#key-features)
-- [Version Support](#Version-Support)
-- [Installation](#installation)
-- [Usage](#usage)
- - [Setup](#Setup)
- - [Transform and Optimize Assets](#Transform-and-Optimize-Assets)
- - [Uploading Assets](#Uploading-Assets)
-
-## Key Features
-Transform and optimize assets. Visit our documentation to learn more about [media optimization](https://cloudinary.com/documentation/media_optimization) and [transformations](https://cloudinary.com/documentation/image_transformations).
-
-## Version Support
-| SDK Version | React Native Version | Expo SDK Version | Video Library |
-|---------------|----------------------|---------------|---------|
-| 1.0.0 - 1.1.0 | >= 0.72 | 50 | expo-av |
-| 1.2.x > | >= 0.72 | 50-53 | expo-av / expo-video |
+# Cloudinary React Native SDK
-## Installation
-
-You can install the package using your preferred package manager:
-
-```bash
-# Using npm
-npm install cloudinary-react-native
+[](https://www.npmjs.com/package/cloudinary-react-native)
+[](https://www.npmjs.com/package/cloudinary-react-native)
+[](https://github.com/cloudinary/cloudinary-react-native/actions/workflows/ci.yml)
-# Using yarn
-yarn add cloudinary-react-native
+The `cloudinary-react-native` package is the Cloudinary SDK for React Native and Expo apps. Use it to upload assets from a device and render transformed, optimized images and video in-app through the `AdvancedImage`, `AdvancedVideo`, and `CLDVideoLayer` components. It bundles [`@cloudinary/url-gen`](https://github.com/cloudinary/js-url-gen) as a direct dependency for URL building. The current release (1.3.0) requires React 18 or 19, React Native 0.79 or later, and Expo SDK 50 through 53.
-# Using pnpm
-pnpm add cloudinary-react-native
-
-### For Video Player functionality
-The SDK supports both `expo-av` and `expo-video` libraries. The appropriate library will be automatically detected and used:
+## Installation
-**For Expo SDK 50-51 (expo-av):**
```bash
-npm install expo-av
+npm install cloudinary-react-native
```
-**For Expo SDK 52+ (expo-video - recommended):**
+Video playback needs one video backend, auto-detected at runtime: install `expo-video` (recommended, Expo SDK 52+) or `expo-av` (Expo SDK 50-54; deprecated). The `CLDVideoLayer` component also needs `@expo/vector-icons` and `expo-font`:
+
```bash
npm install expo-video
+npm install @expo/vector-icons expo-font
```
-**Note:** `expo-av` is deprecated in SDK 52 and removed in SDK 53. For newer Expo versions, use `expo-video`.
+## Configuration
-### For Video Layer with Controls (CLDVideoLayer)
-If you want to use the `CLDVideoLayer` component with UI controls, you need to install additional dependencies:
+This SDK runs on a device and never holds the API secret. Rendering and URL building need only your cloud name, which is safe to ship in the app. Initialize a `Cloudinary` instance from `@cloudinary/url-gen`, using the nested `cloud` config shape:
-```bash
-npm install @expo/vector-icons expo-font
-```
-Or
-```bash
-yarn add @expo/vector-icons expo-font
+```ts
+import { Cloudinary } from '@cloudinary/url-gen';
+
+const cld = new Cloudinary({
+ cloud: { cloudName: 'my_cloud_name' },
+ url: { secure: true },
+});
```
-## Usage
-### Setup
-The `Cloudinary` class is the main entry point for using the library. Your `cloud_name` is required to create an instance of this class. Your `api_key` and `api_secret` are also needed to perform secure API calls to Cloudinary (e.g., image and video uploads). Setting the configuration parameters can be done either programmatically using an appropriate constructor of the Cloudinary class or globally using an environment variable. You can find your account-specific configuration parameters in the **Dashboard** page of your [account console](https://cloudinary.com/console).
+Your cloud name is on the Dashboard of the [Console](https://console.cloudinary.com/console). Uploads from a device use an unsigned upload preset or a signature generated on a server. Keep the API secret out of the app bundle and out of version control — generate signatures server-side with a backend SDK.
-Here's an example of setting configuration parameters in your React Native application:
+## Quick examples
-```js
-import { AdvancedImage } from 'cloudinary-react-native';
-import { Cloudinary } from '@cloudinary/url-gen';
-```
+### Render an optimized image
-### Transform and Optimize Assets
-- [See full documentation](https://cloudinary.com/documentation/)
+`AdvancedImage` takes a `CloudinaryImage` through the `cldImg` prop and forwards other React Native `Image` props such as `style`. Applying `f_auto` and `q_auto` lets Cloudinary pick the format and quality for the device:
```tsx
+import { View } from 'react-native';
import { AdvancedImage } from 'cloudinary-react-native';
-import {Cloudinary} from '@cloudinary/url-gen';
+import { Cloudinary } from '@cloudinary/url-gen';
+import { format, quality } from '@cloudinary/url-gen/actions/delivery';
+import { auto } from '@cloudinary/url-gen/qualifiers/format';
+import { auto as qAuto } from '@cloudinary/url-gen/qualifiers/quality';
-const myCld = new Cloudinary({
- cloud: {
- cloudName: "demo",
- },
-});
+const cld = new Cloudinary({ cloud: { cloudName: 'demo' } });
-let img = myCld.image('sample');
+const img = cld
+ .image('sample')
+ .delivery(format(auto()))
+ .delivery(quality(qAuto()));
+// Delivers https://res.cloudinary.com/demo/image/upload/f_auto,q_auto/sample
-export default function App() {
+export default function Screen() {
return (
-
-
+
+
);
-};
+}
```
-### Video Player
-The `AdvancedVideo` component provides video playback capabilities with optional analytics tracking. **Note: This requires either `expo-av` (SDK 50-51) or `expo-video` (SDK 52+) to be installed.**
+### Upload a file from the device
-```tsx
-import { AdvancedVideo } from 'cloudinary-react-native';
-import {Cloudinary} from '@cloudinary/url-gen';
+`upload(cloudinary, { file, options, callback })` sends a local file URI to Cloudinary. Since the device holds no secret, pass an unsigned upload preset in `options`. The `callback` receives `(error, response)`, where `response` includes `public_id` and `secure_url`:
-const myCld = new Cloudinary({
- cloud: {
- cloudName: "demo",
- },
-});
+```ts
+import { upload, UploadApiOptions } from 'cloudinary-react-native';
+import { Cloudinary } from '@cloudinary/url-gen';
-let video = myCld.video('sea_turtle');
+const cld = new Cloudinary({ cloud: { cloudName: 'demo' }, url: { secure: true } });
-export default function App() {
- return (
-
-
-
- );
+const options: UploadApiOptions = {
+ upload_preset: 'sample_preset',
+ unsigned: true,
};
-```
-
-#### Video Player with Analytics
-Enable analytics tracking for detailed video performance insights:
-
-```tsx
-import { AdvancedVideo } from 'cloudinary-react-native';
-import {Cloudinary} from '@cloudinary/url-gen';
-const myCld = new Cloudinary({
- cloud: {
- cloudName: "demo",
+await upload(cld, {
+ file: '',
+ options,
+ callback: (error: any, response: any) => {
+ if (error) return console.warn(error);
+ console.log(response.public_id, response.secure_url);
},
});
-
-let video = myCld.video('sea_turtle');
-
-export default function App() {
- return (
-
-
-
- );
-};
```
-### Video Layer with Controls
-The `CLDVideoLayer` component provides a full-screen video experience with overlay controls, seekbar, and customizable actions. **Note: This requires `@expo/vector-icons` and `expo-font` to be installed.**
+### Render a video
+
+`AdvancedVideo` takes a `CloudinaryVideo` through `cldVideo` and styles with `videoStyle`. It needs `expo-video` or `expo-av` installed (auto-detected):
```tsx
-import React from 'react';
-import { View, StyleSheet } from 'react-native';
-import { CLDVideoLayer } from 'cloudinary-react-native';
+import { View } from 'react-native';
+import { AdvancedVideo } from 'cloudinary-react-native';
import { Cloudinary } from '@cloudinary/url-gen';
-import { useFonts } from 'expo-font';
-import { Ionicons } from '@expo/vector-icons';
-
-const myCld = new Cloudinary({
- cloud: {
- cloudName: "demo",
- },
-});
-
-export default function App() {
- // Preload fonts to prevent warnings
- const [fontsLoaded] = useFonts({
- ...Ionicons.font,
- });
-
- if (!fontsLoaded) {
- return null; // or a loading component
- }
-
- const video = myCld.video('sea_turtle');
- const handleBack = () => {
- // Handle back navigation
- };
-
- const handleShare = () => {
- // Handle custom share action
- };
+const cld = new Cloudinary({ cloud: { cloudName: 'demo' } });
+const video = cld.video('sea_turtle');
+// Delivers https://res.cloudinary.com/demo/video/upload/sea_turtle
+export default function Screen() {
return (
-
-
+
+
);
}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- backgroundColor: '#000',
- },
-});
-```
-
-### Uploading Assets
-The following example performs an unsigned upload of a `string` using the default settings, a request upload callback, and an upload preset (required for unsigned uploads):
-
-```javascript
- const cld = new Cloudinary({
- cloud: {
- cloudName: ''
- },
- url: {
- secure: true
- }
- });
-
- const options: UploadApiOptions = {
- upload_preset: 'sample_preset',
- unsigned: true,
- }
-
- await upload(cld, {file: filePath , options: options, callback: (error: any, response: any) => {
- //.. handle response
- }})
-```
-
-The uploaded image is assigned a randomly generated public ID, which is returned as part of the response object.
-The image is immediately available for download through a CDN:
-
- cloudinary.image().generate("generatedPublicId")
-
- http://res.cloudinary.com//image/upload/generatedPublicId.jpg
-
-You can also specify your own public ID:
-
-```javascript
-const options: UploadApiOptions = {
- upload_preset: 'sample_preset',
- publicId: "sample_remote",
-}
-
-await upload(cld, {file: filePath , options: options, callback: (error: any, response: any) => {
- //.. handle response
- }})
```
-For security reasons, mobile applications cannot contain the full account credentials, and so they cannot freely upload resources to the cloud.
-Cloudinary provides two different mechanisms to enable end-users to upload resources without providing full credentials.
-
-##### 1. Unsigned uploads using [Upload Presets.](https://cloudinary.com/documentation/upload_presets)
-You can create an upload preset in your Cloudinary account console, defining rules that limit the formats, transformations, dimensions and more.
-Once the preset is defined, it's name is supplied when calling upload. An upload call will only succeed if the preset name is used and the resource is within the preset's pre-defined limits.
-
-The following example uploads a local resource, available as a Uri, assuming a preset named 'sample_preset' already exists in the account:
-
-```javascript
- const options: UploadApiOptions = {
- upload_preset: 'sample_preset',
- unsigned: true,
-}
+## For AI agents
-await upload(cld, {file: uri , options: options, callback: (error: any, response: any) => {
- //.. handle response
- }})
-```
+`cloudinary-react-native` is the React Native and Expo SDK: device uploads (`upload`, `unsignedUpload`, `uploadBase64`) and in-app rendering through `AdvancedImage`, `AdvancedVideo`, and `CLDVideoLayer`. Import URL-building symbols (`Cloudinary`, `cld.image()`, `cld.video()`) from `@cloudinary/url-gen`; import components and upload functions from `cloudinary-react-native`. Never embed the API secret — uploads use an unsigned preset or a server-generated signature. For tasks this package doesn't cover, choose a different package:
-##### 2. Signed uploads with server-generated signature
-Another way to upload without including credentials is using signed uploads.
-You should generate the upload authentication signature on the server side, where it's safe to store the `api_secret`.
-For more information on how to sign upload you can visit our [documentation.](https://cloudinary.com/documentation/upload_images#generating_authentication_signatures)
-
-The Cloudinary React Native SDK allows you to provide a server-generated signature and any additional parameters that were generated on the server side (instead of signing using `api_secret` locally).
-
-Your server can use any Cloudinary libraries (Ruby on Rails, PHP, Python & Django, Java, Perl, .Net, etc.) for generating the signature. The following JSON in an example of a response of an upload authorization request to your server, For more information you can visit our [documentation](https://cloudinary.com/documentation/upload_images#generating_authentication_signatures):
-```json
- {
- "signature": "sgjfdoigfjdgfdogidf9g87df98gfdb8f7d6gfdg7gfd8",
- "public_id": "abdbasdasda76asd7sa789",
- "timestamp": 1346925631,
- "api_key": "123456789012345"
- }
-```
+| Task | Package |
+|---|---|
+| Fully native iOS app (Swift/Obj-C, no React Native) | [`cloudinary_ios`](https://github.com/cloudinary/cloudinary_ios) |
+| Fully native Android app (Kotlin/Java, no React Native) | [`cloudinary_android`](https://github.com/cloudinary/cloudinary_android) |
+| Render components in a web React app (not React Native) | [`@cloudinary/react`](https://github.com/cloudinary/frontend-frameworks) |
+| Build delivery URLs only, no native components | [`@cloudinary/url-gen`](https://github.com/cloudinary/js-url-gen) |
+| Server-side upload, asset administration, signing (holds the API secret) | [`cloudinary_npm`](https://github.com/cloudinary/cloudinary_npm) |
+| Run Cloudinary operations as agent tools | [Cloudinary MCP servers](https://github.com/cloudinary/mcp-servers) |
-Use the signature field to put the signature you got from your server, when using signature api key is required as well as part of the Cloudinary initialization.
+## Links
-```javascript
- const options: UploadApiOptions = {
- upload_preset: 'ios_sample',
- signature: "",
- }
- await upload(cld, {file: filePath , options: options, callback: (error: any, response: any) => {
- //.. handle response
- }})
-```
+- [React Native SDK guide](https://cloudinary.com/documentation/react_native_integration)
+- [Image transformations in React Native](https://cloudinary.com/documentation/react_native_image_transformations)
+- [Upload presets](https://cloudinary.com/documentation/upload_presets)
+- [Generating authentication signatures](https://cloudinary.com/documentation/authentication_signatures)
+- [Transformation and API references](https://cloudinary.com/documentation/cloudinary_references)
+- [Documentation llms.txt index](https://cloudinary.com/documentation/llms.txt)
+- [Package on npm](https://www.npmjs.com/package/cloudinary-react-native)
-## Contributions
-See [contributing guidelines](CONTRIBUTING.md).
-
-## Get Help
-If you run into an issue or have a question, you can either:
-- [Open a GitHub issue](https://github.com/cloudinary/cloudinary-react-native/issues) (for issues related to the SDK)
-- [Open a support ticket](https://cloudinary.com/contact) (for issues related to your account)
-
-## About Cloudinary
-Cloudinary is a powerful media API for websites and mobile apps alike, Cloudinary enables developers to efficiently manage, transform, optimize, and deliver images and videos through multiple CDNs. Ultimately, viewers enjoy responsive and personalized visual-media experiences—irrespective of the viewing device.
-
-## Additional Resources
-- [Cloudinary Transformation and REST API References](https://cloudinary.com/documentation/cloudinary_references): Comprehensive references, including syntax and examples for all SDKs.
-- [MediaJams.dev](https://mediajams.dev/): Bite-size use-case tutorials written by and for Cloudinary Developers.
-- [DevJams](https://www.youtube.com/playlist?list=PL8dVGjLA2oMr09amgERARsZyrOz_sPvqw): Cloudinary developer podcasts on YouTube.
-- [Cloudinary Academy](https://training.cloudinary.com/): Free self-paced courses, instructor-led virtual courses, and on-site courses.
-- [Code Explorers and Feature Demos](https://cloudinary.com/documentation/code_explorers_demos_index): A one-stop shop for all code explorers, Postman collections, and feature demos found in the docs.
-- [Cloudinary Roadmap](https://cloudinary.com/roadmap): Your chance to follow, vote, or suggest what Cloudinary should develop next.
-- [Cloudinary Facebook Community](https://www.facebook.com/groups/CloudinaryCommunity): Learn from and offer help to other Cloudinary developers.
-- [Cloudinary Account Registration](https://cloudinary.com/users/register/free): Free Cloudinary account registration.
-- [Cloudinary Website](https://cloudinary.com): Learn about Cloudinary's products, partners, customers, pricing, and more.
-
-## Licence
Released under the MIT license.