diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml new file mode 100644 index 0000000..bf5d9dd --- /dev/null +++ b/.github/workflows/nodejs.yml @@ -0,0 +1,83 @@ +name: Node CI + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [18.x, 20.x] + + steps: + - uses: actions/checkout@v1 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + + - name: Setup module + run: | + npm install + env: + CI: true + + e2e: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [18.x] + + steps: + - uses: actions/checkout@v1 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + + - name: Setup module + run: | + npm install + npm run build + npm pack + - name: build example/app-router + run: | + cd example/app-router + echo NEXT_PUBLIC_URL_ENDPOINT = ${{ secrets.IK_URL_ENDPOINT }} > .env; + echo NEXT_PUBLIC_PUBLIC_KEY = ${{ secrets.IK_PUBLIC_KEY }} >> .env; + echo NEXT_PUBLIC_AUTHENTICATION_ENDPOINT = 'http://localhost:3000/api/auth' >> .env; + echo PRIVATE_KEY = ${{ secrets.IK_PRIVATE_KEY }} >> .env; + npm install && npm run build + env: + CI: true + NEXT_PUBLIC_PUBLIC_KEY: ${{ secrets.IK_PUBLIC_KEY }} + PRIVATE_KEY: ${{ secrets.IK_PRIVATE_KEY }} + NEXT_PUBLIC_URL_ENDPOINT: ${{ secrets.IK_URL_ENDPOINT }} + + - name: Run E2E tests + uses: cypress-io/github-action@v4 + with: + start: npm run serve:app-router + wait-on: 'http://localhost:3000' + env: + DEBUG: 'cypress:server:browsers:electron' + CI: true + NEXT_PUBLIC_PUBLIC_KEY: ${{ secrets.IK_PUBLIC_KEY }} + PRIVATE_KEY: ${{ secrets.IK_PRIVATE_KEY }} + NEXT_PUBLIC_URL_ENDPOINT: ${{ secrets.IK_URL_ENDPOINT }} + + - name: tar workspace + if: always() + run: | + tar -cf build.tar --exclude=./build.tar . + - name: Archive build details + if: always() + uses: actions/upload-artifact@v3 + with: + name: e2e-archive + path: build.tar + retention-days: 1 diff --git a/.github/workflows/npmpublish.yml b/.github/workflows/npmpublish.yml new file mode 100644 index 0000000..89c68e1 --- /dev/null +++ b/.github/workflows/npmpublish.yml @@ -0,0 +1,49 @@ +name: Publish + +on: + release: + types: [published] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [18.x, 20.x] + + steps: + - uses: actions/checkout@v1 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - name: npm install, build, and test + run: | + npm i + npm run build + env: + CI: true + NEXT_PUBLIC_PUBLIC_KEY: ${{ secrets.IK_PUBLIC_KEY }} + PRIVATE_KEY: ${{ secrets.IK_PRIVATE_KEY }} + NEXT_PUBLIC_URL_ENDPOINT: ${{ secrets.IK_URL_ENDPOINT }} + + + publish: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: 18 + registry-url: https://registry.npmjs.org/ + - name: npm publish + run: | + npm i + npm run build + npm config set //registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN + npm publish + env: + NODE_AUTH_TOKEN: ${{secrets.npm_token}} + CI: true diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..5ebca89 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +.env +.vscode +lib +dist +coverage +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..8bcf8f6 --- /dev/null +++ b/README.md @@ -0,0 +1,785 @@ +[ImageKit.io](https://imagekit.io) + +# ImageKit.io Next.js SDK + +[![Node CI](https://github.com/imagekit-developer/imagekit-next/workflows/Node%20CI/badge.svg)](https://github.com/imagekit-developer/imagekit-next/) +[![npm version](https://img.shields.io/npm/v/imagekitio-next)](https://www.npmjs.com/package/imagekitio-next) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![Twitter Follow](https://img.shields.io/twitter/follow/imagekitio?label=Follow&style=social)](https://twitter.com/ImagekitIo) + +ImageKit Next.js SDK allows you to resize, optimize, deliver, and upload images and videos in your Next.js application. + +[ImageKit](https://imagekit.io) is a complete media storage, optimization, and transformation solution that comes with an image and video CDN. It can be integrated with your existing infrastructure - storage like AWS S3, web servers, your CDN, and custom domain names, allowing you to deliver optimized images in minutes with minimal code changes. + +## Installation + +Add `imagekitio-next` to your project by executing one of the following commands: + +```shell +npm install --save imagekitio-next +``` + +or + +```shell +yarn add imagekitio-next +``` + +## Usage + +### Initialization + +Import components in your code: + +```js +import { IKImage, IKVideo, ImageKitProvider, IKUpload, ImageKitContext } from 'imagekitio-next' +``` + +### Pages Router (/src) + +By default, `imagekitio-next` fully supports the included components in the `src` directory without any additional setup. + +### App Router (/app) + +The components in the app directory are, by default, React Server-Side Components (RSCs), but not everything can be done server-side. That's where Client components come in. + +`imagekitio-next` provides components that operate exclusively on the client side. + +When using the SDK for the first time, you might enter either of the following errors. + +`Error: (0 , react__WEBPACK_IMPORTED_MODULE_0__.createContext) is not a function` + +or + +`You're importing a component that needs createContext. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.` + +To simply fix this, you can force the component or the page to operate solely on Client Side by adding "use client"; directive at the start of the file, you can read more about it here [Using Client Components in Next.js](https://nextjs.org/docs/app/building-your-application/rendering/client-components#using-client-components-in-nextjs). + +### Allowing images to be loaded from trusted external URLs + +To protect your application from malicious users, configuration is required to use external images. The `remotePatterns` configuration in Next.js specifies the sources allowed to load images via external URLs. This enhances security by preventing unauthorized image sources, which could potentially expose the application to vulnerabilities like cross-site scripting (XSS) or data theft. By defining a whitelist of trusted image sources, developers can ensure that only images from these sources are loaded, thereby safeguarding the application. For more details, refer to the [Next.js documentation](https://nextjs.org/docs/app/api-reference/components/image#remotepatterns). + +`next.config.js` +```js +module.exports = { + images: { + remotePatterns: [ + { + protocol: "https", + hostname: "ik.imagekit.io", + port: '', + }, + ], + }, +} +``` + + +### Examples + +#### Image & video rendering and transformations +```js + + // Render an image using a relative path - https://ik.imagekit.io/your_imagekit_id/default-image.jpg + + + // Overriding urlEndpoint defined in parent ImageKitProvider - https://www.custom-domain.com/default-image.jpg + + + // Render an image using an absolute URL - https://www1.custom-domain.com/default-image.jpg?tr=w-100 + + + // Height and width manipulation - https://ik.imagekit.io/your_imagekit_id/tr:h-200,w-200/default-image.jpg + + + // Chained transformation - https://ik.imagekit.io/your_imagekit_id/tr:h-200,w-200:rt-90/default-image.jpg + + + // Video element with basic transformation, reduced quality by 50% using q:50 + + +``` + +#### Image lazy loading and low-quality placeholder +```js + + // Lazy loading image + + + /* + Low-quality image placeholder + Will first load https://ik.imagekit.io/your_imagekit_id/tr:h-200,w-200:q-20,bl-6/default-image.jpg, while the original image, i.e., https://ik.imagekit.io/your_imagekit_id/tr:h-200,w-200/default-image.jpg is being loaded in the background. + */ + + + // Low-quality image placeholder with custom quality and blur values + + + // Low-quality image placeholder and lazy loading of original image in the background + + +``` + +#### File upload example +```js +// Ensure you pass publicKey, urlEndpoint, and authenticator function to the parent ImageKitProvider component or to the IKUpload component directly. +Promise} + // This promise resolves with an object containing the necessary security parameters i.e `signature`, `token`, and `expire`. + > + + + // Passing different upload API options + + +``` + +## Demo application +* The official step-by-step Next.js quick start guide - https://imagekit.io/docs/integration/next + +## Components + +The library includes 6 Components: + +* [`ImageKitProvider`](#ImageKitProvider) is used to define options such as `urlEndpoint`, `publicKey`, or `authenticator` for all child components. It does not render any UI elements. +* `IKImage` for [image resizing](#image-resizing), this utilizes next/image and renders an `` tag. +* `IKVideo` for [video resizing](#video-resizing), this renders a `