├── .npmrc ├── scripts ├── .gitignore ├── .env.example ├── assets.json ├── package.json ├── videos.json ├── upload-sample-images.js └── images.json ├── docs ├── styles │ ├── settings │ │ ├── __settings.scss │ │ └── _colors.scss │ ├── Docs.module.scss │ └── global.scss ├── components │ ├── Button │ │ ├── index.js │ │ └── Button.js │ ├── OgImage │ │ ├── index.js │ │ └── OgImage.js │ ├── Table │ │ ├── index.js │ │ └── Table.js │ ├── Video │ │ ├── index.js │ │ ├── Video.module.scss │ │ └── Video.js │ ├── CodeBlock │ │ ├── index.js │ │ ├── CodeBlock.js │ │ └── CodeBlock.module.scss │ ├── ImageGrid │ │ ├── index.js │ │ ├── ImageGrid.js │ │ └── ImageGrid.module.scss │ ├── HeaderImage │ │ ├── index.js │ │ ├── HeaderImage.js │ │ └── HeaderImage.module.scss │ └── ExamplesCldOgImage │ │ ├── index.js │ │ └── ExamplesCldOgImage.js ├── pages │ ├── templates │ │ └── _meta.json │ ├── cldimage │ │ ├── _meta.json │ │ └── basic-usage.mdx │ ├── cldogimage │ │ ├── _meta.json │ │ ├── examples.mdx │ │ ├── configuration.mdx │ │ └── basic-usage.mdx │ ├── getcldimageurl │ │ ├── _meta.json │ │ ├── basic-usage.mdx │ │ └── examples.mdx │ ├── getcldvideourl │ │ ├── _meta.json │ │ ├── configuration.mdx │ │ ├── examples.mdx │ │ └── basic-usage.mdx │ ├── clduploadbutton │ │ ├── _meta.json │ │ ├── configuration.mdx │ │ ├── basic-usage.mdx │ │ └── examples.mdx │ ├── getcldogimageurl │ │ ├── _meta.json │ │ ├── configuration.mdx │ │ ├── examples.mdx │ │ └── basic-usage.mdx │ ├── clduploadwidget │ │ ├── _meta.json │ │ └── signed-uploads.mdx │ ├── cldvideoplayer │ │ ├── _meta.json │ │ ├── transformations.mdx │ │ └── basic-usage.mdx │ ├── guides │ │ ├── _meta.json │ │ ├── using-custom-domains.mdx │ │ ├── image-underlays.mdx │ │ ├── background-removal.mdx │ │ ├── image-optimization.mdx │ │ ├── uploading-images-and-videos.mdx │ │ ├── image-overlays.mdx │ │ ├── remote-images.mdx │ │ ├── text-overlays.mdx │ │ └── social-media-card.mdx │ ├── api │ │ └── sign-cloudinary-params.js │ ├── _app.mdx │ ├── _meta.json │ ├── nextjs-14.mdx │ ├── installation.mdx │ └── changelog.mdx ├── public │ ├── favicon.ico │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── apple-touch-icon.png │ ├── favicon-1024x1024.png │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── browserconfig.xml │ └── site.webmanifest ├── postcss.config.js ├── lib │ ├── utils.js │ └── parse.js ├── .env.example ├── tailwind.config.js ├── .gitignore ├── package.json ├── next.config.js └── theme.config.js ├── pnpm-workspace.yaml ├── next-cloudinary ├── .gitignore ├── .npmignore ├── tests │ ├── nextjs-app │ │ ├── .eslintrc.json │ │ ├── next.config.js │ │ ├── app │ │ │ ├── head.tsx │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ │ ├── .gitignore │ │ ├── package.json │ │ ├── tsconfig.json │ │ └── README.md │ └── helpers │ │ ├── getCldOgImageUrl.spec.js │ │ ├── getCldImageUrl.spec.js │ │ └── getCldVideoUrl.spec.js ├── src │ ├── constants │ │ ├── sizes.ts │ │ └── analytics.ts │ ├── components │ │ ├── CldImage │ │ │ ├── index.ts │ │ │ └── CldImage.tsx │ │ ├── CldOgImage │ │ │ ├── index.ts │ │ │ └── CldOgImage.tsx │ │ ├── CldUploadButton │ │ │ ├── index.ts │ │ │ └── CldUploadButton.tsx │ │ ├── CldVideoPlayer │ │ │ ├── index.ts │ │ │ ├── CldVideoPlayer.types.ts │ │ │ └── CldVideoPlayer.tsx │ │ └── CldUploadWidget │ │ │ ├── index.ts │ │ │ └── CldUploadWidget.types.ts │ ├── lib │ │ ├── util.ts │ │ └── cloudinary.ts │ ├── helpers │ │ ├── getCldOgImageUrl.ts │ │ ├── getCldImageUrl.ts │ │ └── getCldVideoUrl.ts │ ├── index.ts │ └── loaders │ │ └── cloudinary-loader.ts ├── babel.config.js ├── tsup.config.ts ├── tsconfig.json ├── package.json └── plugins │ └── copy-assets.ts ├── .gitignore ├── package.json ├── .github ├── dependabot.yml ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── pull_request_template.md └── workflows │ └── test_and_release.yml ├── LICENSE ├── .releaserc ├── CONTRIBUTING.md └── CODE_OF_CONDUCT.md /.npmrc: -------------------------------------------------------------------------------- 1 | auto-install-peers = true -------------------------------------------------------------------------------- /scripts/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | node_modules -------------------------------------------------------------------------------- /docs/styles/settings/__settings.scss: -------------------------------------------------------------------------------- 1 | @import "colors"; -------------------------------------------------------------------------------- /docs/components/Button/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './Button'; -------------------------------------------------------------------------------- /docs/components/OgImage/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './OgImage'; -------------------------------------------------------------------------------- /docs/components/Table/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './Table'; -------------------------------------------------------------------------------- /docs/components/Video/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './Video'; -------------------------------------------------------------------------------- /docs/styles/settings/_colors.scss: -------------------------------------------------------------------------------- 1 | $color-cloudinary-orange: #ff5050; -------------------------------------------------------------------------------- /docs/components/CodeBlock/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './CodeBlock'; -------------------------------------------------------------------------------- /docs/components/ImageGrid/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './ImageGrid'; -------------------------------------------------------------------------------- /docs/components/HeaderImage/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './HeaderImage'; -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "docs" 3 | - "next-cloudinary" 4 | -------------------------------------------------------------------------------- /docs/pages/templates/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "social-media-cards": "Social Media Cards" 3 | } -------------------------------------------------------------------------------- /docs/components/ExamplesCldOgImage/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './ExamplesCldOgImage'; -------------------------------------------------------------------------------- /next-cloudinary/.gitignore: -------------------------------------------------------------------------------- 1 | # moduleResolution: Node(10) support 2 | /helpers.* 3 | /versions.ts -------------------------------------------------------------------------------- /next-cloudinary/.npmignore: -------------------------------------------------------------------------------- 1 | babel.config.js 2 | jest.config.js 3 | node_modules 4 | src 5 | tests -------------------------------------------------------------------------------- /next-cloudinary/tests/nextjs-app/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /next-cloudinary/src/constants/sizes.ts: -------------------------------------------------------------------------------- 1 | export const OG_IMAGE_WIDTH = 1200; 2 | export const OG_IMAGE_HEIGHT = 627; -------------------------------------------------------------------------------- /docs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudinary-community/next-cloudinary/HEAD/docs/public/favicon.ico -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode 3 | .env 4 | next-cloudinary/dist 5 | .idea 6 | tsconfig.tsbuildinfo 7 | .DS_Store 8 | -------------------------------------------------------------------------------- /docs/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /docs/public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudinary-community/next-cloudinary/HEAD/docs/public/favicon-16x16.png -------------------------------------------------------------------------------- /docs/public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudinary-community/next-cloudinary/HEAD/docs/public/favicon-32x32.png -------------------------------------------------------------------------------- /docs/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudinary-community/next-cloudinary/HEAD/docs/public/apple-touch-icon.png -------------------------------------------------------------------------------- /docs/public/favicon-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudinary-community/next-cloudinary/HEAD/docs/public/favicon-1024x1024.png -------------------------------------------------------------------------------- /next-cloudinary/src/components/CldImage/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './CldImage'; 2 | export type { CldImageProps } from './CldImage'; -------------------------------------------------------------------------------- /docs/pages/cldimage/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "basic-usage": "Basic Usage", 3 | "configuration": "Configuration", 4 | "examples": "Examples" 5 | } -------------------------------------------------------------------------------- /docs/pages/cldogimage/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "basic-usage": "Basic Usage", 3 | "configuration": "Configuration", 4 | "examples": "Examples" 5 | } -------------------------------------------------------------------------------- /docs/pages/getcldimageurl/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "basic-usage": "Basic Usage", 3 | "configuration": "Configuration", 4 | "examples": "Examples" 5 | } -------------------------------------------------------------------------------- /docs/pages/getcldvideourl/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "basic-usage": "Basic Usage", 3 | "configuration": "Configuration", 4 | "examples": "Examples" 5 | } -------------------------------------------------------------------------------- /docs/public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudinary-community/next-cloudinary/HEAD/docs/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /docs/public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudinary-community/next-cloudinary/HEAD/docs/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /next-cloudinary/src/components/CldOgImage/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './CldOgImage'; 2 | export type { CldOgImageProps } from './CldOgImage'; -------------------------------------------------------------------------------- /scripts/.env.example: -------------------------------------------------------------------------------- 1 | CLOUDINARY_CLOUD_NAME="" 2 | CLOUDINARY_API_KEY="" 3 | CLOUDINARY_API_SECRET="" -------------------------------------------------------------------------------- /docs/pages/clduploadbutton/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "basic-usage": "Basic Usage", 3 | "configuration": "Configuration", 4 | "examples": "Examples" 5 | } -------------------------------------------------------------------------------- /docs/pages/getcldogimageurl/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "basic-usage": "Basic Usage", 3 | "configuration": "Configuration", 4 | "examples": "Examples" 5 | } -------------------------------------------------------------------------------- /next-cloudinary/src/components/CldUploadButton/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './CldUploadButton'; 2 | export type { CldUploadButtonProps } from './CldUploadButton'; -------------------------------------------------------------------------------- /docs/lib/utils.js: -------------------------------------------------------------------------------- 1 | import {clsx } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | 8 | -------------------------------------------------------------------------------- /docs/pages/clduploadwidget/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "basic-usage": "Basic Usage", 3 | "configuration": "Configuration", 4 | "signed-uploads": "Signed Uploads", 5 | "examples": "Examples" 6 | } -------------------------------------------------------------------------------- /docs/pages/cldvideoplayer/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "basic-usage": "Basic Usage", 3 | "configuration": "Configuration", 4 | "transformations": "Transformations", 5 | "examples": "Examples" 6 | } -------------------------------------------------------------------------------- /next-cloudinary/src/components/CldVideoPlayer/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './CldVideoPlayer'; 2 | export type { CldVideoPlayerProps, CldVideoPlayerPropsLogo } from './CldVideoPlayer.types'; -------------------------------------------------------------------------------- /next-cloudinary/src/components/CldUploadWidget/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './CldUploadWidget'; 2 | export type { CldUploadWidgetProps, CldUploadWidgetPropsChildren } from './CldUploadWidget.types'; -------------------------------------------------------------------------------- /next-cloudinary/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = api => { 2 | if ( api.env('test') ) { 3 | return { 4 | presets: [['@babel/preset-env', {targets: {node: 'current'}}]], 5 | } 6 | } 7 | 8 | return {}; 9 | }; -------------------------------------------------------------------------------- /scripts/assets.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "publicId": "space-jelly-cosmo-helmet", 4 | "url": "https://res.cloudinary.com/colbycloud-next-cloudinary/image/upload/v1676058142/assets/space-jelly-cosmo-helmet.svg", 5 | "resourceType": "image" 6 | } 7 | ] -------------------------------------------------------------------------------- /scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "scripts", 3 | "version": "0.0.1", 4 | "scripts": { 5 | "upload": "node upload-sample-images.js" 6 | }, 7 | "devDependencies": { 8 | "cloudinary": "^1.32.0", 9 | "dotenv": "^16.4.5" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /next-cloudinary/tests/nextjs-app/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | env: { 4 | NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME: process.env.NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME || 'test' 5 | }, 6 | } 7 | 8 | module.exports = nextConfig 9 | -------------------------------------------------------------------------------- /docs/styles/Docs.module.scss: -------------------------------------------------------------------------------- 1 | @import "./settings/__settings"; 2 | 3 | .button { 4 | color: white; 5 | font-weight: bold; 6 | text-transform: uppercase; 7 | background-color: $color-cloudinary-orange; 8 | padding: .6em 1.2em; 9 | border: none; 10 | border-radius: 999px; 11 | } -------------------------------------------------------------------------------- /docs/public/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #da532c 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/components/ImageGrid/ImageGrid.js: -------------------------------------------------------------------------------- 1 | import styles from './ImageGrid.module.scss'; 2 | 3 | const ImageGrid = ({ children, columns = 2 }) => { 4 | return ( 5 |
    6 | { children } 7 |
