1"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[461],{9041:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>u,frontMatter:()=>a,metadata:()=>s,toc:()=>d});var i=t(4848),r=t(8453);const a={},o=void 0,s={id:"js-cookbook/image-libraries",title:"image-libraries",description:"ImageKit",source:"@site/docs/js-cookbook/14-image-libraries.md",sourceDirName:"js-cookbook",slug:"/js-cookbook/image-libraries",permalink:"/docs/js-cookbook/image-libraries",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:14,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"data-validation",permalink:"/docs/js-cookbook/data-validation"},next:{title:"notification-libraries",permalink:"/docs/js-cookbook/notification-libraries"}},l={},d=[{value:"ImageKit",id:"imagekit",level:2},{value:"NextJS starter",id:"nextjs-starter",level:3},{value:"Installation",id:"installation",level:4},{value:"Client side media display",id:"client-side-media-display",level:4},{value:"Server side setup",id:"server-side-setup",level:4},{value:"Server side uploading",id:"server-side-uploading",level:4},{value:"AI transformations",id:"ai-transformations",level:4}];function c(e){const n={code:"code",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"imagekit",children:"ImageKit"}),"\n",(0,i.jsx)(n.h3,{id:"nextjs-starter",children:"NextJS starter"}),"\n",(0,i.jsx)(n.h4,{id:"installation",children:"Installation"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-embed",children:'title: "Next.js ImageKit SDK"\nimage: "https://ik.imgkit.net/ikmedia/logo/light_T4buIzohVH.svg"\ndescription: "Real-time image & video resizing, automatic optimization, and file uploading in Next.js using ImageKit.io."\nurl: "https://imagekit.io/docs/integration/nextjs"\nfavicon: ""\naspectRatio: "21"\n'})}),"\n",(0,i.jsx)(n.p,{children:"First, install."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"npm install @imagekit/next \n"})}),"\n",(0,i.jsx)(n.p,{children:"Then set the environment variables:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'NEXT_PUBLIC_IMAGEKIT_PUBLIC_KEY="your_public_key"\nIMAGEKIT_PRIVATE_KEY="your_private_key"\nNEXT_PUBLIC_IMAGEKIT_URL_ENDPOINT="https://ik.imagekit.io/your_id"\n'})}),"\n",(0,i.jsx)(n.h4,{id:"client-side-media-display",children:"Client side media display"}),"\n",(0,i.jsxs)(n.p,{children:["Then you can then render images and videos like so using the ",(0,i.jsx)(n.code,{children:"<Image />"})," and ",(0,i.jsx)(n.code,{children:"<Video />"})," component from ",(0,i.jsx)(n.code,{children:"@imagekit/next"})," respectively, automatically uploading images to a bucket or rendering them if the src relative to the URL endpoint already exists."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tsx",children:'//import Image from \'next/image\'\nimport { Image } from \'@imagekit/next\';\n\nexport default function Page() {\n return (\n <Image\n urlEndpoint="https://ik.imagekit.io/your_imagekit_id" // your bucket\n src="/profile.png"\n width={500}\n height={500}\n alt="Picture of the author"\n />\n )\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"Here are the possible props on both components:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"urlEndpoint"}),": the imagekit endpoint of your imagekit app, which is the bucket of all media assets you store in a specific imagekit app.","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["If you have rendered this inside an ",(0,i.jsx)(n.code,{children:"<ImageKitProvider />"})," component, the ",(0,i.jsx)(n.code,{children:"urlEndpoint"})," is automatically inferring from that provider so you don't have to provide this prop each time on individual ",(0,i.jsx)(n.code,{children:"<Image />"})," or ",(0,i.jsx)(n.code,{children:"<Video />"})," components."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"src"}),": the url path of the uploaded media asset you want to render relative to the ",(0,i.jsx)(n.code,{children:"urlEndpoint"}),", to render that full url if it does exist."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"transformation"}),": an array of sequential image transformation methods to apply to the image, either for rendering or uploading."]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tsx",children:'import { Video } from \'@imagekit/next\';\nexport default function Page() {\n return (\n <Video\n urlEndpoint="https://ik.imagekit.io/your_imagekit_id"\n src="/video.mp4"\n controls\n width={500}\n height={500}\n transformation={[\n {\n width: 800,\n height: 400,\n crop: "at_max",\n quality: 80,\n },\n {\n blur: 2,\n },\n ]}\n />\n )\n}\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tsx",children:'import { Image } from \'@imagekit/next\';
1\n\nexport default function Page() {\n return (\n <Image\n urlEndpoint="https://ik.imagekit.io/your_imagekit_id"\n src="/profile.png"\n width={500}\n height={500}\n alt="Picture of the author"\n transformation={[{ width: 500, height: 500 }]}\n />\n )\n}\n'})}),"\n",(0,i.jsx)(n.h4,{id:"server-side-setup",children:"Server side setup"}),"\n",(0,i.jsx)(n.p,{children:"First create a route that authenticates with the imagekit public and private keys"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",metastring:'title="app/api/upload-auth/route.ts"',children:'import { getUploadAuthParams } from "@imagekit/next/server";\nimport { NextResponse } from "next/server";\n\nexport async function GET() {\n const authParams = getUploadAuthParams({\n privateKey: process.env.IMAGEKIT_PRIVATE_KEY!,\n publicKey: process.env.NEXT_PUBLIC_IMAGEKIT_PUBLIC_KEY!,\n });\n\n return NextResponse.json(authParams);\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Then create an imagekit provider that authenticates with those keys by fetching that route and also provide your ",(0,i.jsx)(n.code,{children:"urlEndpoint"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tsx",children:'"use client";\nimport { ImageKitProvider } from "@imagekit/next";\n\nconst urlEndpoint = process.env.NEXT_PUBLIC_IMAGEKIT_URL_ENDPOINT;\nconst publicKey = process.env.NEXT_PUBLIC_IMAGEKIT_PUBLIC_KEY;\n\nexport default function Providers({ children }: { children: React.ReactNode }) {\n const authenticator = async () => {\n try {\n const response = await fetch("/api/upload-auth");\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Request failed with status ${response.status}: ${errorText}`,\n );\n }\n\n const data = await response.json();\n const { signature, expire, token } = data;\n return { signature, expire, token };\n } catch (error) {\n throw new Error(`Authentication request failed: ${error}`);\n }\n };\n\n return (\n <ImageKitProvider\n urlEndpoint={urlEndpoint}\n publicKey={publicKey}\n authenticator={authenticator}\n >\n {children}\n </ImageKitProvider>\n );\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"To build URLs with transformation parameters from a specific media source, you can use this utility:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:'import { buildSrc } from "@imagekit/next";\n\nfunction buildTransformedUrl(path: string) {\n\tconst url = buildSrc({\n\t src: `https://ik.imagekit.io/your_id/${path}`,\n\t transformation: [{ width: 300, height: 300 }],\n\t});\n\treturn url\n}\n'})}),"\n",(0,i.jsx)(n.h4,{id:"server-side-uploading",children:"Server side uploading"}),"\n",(0,i.jsxs)(n.p,{children:["The\xa0",(0,i.jsx)(n.code,{children:"IKUpload"}),"\xa0component provides a secure way to upload files directly to ImageKit."]}),"\n",(0,i.jsx)(n.p,{children:"Here are the parameters:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"folder"}),": Specify the folder path (e.g.,\xa0",(0,i.jsx)(n.code,{children:'"/users/avatars"'}),")."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"isPrivateFile"}),": If true, the file will be marked private."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"onUploadProgress"}),": Callback for progress monitoring."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"validateFile"}),": Client-side validation function."]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tsx",children:'"use client";\nimport { IKUpload } from "@imagekit/next";\n\nexport default function MyUploadComponent() {\n const onError = (err: any) => {\n console.log("Error", err);\n };\n\n const onSuccess = (res: any) =>
1 {\n console.log("Success", res);\n };\n\n return (\n <IKUpload\n fileName="test-upload.png"\n tags={["sample-tag"]}\n useUniqueFileName={true}\n onError={onError}\n onSuccess={onSuccess}\n />\n );\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"here is an example of uploading imperatively by calling an upload API and creating a common image preview component:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tsx",children:'import { useRef, useState } from "react";\nimport { Button } from "@/components/ui/button";\nimport { Card } from "@/components/ui/card";\nimport { ImageIcon, Loader2, X } from "lucide-react";\nimport { toast } from "sonner";\nimport { upload } from "@imagekit/next";\nimport Image from "next/image";\n\ninterface UploadProps {\n onUploadSuccess: (url: string) => void;\n onUploadError: () => void;\n fileInputRef: ReturnType<useRef<HTMLInputElement>>;\n generateUniqueFilename: (filename: string) => string;\n authenticationRoute?: string\n}\n\nconst MAX_FILE_SIZE = 1 * 1024 * 1024; // 1MB in bytes\n\nexport default function useImagekitUpload({\n onUploadSuccess,\n onUploadError,\n fileInputRef,\n generateUniqueFilename,\n authenticationRoute = "/api/imagekit-auth" // custom route for server-side\n}: UploadProps) {\n const [file, setFile] = useState<File | null>(null);\n const [previewUrl, setPreviewUrl] = useState<string | null>(null);\n const [isUploading, setIsUploading] = useState(false);\n const [uploadedUrl, setUploadedUrl] = useState<string | null>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const handleFileSelect = async (selectedFile: File) => {\n // Validate file type\n if (!selectedFile.type.startsWith("image/")) {\n toast.error("Please select an image file");\n onUploadError();\n return;\n }\n\n // Validate file size\n if (selectedFile.size > MAX_FILE_SIZE) {\n toast.error("Image must be less than 1MB");\n onUploadError();\n return;\n }\n\n setFile(selectedFile);\n\n // Create preview\n const reader = new FileReader();\n reader.onload = (e) => {\n setPreviewUrl(e.target?.result as string);\n };\n reader.readAsDataURL(selectedFile);\n };\n\n const uploadToImageKit = async (fileToUpload: File) => {\n setIsUploading(true);\n\n try {\n // Fetch authentication parameters from our API route\n const authResponse = await fetch("/api/imagekit-auth");\n if (!authResponse.ok) {\n throw new Error("Failed to get upload authentication");\n }\n\n const authData = await authResponse.json();\n\n // Upload to ImageKit\n const result = await upload({\n file: fileToUpload,\n fileName: `profile-${Date.now()}-${fileToUpload.name}`,\n folder: "/profile-pictures",\n useUniqueFileName: true,\n token: authData.token,\n signature: authData.signature,\n expire: authData.expire,\n publicKey: process.env.NEXT_PUBLIC_IMAGEKIT_PUBLIC_KEY!,\n // IMAGEKIT automatically transforms to webp\n // transformation: {\n // pre: "format(webp)",\n // },\n });\n\n setUploadedUrl(result.url || null);\n onUploadSuccess(result.url || "");\n } catch (error) {\n console.error("Upload error:", error);\n onUploadError();\n clearFile();\n } finally {\n setIsUploading(false);\n }\n };\n\n const handleDrop = (e: React.DragEvent) => {\n e.preventDefault();\n const droppedFile = e.dataTransfer.files[0];\n if (droppedFile) {\n handleFileSelect(droppedFile);\n }\n };\n\n const handleDragOver = (e: React.DragEvent) => {\n e.preventDefault();\n };\n\n const clearFile = () => {\n setFile(null);\n setPreviewUrl(null);\n setUploadedUrl(null);\n if (fileInputRef.current) {\n fileInputRef.current.value = "";\n }\n };\n \n return {\n\t handleDrop,\n\t handleDragOver,\n\t clearFile,\n\t handleFileSelect,\n\t uploadToImageKit\n }\n}\n'})}),"\n",(0,i.jsx)(n.h4,{id:"ai-transformations",children:"AI transformations"}),"\n",(0,i.jsx)(n.p,{children:"ImageKit supports advanced AI-powered transformations:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tsx",children:'<Image\n src="/product.jpg"\n alt="Product"\n width={500}\n height={500}
1\n transformation={[{ aiRemoveBackground: true }]}\n/>;\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tsx",children:'<Image\n src="/low-res.jpg"\n alt="Upscaled"\n width={1000}\n height={1000}\n transformation={[{ aiUpscale: true }]}\n/>;\n'})})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>s});var i=t(6540);const r={},a=i.createContext(r);function o(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.