PageSourceSearch

https://threejsnotes.netlify.app/assets/js/d1abc9c3.ed02cf10.js

js threejsnotes.netlify.app collected 2026-10-03 11:30:46 UTC 14,984 bytes, 1 lines download raw bytes

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.