8 | ) 9 | } 10 | 11 | export default ImageGrid; -------------------------------------------------------------------------------- /docs/.env.example: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME="" 2 | NEXT_PUBLIC_CLOUDINARY_API_KEY="" 3 | CLOUDINARY_API_SECRET="" 4 | NEXT_PUBLIC_CLOUDINARY_IMAGES_DIRECTORY="" 5 | NEXT_PUBLIC_CLOUDINARY_VIDEOS_DIRECTORY="" -------------------------------------------------------------------------------- /next-cloudinary/src/lib/util.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * triggerOnIdle 3 | * @see MDN Polyfill https://github.com/behnammodi/polyfill/blob/master/window.polyfill.js#L7-L24 4 | */ 5 | 6 | export function triggerOnIdle(callback: any) { 7 | if ( window && 'requestIdleCallback' in window ) { 8 | return requestIdleCallback(callback); 9 | } 10 | return setTimeout(() => callback(), 1); 11 | } -------------------------------------------------------------------------------- /next-cloudinary/tests/nextjs-app/app/head.tsx: -------------------------------------------------------------------------------- 1 | export default function Head() { 2 | return ( 3 | <> 4 | Create Next App 5 | 6 | 7 | 8 | 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /docs/components/ImageGrid/ImageGrid.module.scss: -------------------------------------------------------------------------------- 1 | .imageGrid { 2 | 3 | list-style: none; 4 | padding: 0; 5 | margin: 2em 0; 6 | display: grid; 7 | grid-gap: 3em; 8 | 9 | &[data-column-count="2"] { 10 | grid-template-columns: repeat(2, calc(50% - 1.5em)); 11 | } 12 | 13 | &[data-column-count="2"] { 14 | 15 | @media (max-width: 480px) { 16 | grid-template-columns: 1fr; 17 | } 18 | 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /docs/components/Video/Video.module.scss: -------------------------------------------------------------------------------- 1 | .video { 2 | margin-left: auto; 3 | margin-right: auto; 4 | 5 | figcaption { 6 | text-align: center; 7 | margin-top: 1em; 8 | } 9 | } 10 | 11 | .videoContainer { 12 | position: relative; 13 | overflow: hidden; 14 | 15 | iframe { 16 | position: absolute; 17 | top: 0; 18 | left: 0; 19 | width: 100%; 20 | height: 100%; 21 | border: 0; 22 | } 23 | } -------------------------------------------------------------------------------- /docs/styles/global.scss: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | main { 6 | flex-grow: 1; 7 | } 8 | 9 | h2 { 10 | padding-bottom: .5rem; 11 | margin-bottom: 1rem; 12 | } 13 | 14 | p { 15 | 16 | margin-bottom: 1.5rem; 17 | 18 | &:last-child { 19 | margin-bottom: 0; 20 | } 21 | 22 | } 23 | 24 | pre { 25 | display: grid; // Hack to prevent overflow 26 | } 27 | 28 | .nextra-callout a { 29 | text-decoration: underline; 30 | } -------------------------------------------------------------------------------- /next-cloudinary/tests/nextjs-app/app/layout.tsx: -------------------------------------------------------------------------------- 1 | export default function RootLayout({ 2 | children, 3 | }: { 4 | children: React.ReactNode 5 | }) { 6 | return ( 7 | 8 | {/* 9 | will contain the components returned by the nearest parent 10 | head.tsx. Find out more at https://beta.nextjs.org/docs/api-reference/file-conventions/head 11 | */} 12 | 13 | {children} 14 | 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /docs/lib/parse.js: -------------------------------------------------------------------------------- 1 | /** 2 | * getUrlParamsFromString 3 | */ 4 | 5 | export function getUrlParamsFromString(string) { 6 | let url; 7 | 8 | try { 9 | url = new URL(string); 10 | } catch (e) { 11 | throw new Error(`Failed to get URL params from string: ${e.message}`); 12 | } 13 | 14 | const params = new URLSearchParams(url.search); 15 | 16 | return Array.from(params.keys()).map((key) => { 17 | return { 18 | key, 19 | value: params.get(key), 20 | }; 21 | }); 22 | } -------------------------------------------------------------------------------- /docs/pages/guides/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "background-removal": "Background Removal", 3 | "image-optimization": "Image Optimization", 4 | "image-overlays": "Image Overlays", 5 | "image-underlays": "Image Underlays", 6 | "placeholders": "Placeholders", 7 | "responsive-images": "Responsive Images", 8 | "social-media-card": "Social Media Card", 9 | "text-overlays": "Text Overlays", 10 | "uploading-images-and-videos": "Uploading Images & Videos", 11 | "using-custom-domains": "Using Custom Domains" 12 | } -------------------------------------------------------------------------------- /docs/pages/api/sign-cloudinary-params.js: -------------------------------------------------------------------------------- 1 | import { v2 as cloudinary } from "cloudinary"; 2 | 3 | export default async function handler(req, res) { 4 | const { paramsToSign } = req.body; 5 | 6 | try { 7 | const signature = cloudinary.utils.api_sign_request( 8 | paramsToSign, 9 | process.env.CLOUDINARY_API_SECRET 10 | ); 11 | res.status(200).json({ 12 | signature, 13 | }); 14 | } catch (error) { 15 | res.status(500).json({ 16 | error: error.message, 17 | }); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /next-cloudinary/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, Options } from 'tsup' 2 | import { plugin as CopyAssetsPlugin } from './plugins/copy-assets'; 3 | 4 | const commonConfig: Options = { 5 | dts: true, 6 | external: ['react'], 7 | format: ['esm', 'cjs'], 8 | minify: true, 9 | sourcemap: true, 10 | }; 11 | 12 | export default defineConfig([ 13 | { 14 | ...commonConfig, 15 | entry: ['src/index.ts'], 16 | esbuildPlugins: [CopyAssetsPlugin] // Add plugin to copy assets on one of the entrypoints 17 | } 18 | ]); -------------------------------------------------------------------------------- /docs/public/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /docs/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | darkMode: ["class", 'html[class~="dark"]'], 4 | content: [ 5 | "./app/**/*.{js,ts,jsx,tsx,md,mdx}", 6 | "./pages/**/*.{js,ts,jsx,tsx,md,mdx}", 7 | "./components/**/*.{js,ts,jsx,tsx,md,mdx}", 8 | 9 | // Or if using `src` directory: 10 | "./src/**/*.{js,ts,jsx,tsx,md,mdx}", 11 | ], 12 | theme: { 13 | extend: { 14 | colors: { 15 | 'primary':'#3448C5', 16 | } 17 | }, 18 | }, 19 | plugins: [], 20 | } 21 | 22 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /next-cloudinary/src/constants/analytics.ts: -------------------------------------------------------------------------------- 1 | import nextPkg from 'next/package.json'; 2 | import pkg from '../../package.json'; 3 | 4 | export const NEXT_CLOUDINARY_ANALYTICS_PRODUCT_ID = 'A'; 5 | export const NEXT_CLOUDINARY_ANALYTICS_ID = 'V'; 6 | export const NEXT_VERSION = normalizeVersion(nextPkg.version); 7 | export const NEXT_CLOUDINARY_VERSION = normalizeVersion(pkg.version); 8 | 9 | function normalizeVersion(version: string) { 10 | let normalized = version; 11 | if ( normalized.includes('-') ) { 12 | normalized = normalized.split('-')[0]; 13 | } 14 | return normalized; 15 | } -------------------------------------------------------------------------------- /next-cloudinary/tests/nextjs-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /docs/components/HeaderImage/HeaderImage.js: -------------------------------------------------------------------------------- 1 | import styles from './HeaderImage.module.scss'; 2 | 3 | export const HeaderImage = ({ children, layout, caption }) => { 4 | return ( 5 |
6 |
7 | { children } 8 |
9 | {caption && ( 10 |

{ caption }

11 | )} 12 |
13 | ); 14 | }; 15 | 16 | export default HeaderImage; 17 | -------------------------------------------------------------------------------- /next-cloudinary/tests/nextjs-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@types/node": "^20.11.19", 13 | "@types/react": "^18.2.57", 14 | "@types/react-dom": "^18.2.19", 15 | "eslint": "^8.56.0", 16 | "eslint-config-next": "^14.1.0", 17 | "next": "^14.2.10", 18 | "react": "^18.2.0", 19 | "react-dom": "^18.2.0", 20 | "typescript": "^5.3.3" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /next-cloudinary/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/recommended/tsconfig.json", 3 | "compilerOptions": { 4 | "declaration": true, 5 | "declarationMap": true, 6 | "emitDeclarationOnly": true, 7 | "esModuleInterop": true, 8 | "jsx": "react", 9 | "lib": ["dom", "esnext"], 10 | "module": "nodenext", 11 | "moduleResolution": "nodenext", 12 | "noEmit": false, 13 | "resolveJsonModule": true, 14 | "sourceMap": true, 15 | "target": "esnext", 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | }, 22 | "exclude": ["node_modules"] 23 | } -------------------------------------------------------------------------------- /docs/components/ExamplesCldOgImage/ExamplesCldOgImage.js: -------------------------------------------------------------------------------- 1 | import { CldImage } from '../../../next-cloudinary'; 2 | import { OG_IMAGE_WIDTH, OG_IMAGE_HEIGHT } from '../../../next-cloudinary/src/constants/sizes'; 3 | 4 | const ExamplesCldOgImage = ({ ...props }) => { 5 | return ( 6 | 20 | ) 21 | } 22 | 23 | export default ExamplesCldOgImage; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next-cloudinary", 3 | "repository": "git@github.com:cloudinary-community/next-cloudinary.git", 4 | "author": "Cloudinary ", 5 | "license": "MIT", 6 | "private": true, 7 | "scripts": { 8 | "release": "semantic-release" 9 | }, 10 | "devDependencies": { 11 | "@colbyfayock/semantic-release-pnpm": "^1.2.2", 12 | "@semantic-release/changelog": "^6.0.3", 13 | "@semantic-release/git": "^10.0.1", 14 | "semantic-release": "^23.0.0" 15 | }, 16 | "packageManager": "pnpm@10.7.0+sha512.6b865ad4b62a1d9842b61d674a393903b871d9244954f652b8842c2b553c72176b278f64c463e52d40fff8aba385c235c8c9ecf5cc7de4fd78b8bb6d49633ab6" 17 | } 18 | -------------------------------------------------------------------------------- /docs/components/Button/Button.js: -------------------------------------------------------------------------------- 1 | import Link from 'next/link'; 2 | 3 | import { cn } from '../../lib/utils'; 4 | 5 | const Button = ({ children, className = '', href, onClick }) => { 6 | let buttonColor = 'text-white bg-primary hover:bg-blue-600'; 7 | 8 | const buttonStyles = cn('inline-block rounded py-2.5 px-6 text-lg font-bold uppercase', buttonColor, className); 9 | 10 | if ( href ) { 11 | return ( 12 | 13 | { children } 14 | 15 | ) 16 | } 17 | 18 | return ( 19 | 22 | ) 23 | } 24 | 25 | export default Button; -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" 9 | directory: "/next-cloudinary" 10 | schedule: 11 | interval: "weekly" 12 | - package-ecosystem: "npm" 13 | directory: "/" 14 | schedule: 15 | interval: "daily" 16 | allow: 17 | - dependency-name: "@cloudinary-util/url-loader" 18 | - dependency-name: "@cloudinary-util/util" 19 | -------------------------------------------------------------------------------- /docs/components/HeaderImage/HeaderImage.module.scss: -------------------------------------------------------------------------------- 1 | .headerImage { 2 | 3 | width: 100vw; 4 | padding: 1em; 5 | margin-left: -1.5rem; 6 | margin-right: -1.5rem; 7 | margin-top: 1.5rem; 8 | margin-bottom: 1.5rem; 9 | 10 | 11 | @media (min-width: 480px) { 12 | width: 100%; 13 | padding: 2em; 14 | border-radius: .25em; 15 | margin: 0; 16 | margin-top: 1.5rem; 17 | margin-bottom: 1.5rem; 18 | } 19 | 20 | } 21 | 22 | .headerImageChildren { 23 | 24 | display: flex; 25 | justify-content: center; 26 | max-width: 500px; 27 | margin: 0 auto; 28 | 29 | &[data-layout="grid"] { 30 | display: grid; 31 | max-width: 100%; 32 | grid-template-columns: 1fr 1fr; 33 | gap: 1em; 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /next-cloudinary/src/helpers/getCldOgImageUrl.ts: -------------------------------------------------------------------------------- 1 | import { OG_IMAGE_WIDTH, OG_IMAGE_HEIGHT } from '../constants/sizes'; 2 | 3 | import { getCldImageUrl } from './getCldImageUrl'; 4 | import type { GetCldImageUrlOptions } from './getCldImageUrl'; 5 | 6 | /** 7 | * getCldImageUrl 8 | */ 9 | 10 | export type GetCldOgImageUrlOptions = GetCldImageUrlOptions; 11 | 12 | export function getCldOgImageUrl(options: GetCldOgImageUrlOptions) { 13 | return getCldImageUrl({ 14 | ...options, 15 | format: options.format || 'jpg', 16 | width: options.width || OG_IMAGE_WIDTH, 17 | height: options.height || OG_IMAGE_HEIGHT, 18 | crop: options.crop || { 19 | type: 'fill', 20 | gravity: 'center', 21 | source: true 22 | } 23 | }); 24 | } -------------------------------------------------------------------------------- /docs/pages/_app.mdx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link'; 2 | import { Analytics } from '@vercel/analytics/react'; 3 | import { GoogleAnalytics } from "nextjs-google-analytics"; 4 | 5 | import 'nextra-theme-docs/style.css'; 6 | import '../styles/global.scss'; 7 | 8 | export default function Nextra({ Component, pageProps }) { 9 | return ( 10 | <> 11 | 12 |
13 | 14 |

15 | Next Cloudinary v6 now available! View Changelog 16 |

17 | 18 |
19 | 20 | 21 | 22 | ); 23 | } -------------------------------------------------------------------------------- /next-cloudinary/tests/nextjs-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true, 17 | "plugins": [ 18 | { 19 | "name": "next" 20 | } 21 | ], 22 | "baseUrl": ".", 23 | "paths": { 24 | "@/*": ["./*"] 25 | } 26 | }, 27 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 28 | "exclude": ["node_modules"] 29 | } 30 | -------------------------------------------------------------------------------- /next-cloudinary/src/helpers/getCldImageUrl.ts: -------------------------------------------------------------------------------- 1 | import { constructCloudinaryUrl } from '@cloudinary-util/url-loader'; 2 | import type { ImageOptions, ConfigOptions, AnalyticsOptions } from '@cloudinary-util/url-loader'; 3 | 4 | import { getCloudinaryConfig, getCloudinaryAnalytics } from "../lib/cloudinary"; 5 | 6 | /** 7 | * getCldImageUrl 8 | */ 9 | 10 | export type GetCldImageUrlOptions = ImageOptions; 11 | export type GetCldImageUrlConfig = ConfigOptions; 12 | export type GetCldImageUrlAnalytics = AnalyticsOptions; 13 | 14 | export function getCldImageUrl(options: GetCldImageUrlOptions, config?: GetCldImageUrlConfig, analytics?: GetCldImageUrlAnalytics) { 15 | return constructCloudinaryUrl({ 16 | options, 17 | config: getCloudinaryConfig(config), 18 | analytics: getCloudinaryAnalytics(analytics) 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Feature Request" 3 | about: "Suggest an idea or possible new feature for this project." 4 | title: "[Feature] " 5 | labels: "Type: Feature" 6 | --- 7 | 8 | # **Feature Request** 9 | 10 | ## **Is your feature request related to a problem? Please describe.** 11 | 12 | 13 | 14 | ## **Describe the solution you'd like** 15 | 16 | 17 | 18 | 19 | ## **Describe alternatives you've considered** 20 | 21 | 22 | 23 | ## **Additional context** 24 | 25 | 26 | -------------------------------------------------------------------------------- /next-cloudinary/src/helpers/getCldVideoUrl.ts: -------------------------------------------------------------------------------- 1 | import { constructCloudinaryUrl } from '@cloudinary-util/url-loader'; 2 | import type { VideoOptions, ConfigOptions, AnalyticsOptions } from '@cloudinary-util/url-loader'; 3 | 4 | import { getCloudinaryConfig, getCloudinaryAnalytics } from "../lib/cloudinary"; 5 | 6 | /** 7 | * getCldVideoUrl 8 | */ 9 | 10 | export type GetCldVideoUrlOptions = VideoOptions; 11 | export type GetCldVideoUrlConfig = ConfigOptions; 12 | export type GetCldVideoUrlAnalytics = AnalyticsOptions; 13 | 14 | export function getCldVideoUrl(options: GetCldVideoUrlOptions, config?: GetCldVideoUrlConfig, analytics?: GetCldVideoUrlAnalytics) { 15 | return constructCloudinaryUrl({ 16 | options: { 17 | assetType: 'video', 18 | format: 'auto:video', 19 | ...options 20 | }, 21 | config: getCloudinaryConfig(config), 22 | analytics: getCloudinaryAnalytics(analytics) 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@cloudinary-util/types": "^1.4.0", 13 | "@cloudinary-util/url-loader": "5.7.0", 14 | "@cloudinary-util/util": "^3.2.0", 15 | "@vercel/analytics": "^1.2.2", 16 | "cloudinary": "^2.0.1", 17 | "clsx": "^2.1.0", 18 | "next": "^14.1.0", 19 | "nextjs-google-analytics": "^2.3.3", 20 | "nextra": "^2.13.3", 21 | "nextra-theme-docs": "^2.13.3", 22 | "react": "^18.2.0", 23 | "react-dom": "^18.2.0", 24 | "react-icons": "^5.0.1", 25 | "sass": "^1.71.1", 26 | "tailwind-merge": "^2.2.1" 27 | }, 28 | "devDependencies": { 29 | "autoprefixer": "^10.4.17", 30 | "postcss": "^8.4.35", 31 | "tailwindcss": "^3.4.1" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Cloudinary 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/pages/getcldvideourl/configuration.mdx: -------------------------------------------------------------------------------- 1 | import Head from 'next/head'; 2 | 3 | import OgImage from '../../components/OgImage'; 4 | 5 | 6 | getCldVideoUrl Configuration - Next Cloudinary 7 | 8 | 9 | 10 | 11 | 15 | 16 | # getCldVideoUrl Configuration 17 | 18 | Configuration for getCldVideoUrl is the same as [getCldImageUrl](/getcldimageurl/configuration). 19 | 20 | The only difference is getCldVideoUrl provides the following default settings: 21 | 22 | | Option Name | Type | Default | 23 | |--------------------|--------------------|------------| 24 | | assetType | string | `"video"` | 25 | 26 | Additionally, the transformations do not have access to image-specific transformations. 27 | 28 | Find more configuration settings over at [getCldImageUrl configuration](/getcldimageurl/configuration). -------------------------------------------------------------------------------- /docs/components/CodeBlock/CodeBlock.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import { BsArrowsExpand, BsArrowsCollapse } from 'react-icons/bs' 3 | 4 | import { cn } from '../../lib/utils'; 5 | 6 | import styles from './CodeBlock.module.scss'; 7 | 8 | export const CodeBlock = ({ children, className }) => { 9 | const [expanded, setExpanded] = useState(false); 10 | 11 | return ( 12 |
13 |
14 | { children } 15 |
16 |
    17 | {!expanded && ( 18 |
  • 19 | 23 |
  • 24 | )} 25 | {expanded && ( 26 |
  • 27 | 31 |
  • 32 | )} 33 |
34 |
35 | ); 36 | }; 37 | 38 | export default CodeBlock; 39 | -------------------------------------------------------------------------------- /docs/next.config.js: -------------------------------------------------------------------------------- 1 | const withNextra = require('nextra')({ 2 | theme: 'nextra-theme-docs', 3 | themeConfig: './theme.config.js' 4 | }); 5 | 6 | module.exports = withNextra({ 7 | env: { 8 | ASSETS_DIRECTORY: process.env.NEXT_PUBLIC_CLOUDINARY_ASSETS_DIRECTORY || 'assets', 9 | IMAGES_DIRECTORY: process.env.NEXT_PUBLIC_CLOUDINARY_IMAGES_DIRECTORY || 'images', 10 | VIDEOS_DIRECTORY: process.env.NEXT_PUBLIC_CLOUDINARY_VIDEOS_DIRECTORY || 'videos' 11 | }, 12 | async redirects() { 13 | return [ 14 | { 15 | source: '/nextjs-13', 16 | destination: '/nextjs-14', 17 | permanent: false, 18 | }, 19 | { 20 | source: '/components/:path(.*)', 21 | destination: '/:path*', 22 | permanent: false, 23 | }, 24 | { 25 | source: '/helpers/:path(.*)', 26 | destination: '/:path*', 27 | permanent: false, 28 | }, 29 | { 30 | source: '/use-cases/:path(.*)', 31 | destination: '/guides/:path*', 32 | permanent: false, 33 | }, 34 | { 35 | source: '/resources', 36 | destination: '/', 37 | permanent: false, 38 | }, 39 | ]; 40 | } 41 | }); -------------------------------------------------------------------------------- /scripts/videos.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "publicId": "cooking-stirfry", 4 | "url": "https://res.cloudinary.com/colbycloud-next-cloudinary/video/upload/v1675968490/videos/cooking-stirfry.mp4" 5 | }, 6 | { 7 | "publicId": "mountain-stars", 8 | "url": "https://res.cloudinary.com/colbycloud-next-cloudinary/video/upload/v1675968484/videos/mountain-stars.mp4" 9 | }, 10 | { 11 | "publicId": "hang-gliding", 12 | "url": "https://res.cloudinary.com/colbycloud-next-cloudinary/video/upload/v1675968481/videos/hang-gliding.mp4" 13 | }, 14 | { 15 | "publicId": "skateboarding", 16 | "url": "https://res.cloudinary.com/colbycloud-next-cloudinary/video/upload/v1675968477/videos/skateboarding.mp4" 17 | }, 18 | { 19 | "publicId": "soccer", 20 | "url": "https://res.cloudinary.com/colbycloud-next-cloudinary/video/upload/v1675968473/videos/soccer.mp4" 21 | }, 22 | { 23 | "publicId": "waterfall", 24 | "url": "https://res.cloudinary.com/colbycloud-next-cloudinary/video/upload/v1675968467/videos/waterfall.mp4" 25 | }, 26 | { 27 | "publicId": "dog-running-snow", 28 | "url": "https://res.cloudinary.com/colbycloud-next-cloudinary/video/upload/v1675968457/videos/dog-running-snow.mp4" 29 | } 30 | ] -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "branches": [ 3 | "main", 4 | "next", 5 | "next-major", 6 | { 7 | "name": "beta", 8 | "prerelease": true 9 | }, 10 | { 11 | "name": "alpha", 12 | "prerelease": true 13 | } 14 | ], 15 | "plugins": [ 16 | [ 17 | "@semantic-release/commit-analyzer", 18 | { 19 | "preset": "angular", 20 | "releaseRules": [ 21 | { 22 | "type": "docs", 23 | "scope": "README", 24 | "release": "patch" 25 | } 26 | ], 27 | "parserOpts": { 28 | "noteKeywords": [ 29 | "BREAKING CHANGE", 30 | "BREAKING CHANGES" 31 | ] 32 | } 33 | } 34 | ], 35 | "@semantic-release/release-notes-generator", 36 | [ 37 | "@semantic-release/changelog", 38 | { 39 | "changelogFile": "CHANGELOG.md" 40 | } 41 | ], 42 | [ 43 | "@colbyfayock/semantic-release-pnpm", 44 | { 45 | "pkgRoot": "next-cloudinary", 46 | "publishBranch": "main|beta" 47 | } 48 | ], 49 | [ 50 | "@semantic-release/git", 51 | { 52 | "assets": [ 53 | "next-cloudinary/package.json", 54 | "CHANGELOG.md" 55 | ] 56 | } 57 | ], 58 | "@semantic-release/github" 59 | ] 60 | } 61 | -------------------------------------------------------------------------------- /next-cloudinary/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next-cloudinary", 3 | "version": "6.17.5", 4 | "license": "MIT", 5 | "main": "./dist/index.js", 6 | "module": "./dist/index.mjs", 7 | "types": "./dist/index.d.ts", 8 | "source": "src/index.ts", 9 | "scripts": { 10 | "build": "tsup", 11 | "dev": "tsup --watch", 12 | "prepublishOnly": "cp ../README.md . && cp ../LICENSE . && pnpm build", 13 | "postpublish": "rm ./README.md && rm ./LICENSE", 14 | "test": "vitest run", 15 | "test:app": "NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME=\"test\" pnpm build && cd tests/nextjs-app && npm install && npm run build", 16 | "test:watch": "vitest" 17 | }, 18 | "dependencies": { 19 | "@cloudinary-util/types": "1.5.10", 20 | "@cloudinary-util/url-loader": "5.10.4", 21 | "@cloudinary-util/util": "4.0.0" 22 | }, 23 | "devDependencies": { 24 | "@babel/core": "^7.25.2", 25 | "@babel/preset-env": "^7.25.3", 26 | "@tsconfig/recommended": "^1.0.7", 27 | "@types/node": "^22.0.2", 28 | "@types/react": "^18.3.3", 29 | "@types/react-dom": "^18.3.0", 30 | "dotenv": "^16.4.5", 31 | "mkdirp": "^3.0.1", 32 | "tsup": "^8.2.3", 33 | "typescript": "^5.5.4", 34 | "vitest": "^2.0.5" 35 | }, 36 | "peerDependencies": { 37 | "next": "^12 || ^13 || ^14 || >=15.0.0-rc || ^15", 38 | "react": "^17 || ^18 || >=19.0.0-beta || ^19" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /docs/pages/clduploadbutton/configuration.mdx: -------------------------------------------------------------------------------- 1 | import Head from 'next/head'; 2 | 3 | import OgImage from '../../components/OgImage'; 4 | 5 | 6 | CldUploadButton Configuration - Next Cloudinary 7 | 8 | 9 | 10 | 11 | 15 | 16 | # CldUploadButton Configuration 17 | 18 | ## Props 19 | 20 | CldUploadButton inherits all of the props associated with the [CldUploadWidget](/clduploadwidget/configuration) component including callback functions except for the `children` option. 21 | 22 | In addition, the following props are available: 23 | 24 | | Prop Name | Type | Example | 25 | |--------------------|--------------------|----------------------------------------| 26 | | className | string | `"my-button"` | 27 | | onClick | function | `function (event) { }` | 28 | 29 | `children` are rendered "as is" inside of the ` 39 | ) 40 | }} 41 | 42 | 43 |
46 |

CldUploadButton

47 | 48 |
49 |
52 |

CldVideoPlayer

53 | 59 |
60 | 61 | ) 62 | } 63 | -------------------------------------------------------------------------------- /docs/pages/getcldvideourl/examples.mdx: -------------------------------------------------------------------------------- 1 | import Head from 'next/head'; 2 | import { Callout } from 'nextra-theme-docs'; 3 | 4 | import { CldImage, getCldVideoUrl } from '../../../next-cloudinary'; 5 | 6 | import OgImage from '../../components/OgImage'; 7 | import ImageGrid from '../../components/ImageGrid'; 8 | 9 | 10 | getCldVideoUrl Examples - Next Cloudinary 11 | 12 | 13 | 14 | 15 | 19 | 20 | # getCldVideoUrl Examples 21 | 22 | 23 |
  • 24 | ### Basic 25 | 26 |
    27 | 28 |
  • 48 |
  • 49 | ### Cropping & Resizing 50 | 51 |
    52 | 53 |
  • 77 |
    -------------------------------------------------------------------------------- /next-cloudinary/tests/nextjs-app/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | ``` 14 | 15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 16 | 17 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 18 | 19 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. 20 | 21 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. 22 | 23 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 24 | 25 | ## Learn More 26 | 27 | To learn more about Next.js, take a look at the following resources: 28 | 29 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 30 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 31 | 32 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 33 | 34 | ## Deploy on Vercel 35 | 36 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 37 | 38 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 39 | -------------------------------------------------------------------------------- /docs/components/Table/Table.js: -------------------------------------------------------------------------------- 1 | const Table = ({ columns, data }) => { 2 | return ( 3 | 4 | {Array.isArray(columns) && ( 5 | 6 | 7 | {columns.map(({ title, id }) => { 8 | return ( 9 | 12 | ) 13 | })} 14 | 15 | 16 | )} 17 | {Array.isArray(data) && ( 18 | 19 | {data.map((row, index) => { 20 | return ( 21 | 22 | { columns.map(({ id }, index) => { 23 | let Child = row[id] || ' '; 24 | 25 | if ( typeof Child === 'function' ) { 26 | Child = 27 | } 28 | 29 | if ( index === 0 ) { 30 | return ( 31 | 34 | ) 35 | } 36 | return ( 37 | 40 | ) 41 | })} 42 | 43 | ) 44 | })} 45 | 46 | )} 47 |
    10 | { title || ' ' } 11 |
    32 | { Child } 33 | 38 | { Child } 39 |
    48 | ) 49 | } 50 | 51 | export default Table; -------------------------------------------------------------------------------- /docs/pages/guides/image-underlays.mdx: -------------------------------------------------------------------------------- 1 | import Head from 'next/head'; 2 | import { Tab, Tabs } from 'nextra-theme-docs'; 3 | 4 | import OgImage from '../../components/OgImage'; 5 | 6 | import { CldImage } from '../../../next-cloudinary'; 7 | 8 | 9 | Image Underlays - Next Cloudinary 10 | 11 | 12 | 13 | 14 | 18 | 19 | # Adding Layers Under Images 20 | 21 | Underlays function very similar to overlays in terms of options, however they **do not support text**. 22 | 23 | See the examples above under Overlays to learn more about the available configurations. 24 | 25 | ## Example 26 | 27 |
    28 | 37 |
    38 | 39 | 40 | 41 | ```jsx copy 42 | import { CldImage } from 'next-cloudinary'; 43 | 44 | 53 | ``` 54 | 55 | 56 | ```jsx copy 57 | import { getCldImageUrl } from 'next-cloudinary'; 58 | 59 | getCldImageUrl({ 60 | width: 960, 61 | height: 600, 62 | src: 'images/turtle', 63 | removeBackground: true, 64 | underlay: 'images/galaxy' 65 | }) 66 | ``` 67 | 68 | 69 | 70 | ## Learn More 71 | * [CldImage](/cldimage/basic-usage) 72 | * [getCldImageUrl](/getcldimageurl/basic-usage) -------------------------------------------------------------------------------- /scripts/images.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "publicId": "city-skyline", 4 | "url": "https://user-images.githubusercontent.com/1045274/198430381-45a4e8ce-a153-46b4-8033-f308efda680e.jpeg" 5 | }, 6 | { 7 | "publicId": "cloudinary-white", 8 | "url": "https://res.cloudinary.com/colbycloud-next-cloudinary/image/upload/v1666934571/images/cloudinary-white.svg" 9 | }, 10 | { 11 | "publicId": "cloudinary-logo-white", 12 | "url": "https://res.cloudinary.com/colbycloud-next-cloudinary/image/upload/images/cloudinary-logo-white.svg" 13 | }, 14 | { 15 | "publicId": "earth", 16 | "url": "https://user-images.githubusercontent.com/1045274/198430383-2d91bc89-63a8-448c-b322-37ead1fc3be2.jpeg" 17 | }, 18 | { 19 | "publicId": "galaxy", 20 | "url": "https://user-images.githubusercontent.com/1045274/198429472-f6dbc643-13bb-4fea-9597-8ca5c691997f.jpg" 21 | }, 22 | { 23 | "publicId": "mountain", 24 | "url": "https://user-images.githubusercontent.com/1045274/198429478-3372fb00-3641-46b1-be6f-d9ec372a340d.jpg" 25 | }, 26 | { 27 | "publicId": "next-cloudinary-social-background", 28 | "url": "https://user-images.githubusercontent.com/1045274/198507882-59802c05-ca72-4d8a-b630-ff38574dbd9b.png" 29 | }, 30 | { 31 | "publicId": "nextjs-white", 32 | "url": "https://res.cloudinary.com/colbycloud-next-cloudinary/image/upload/v1666934571/images/nextjs-white.svg" 33 | }, 34 | { 35 | "publicId": "sneakers", 36 | "url": "https://user-images.githubusercontent.com/1045274/198430384-59e3773d-8b62-4c7b-8632-e768385739ed.jpeg" 37 | }, 38 | { 39 | "publicId": "turtle", 40 | "url": "https://user-images.githubusercontent.com/1045274/198430387-09596747-29fe-4e02-a577-99aee29a2b3f.jpeg" 41 | }, 42 | { 43 | "publicId": "white", 44 | "url": "https://user-images.githubusercontent.com/1045274/198429482-5c938801-d6af-4d8f-b579-8032d4f12071.png" 45 | }, 46 | { 47 | "publicId": "woman-headphones", 48 | "url": "https://user-images.githubusercontent.com/1045274/198430389-778e5118-0e08-44f0-817e-44ba4a5de411.jpeg" 49 | } 50 | ] -------------------------------------------------------------------------------- /docs/pages/guides/background-removal.mdx: -------------------------------------------------------------------------------- 1 | import Head from 'next/head'; 2 | import { Callout, Tab, Tabs } from 'nextra-theme-docs'; 3 | 4 | import OgImage from '../../components/OgImage'; 5 | 6 | import { CldImage } from '../../../next-cloudinary'; 7 | 8 | 9 | Background Removal - Next Cloudinary 10 | 11 | 12 | 13 | 14 | 18 | 19 | # Removing a Background from an Image 20 | 21 | The CldImage component allows you to easily remove backgrounds from images using the `removeBackground` prop. 22 | 23 | 24 | Removing backgrounds require enabling the [Cloudinary AI Background Removal Add-On](https://cloudinary.com/documentation/cloudinary_ai_background_removal_addon) which includes a free tier for getting started. 25 | 26 | 27 | ## Example 28 | 29 |
    30 | 38 |
    39 | 40 | 41 | 42 | ```jsx copy 43 | import { CldImage } from 'next-cloudinary'; 44 | 45 | 53 | ``` 54 | 55 | 56 | ```jsx copy 57 | import { getCldImageUrl } from 'next-cloudinary'; 58 | 59 | getCldImageUrl({ 60 | width: 960, 61 | height: 600, 62 | src: 'images/turtle', 63 | removeBackground: true 64 | }) 65 | ``` 66 | 67 | 68 | 69 | ## Learn More 70 | * [CldImage](/cldimage/basic-usage) 71 | * [getCldImageUrl](/getcldimageurl/basic-usage) -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind are welcome! 3 | 4 | ## Issues 5 | 6 | ### Creating an Issue 7 | If you find a bug or problem, or maybe the documentation just doesn't make sense, please create an Issue to document the concern. 8 | 9 | ### Description 10 | Please be descriptive in your Issue. The more info you provide, the more likely someone will be able to help. 11 | 12 | ### Code Examples 13 | If you're experiencing an issue with the code, the most helpful thing you can do is create an example where you can reproduce the problem. This can be an open-source GitHub repo, a private repo you can share with the maintainers, a [CodeSandbox](https://codesandbox.io/), or anything to show the issue live with code alongside it. 14 | 15 | ## Pull Requests 16 | 17 | ### Creating a Pull Request 18 | If you're able to fix an active Issue, feel free to create a new Pull Request addressing the problem. There are no guarantees that the code will be merged in "as is", but chances are, if you're willing to work with the maintainers, everyone will be able to come up with a solution everyone can be happy with. 19 | 20 | ### Description 21 | Please be descriptive in your Pull Request. Whether big or small, it's important to be able to see the context of a change throughout the history of a project. 22 | 23 | ### Linking Fixed Issues 24 | If the Pull Request is addressing an Issue, please link that issue by specifying the `Fixes [Issue #]` syntax within the Pull Request. 25 | 26 | ### Getting Added to All Contributors in the README.md 27 | Once your Pull Request is successfully merged, feel free to tag yourself using the [All Contributors syntax](https://allcontributors.org/docs/en/bot/usage), which will create a new Pull Request requesting to add you in. 28 | 29 | ``` 30 | @all-contributors please add for 31 | ``` 32 | 33 | If your Pull Request is merged in and you're not added, please let someone know if you don't want to tag yourself, as we want to recognize everyone for their help. 34 | -------------------------------------------------------------------------------- /next-cloudinary/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as CldImage } from './components/CldImage'; 2 | export type { CldImageProps } from './components/CldImage'; 3 | 4 | export { default as CldOgImage } from './components/CldOgImage'; 5 | export type { CldOgImageProps } from './components/CldOgImage'; 6 | 7 | export { default as CldUploadButton } from './components/CldUploadButton'; 8 | export type { CldUploadButtonProps } from './components/CldUploadButton'; 9 | 10 | export { default as CldUploadWidget } from './components/CldUploadWidget'; 11 | export type { CldUploadWidgetProps, CldUploadWidgetPropsChildren } from './components/CldUploadWidget'; 12 | export type { 13 | CloudinaryUploadWidgetOptions, 14 | CloudinaryUploadWidgetResults, 15 | CloudinaryUploadWidgetInfo, 16 | CloudinaryUploadWidgetInstanceMethods, 17 | CloudinaryUploadWidgetInstanceMethodCloseOptions, 18 | CloudinaryUploadWidgetInstanceMethodDestroyOptions, 19 | CloudinaryUploadWidgetInstanceMethodOpenOptions, 20 | CloudinaryUploadWidgetInstanceMethodUpdateOptions, 21 | CloudinaryUploadWidgetSources, 22 | CloudinaryUploadWidgetError 23 | } from '@cloudinary-util/types'; 24 | 25 | export { default as CldVideoPlayer } from './components/CldVideoPlayer'; 26 | export type { CldVideoPlayerProps, CldVideoPlayerPropsLogo } from './components/CldVideoPlayer'; 27 | export type { CloudinaryVideoPlayer, CloudinaryVideoPlayerOptions, CloudinaryVideoPlayerOptionsColors, CloudinaryVideoPlayerOptionsLogo } from '@cloudinary-util/types'; 28 | 29 | export { cloudinaryLoader } from './loaders/cloudinary-loader'; 30 | export type { CloudinaryLoader, CloudinaryLoaderLoaderOptions, CloudinaryLoaderCldOptions } from './loaders/cloudinary-loader'; 31 | 32 | export { getCldImageUrl } from './helpers/getCldImageUrl'; 33 | export type { GetCldImageUrlOptions, GetCldImageUrlConfig, GetCldImageUrlAnalytics } from './helpers/getCldImageUrl'; 34 | 35 | export { getCldOgImageUrl } from './helpers/getCldOgImageUrl'; 36 | export type { GetCldOgImageUrlOptions } from './helpers/getCldOgImageUrl'; 37 | 38 | export { getCldVideoUrl } from './helpers/getCldVideoUrl'; 39 | export type { GetCldVideoUrlOptions, GetCldVideoUrlConfig, GetCldVideoUrlAnalytics } from './helpers/getCldVideoUrl'; -------------------------------------------------------------------------------- /docs/pages/clduploadbutton/basic-usage.mdx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import Head from 'next/head'; 3 | import { Callout } from 'nextra-theme-docs'; 4 | 5 | import { CldUploadButton } from '../../../next-cloudinary'; 6 | 7 | import OgImage from '../../components/OgImage'; 8 | 9 | import styles from '../../styles/Docs.module.scss'; 10 | 11 | 12 | CldUploadButton - Next Cloudinary 13 | 14 | 15 | 16 | 17 | 21 | 22 | # Getting Started with CldUploadButton 23 | 24 | The CldUploadButton creates a button element that uses an instance of the [Cloudinary Upload Widget](https://cloudinary.com/documentation/upload_widget) to give you an easy way to add upload capabilities to your Next.js app. 25 | 26 | The CldUploadButton component wraps the [CldUploadWidget](/clduploadwidget/basic-usage) component providing a pre-defined UI (a button). The same concepts apply, including having the option of using Signed or Unsigned uploads. 27 | 28 | ## Basic Usage 29 | 30 | ```jsx copy 31 | import { CldUploadButton } from 'next-cloudinary'; 32 | 33 | 34 | ``` 35 | 36 | 37 | Using the App Router in Next.js 13+? Add the `"use client"` directive at the top of your file. 38 | 39 | 40 | export const UnsignedUpload = () => { 41 | const [resource, setResource] = useState(); 42 | return ( 43 | <> 44 | { 47 | setResource(result?.info); 48 | widget.close(); 49 | }} 50 | uploadPreset="" 51 | /> 52 |

    URL: { resource?.secure_url }

    53 | 54 | ) 55 | } 56 | 57 |
    58 | 59 |
    60 | 61 | ## Learn More about CldUploadButton 62 | * [Configuration](/clduploadbutton/configuration) 63 | * [Examples](/clduploadbutton/examples) -------------------------------------------------------------------------------- /docs/pages/guides/image-optimization.mdx: -------------------------------------------------------------------------------- 1 | import Head from 'next/head'; 2 | import { Callout, Tab, Tabs } from 'nextra-theme-docs'; 3 | 4 | import OgImage from '../../components/OgImage'; 5 | import Video from '../../components/Video'; 6 | 7 | import { CldImage } from '../../../next-cloudinary'; 8 | 9 | 10 | Image Optimization - Next Cloudinary 11 | 12 | 13 | 14 | 15 | 19 | 20 | # Optimizing Images in Next.js 21 | 22 | Automatically optimize images using the CldImage component. By default, CldImage opts you in to automatic optimization including delivering the most optimal format for the browser (WebP, AVIF). 23 | 24 | You can further optimize delivery by using [responsive sizing](/guides/responsive-images) by using the `sizes` prop. 25 | 26 | ## Example 27 | 28 |
    29 | 36 |
    37 | 38 | 39 | 40 | ```jsx copy 41 | import { CldImage } from 'next-cloudinary'; 42 | 43 | 50 | ``` 51 | 52 | 53 | ```jsx copy 54 | import { getCldImageUrl } from 'next-cloudinary'; 55 | 56 | getCldImageUrl({ 57 | width: 960, 58 | height: 600, 59 | src: 'images/turtle' 60 | }); 61 | ``` 62 | 63 | 64 | 65 | ## Watch & Learn 66 | 67 |