{"id":15857443,"url":"https://github.com/timmikeladze/next-protect","last_synced_at":"2026-01-24T10:34:59.965Z","repository":{"id":251332450,"uuid":"818812286","full_name":"TimMikeladze/next-protect","owner":"TimMikeladze","description":"🔒 Password protect a Next.js site. Supports App Router, Middleware and Edge Runtime.","archived":false,"fork":false,"pushed_at":"2024-11-01T06:56:47.000Z","size":974,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-11T12:04:30.355Z","etag":null,"topics":["next-authentication","next-password","next-password-protect","next-protect","nextjs","reactjs","typescript"],"latest_commit_sha":null,"homepage":"https://next-protect.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TimMikeladze.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-23T00:09:10.000Z","updated_at":"2024-08-02T21:53:46.000Z","dependencies_parsed_at":"2024-08-02T09:35:51.093Z","dependency_job_id":"3fbbabbb-fa44-4eac-9787-5a073b6c0695","html_url":"https://github.com/TimMikeladze/next-protect","commit_stats":null,"previous_names":["timmikeladze/next-protect"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimMikeladze%2Fnext-protect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimMikeladze%2Fnext-protect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimMikeladze%2Fnext-protect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimMikeladze%2Fnext-protect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TimMikeladze","download_url":"https://codeload.github.com/TimMikeladze/next-protect/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":233655318,"owners_count":18709257,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["next-authentication","next-password","next-password-protect","next-protect","nextjs","reactjs","typescript"],"created_at":"2024-10-05T20:23:11.382Z","updated_at":"2025-09-20T10:32:30.352Z","avatar_url":"https://github.com/TimMikeladze.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🔒 next-protect\n\nProtect your Next.js app with a password. A drop-in solution to keep your deployments protected with a basic password system.\n\n\u003e Check-out a [NextJS example](./examples/nextjs-example/) or view the [Demo](https://next-protect.vercel.app/).\n\n## ✨ Features\n\n- [x] App Router support out of the box.\n- [x] Supports Next.js Middleware, Edge runtime, RSC and SSR.\n- [x] Protect just a specific page or the entire app.\n- [x] Use one or more passwords.\n- [x] Customizable form and styles.\n\n## 📡 Install\n\n```console\nnpm install next-protect\n\nyarn add next-protect\n\npnpm add next-protect\n```\n\n\u003e 👋 Hello there! Follow me [@linesofcode](https://twitter.com/linesofcode) or visit [linesofcode.dev](https://linesofcode.dev) for more cool projects like this one.\n\n## 🚀 Getting started\n\nFirst, modify your `.env` file to include a new environment variable: `NEXT_PROTECT_PASSWORD=\"password-goes-here\"`.\n\nNext we need to instantiate the `NextProtect` class. This instance provides the core functionality of the package. Create a new file `src/app/api/next-protect/index.ts` and export the `NextProtect` class.\n\n```ts\n/* src/app/api/next-protect/index.ts */\nimport { NextProtect } from 'next-protect/server';\n\nexport const np = new NextProtect();\n```\n\nNow we need to expose a `POST` route to our Next.js app. Create a new file `src/app/api/next-protect/route.ts` and export the `POST` method.\n\n```ts\n/* src/app/api/next-protect/route.ts */\nimport { NextRequest } from 'next/server';\nimport { np } from '.';\n\nexport const POST = (req: NextRequest) =\u003e np.POST(req);\n```\n\nThe server-side code is now ready to go, but we still need to render a password form to the user and protect the page.\n\nCreate a `src/middleware.ts` file and export the `middleware` function. This middleware will be called before every request to your app, checks if the user is authenticated, and redirects them into the app or to a login page.\n\n```ts\n/* src/middleware.ts */\nimport { NextRequest } from 'next/server';\nimport { np } from './app/api/next-protect';\n\nexport const middleware = async (req: NextRequest) =\u003e np.middleware(req);\n```\n\nThe final step is to create a Next.js page that will render a password form to the user.\n\nCreate a `src/app/next-protect/page.tsx` file and simply re-export the `NextProtect` component.\n\n```tsx\n/* src/app/next-protect/page.tsx */\nimport 'next-protect/styles.css';\nimport { NextProtect } from 'next-protect/react';\n\nconst Page = () =\u003e \u003cNextProtect /\u003e;\n\nexport default Page;\n```\n\nDone! Now open your browser and navigate to `http://localhost:3000`. You will be redirected to a password form. After entering the correct password, you will be granted access to the entire app. Simple as that! Now you can clear your cookies and refresh the page to see the password form again.\n\n\u003e 🙌 Want to see a fully working codebase? Check out the [NextJS example](./examples/nextjs-example/) or view the [Demo](https://next-protect.vercel.app/).\n\n## 💪 Advanced usage\n\n### Server side rendering (without middleware)\n\nIf you are using React Server Components (RSC), you can call `await np.isProtected()` in your `async` React component to check if the user is authenticated.\n\n\u003e ❗ Important note: just because a layout component is protected does not mean that its child pages are protected.\n\n```tsx\n/* src/app/page.tsx */\nimport 'next-protect/styles.css';\nimport { NextProtect } from 'next-protect/react';\n\nconst Page = async () =\u003e {\n  const isProtected = await np.isProtected();\n\n  return (\n    \u003cNextProtect isProtected={isProtected}\u003e\n      \u003cp\u003eThis content is only visible to authenticated users.\u003c/p\u003e\n    \u003c/NextProtect\u003e\n  );\n};\n```\n\n### Client side rendering (without middleware)\n\nIf you are using React Client Components, simply render a `NextProtect` component without any props. Internally the logic will fall-back to sending a request to `/api/next-protect` to check if the user is authenticated.\n\n```tsx\n/* src/app/page.tsx */\nimport 'next-protect/styles.css';\nimport { NextProtect } from 'next-protect/react';\n\nconst Page = () =\u003e {\n  return (\n    \u003cNextProtect\u003e\n      \u003cp\u003eThis content is only visible to authenticated users.\u003c/p\u003e\n    \u003c/NextProtect\u003e\n  );\n};\n\nexport default Page;\n```\n\n### Multiple Passwords\n\nYou can configure multiple passwords to be used for authentication by passing an array of passwords to the `NextProtect` component.\n\n```ts\n/* src/app/api/next-protect/index.ts */\nimport { NextProtect } from 'next-protect/server';\n\nexport const np = new NextProtect({\n  password: ['password', 'another-password'],\n});\n```\n\n### Customizing and Styling the Form\n\nThe `NextProtect` component accepts a number of props that allow you to customize the form. Here are some examples:\n\n```tsx\n/* src/app/next-protect/page.tsx */\nimport 'next-protect/styles.css';\nimport { NextProtect } from 'next-protect/react';\n\nconst Page = () =\u003e (\n  \u003cNextProtect\n    slotProps={{\n      passwordInput: {\n        placeholder: 'The password is password',\n      },\n    }}\n    header={\u003ch1\u003eCustom Header\u003c/h1\u003e}\n    footer={\u003cp\u003eCustom Footer\u003c/p\u003e}\n  /\u003e\n);\n\nexport default Page;\n```\n\n### Custom redirects and rewrites\n\nYou can customize the redirect and rewrite behavior of the `NextProtect` component by passing the following options to the `NextProtect` constructor.\n\n- `redirectTo`: Redirect the user to a specific URL.\n- `rewriteTo`: Rewrite the URL to a specific URL.\n\n```ts\n/* src/app/api/next-protect/index.ts */\nimport { NextProtect } from 'next-protect/server';\n\nexport const np = new NextProtect({\n  redirectTo: '/dashboard',\n});\n```\n\n### Custom API endpoint\n\nBy default, the `NextProtect` component will use the `/api/next-protect` endpoint to check if the user is authenticated. You can customize this endpoint by passing the `api` prop to the `NextProtect` component.\n\n```ts\n/* src/app/api/next-protect/index.ts */\nimport { NextProtect } from 'next-protect/server';\n\nexport const np = new NextProtect({\n  api: '/api/my-custom-endpoint',\n});\n```\n\n```tsx\n/* src/app/next-protect/page.tsx */\nimport 'next-protect/styles.css';\nimport { NextProtect } from 'next-protect/react';\n\nconst Page = () =\u003e \u003cNextProtect api=\"/api/my-custom-endpoint\" /\u003e;\n\nexport default Page;\n```\n\n## 📚 TSDoc\n\n\u003c!-- TSDOC_START --\u003e\n\n## :toolbox: Functions\n\n- [NextProtect](#gear-nextprotect)\n- [NextProtectForm](#gear-nextprotectform)\n- [useNextProtect](#gear-usenextprotect)\n\n### :gear: NextProtect\n\n| Function      | Type                                                                                                                                                     |\n| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `NextProtect` | `(props: NextProtectProps) =\u003e string or number or bigint or boolean or Iterable\u003cReactNode\u003e or Promise\u003cAwaitedReactNode\u003e or Element or null or undefined` |\n\n### :gear: NextProtectForm\n\n| Function          | Type                                       |\n| ----------------- | ------------------------------------------ |\n| `NextProtectForm` | `(props: NextProtectFormProps) =\u003e Element` |\n\n### :gear: useNextProtect\n\n| Function         | Type                                                                      |\n| ---------------- | ------------------------------------------------------------------------- |\n| `useNextProtect` | `(props: NextProtectHookProps) =\u003e { isProtected: boolean or undefined; }` |\n\n## :wrench: Constants\n\n- [defaultOptions](#gear-defaultoptions)\n- [defaultNextProtectEndpoint](#gear-defaultnextprotectendpoint)\n\n### :gear: defaultOptions\n\n| Constant         | Type                 |\n| ---------------- | -------------------- |\n| `defaultOptions` | `NextProtectOptions` |\n\n### :gear: defaultNextProtectEndpoint\n\n| Constant                     | Type                  |\n| ---------------------------- | --------------------- |\n| `defaultNextProtectEndpoint` | `\"/api/next-protect\"` |\n\n## :factory: NextProtect\n\n### Methods\n\n- [isProtected](#gear-isprotected)\n- [middleware](#gear-middleware)\n- [GET](#gear-get)\n- [POST](#gear-post)\n\n#### :gear: isProtected\n\n| Method        | Type                     |\n| ------------- | ------------------------ |\n| `isProtected` | `() =\u003e Promise\u003cboolean\u003e` |\n\n#### :gear: middleware\n\n| Method       | Type                                               |\n| ------------ | -------------------------------------------------- |\n| `middleware` | `(req: Request) =\u003e Promise\u003cNextResponse\u003cunknown\u003e\u003e` |\n\n#### :gear: GET\n\n| Method | Type                                                                               |\n| ------ | ---------------------------------------------------------------------------------- |\n| `GET`  | `(req?: Request or undefined) =\u003e Promise\u003cNextResponse\u003c{ isProtected: boolean; }\u003e\u003e` |\n\n#### :gear: POST\n\n| Method | Type                                               |\n| ------ | -------------------------------------------------- |\n| `POST` | `(req: Request) =\u003e Promise\u003cNextResponse\u003cunknown\u003e\u003e` |\n\n\u003c!-- TSDOC_END --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimmikeladze%2Fnext-protect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftimmikeladze%2Fnext-protect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimmikeladze%2Fnext-protect/lists"}