{"id":23243694,"url":"https://github.com/fortedigital/nextjs-cache-handler","last_synced_at":"2026-01-17T06:43:21.731Z","repository":{"id":257807102,"uuid":"866421342","full_name":"fortedigital/nextjs-cache-handler","owner":"fortedigital","description":"Next.js caching extensions focusing on Redis based architecture","archived":false,"fork":false,"pushed_at":"2026-01-14T12:29:02.000Z","size":1079,"stargazers_count":134,"open_issues_count":16,"forks_count":22,"subscribers_count":10,"default_branch":"master","last_synced_at":"2026-01-14T16:27:16.570Z","etag":null,"topics":["cache-handler","nextjs","redis","redis-cache"],"latest_commit_sha":null,"homepage":"","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/fortedigital.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-10-02T08:23:00.000Z","updated_at":"2026-01-14T12:21:39.000Z","dependencies_parsed_at":"2024-10-02T10:20:18.499Z","dependency_job_id":"a0bb3ee9-a01a-47c4-8804-3904fb860e24","html_url":"https://github.com/fortedigital/nextjs-cache-handler","commit_stats":null,"previous_names":["fortedigital/nextjs-cache-handler"],"tags_count":66,"template":false,"template_full_name":null,"purl":"pkg:github/fortedigital/nextjs-cache-handler","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fortedigital%2Fnextjs-cache-handler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fortedigital%2Fnextjs-cache-handler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fortedigital%2Fnextjs-cache-handler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fortedigital%2Fnextjs-cache-handler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fortedigital","download_url":"https://codeload.github.com/fortedigital/nextjs-cache-handler/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fortedigital%2Fnextjs-cache-handler/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28502819,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T04:31:57.058Z","status":"ssl_error","status_checked_at":"2026-01-17T04:31:45.816Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["cache-handler","nextjs","redis","redis-cache"],"created_at":"2024-12-19T06:17:41.912Z","updated_at":"2026-01-17T06:43:21.725Z","avatar_url":"https://github.com/fortedigital.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![NPM Version](https://img.shields.io/npm/v/%40fortedigital%2Fnextjs-cache-handler)\n\n# @fortedigital/nextjs-cache-handler\n\nA caching utility built originally on top of [`@neshca/cache-handler`](https://www.npmjs.com/package/@neshca/cache-handler), providing additional cache handlers for specialized use cases with a focus on Redis-based caching.\nStarting from version `2.0.0`, this package no longer depends on `@neshca/cache-handler` and is fully maintained and compatible with Next.js 15 and onwards.\n\n## Documentation\n\nThe documentation at [@neshca/cache-handler - caching-tools.github.io/next-shared-cache](https://caching-tools.github.io/next-shared-cache) is mostly still relevant, though some details may be outdated. New features or relevant changes are described below.\n\n## Migration\n\n- [1.x.x → ^2.x.x](https://github.com/fortedigital/nextjs-cache-handler/blob/master/docs/migration/1_x_x__2_x_x.md)\n- [1.2.x -\u003e ^1.3.x](https://github.com/fortedigital/nextjs-cache-handler/blob/master/docs/migration/1_2_x__1_3_x.md)\n\n## Installation\n\n`npm i @fortedigital/nextjs-cache-handler`\n\nIf upgrading from Next 14 or earlier, **flush your Redis cache** before running new version of the application locally and on your hosted environments. **Cache formats between Next 14 and 15 are incompatible**.\n\n## Next 15 Support\n\nThe original `@neshca/cache-handler` package does not support Next.js 15.\n\nPrior to 2.0.0, this package provided wrappers and enhancements to allow using `@neshca/cache-handler` with Next.js 15.  \nFrom version 2.0.0 onward, `@fortedigital/nextjs-cache-handler` is a standalone solution with no dependency on `@neshca/cache-handler` and is fully compatible with Next.js 15 and [redis 5](https://www.npmjs.com/package/redis).\n\nWe aim to keep up with new Next.js releases and will introduce major changes with appropriate version bumps.\n\n### Swapping from `@neshca/cache-handler`\n\nIf you already use `@neshca/cache-handler` the setup is very streamlined and you just need to replace package references. If you're starting fresh please check [the example project](./examples/redis-minimal).\n\n#### Cache handler\n\n**Before:**\n\n```js\n// cache-handler.mjs\n\nimport { CacheHandler } from \"@neshca/cache-handler\";\n\nCacheHandler.onCreation(() =\u003e {\n  // setup\n});\n\nexport default CacheHandler;\n```\n\n**After:**\n\n```js\n// cache-handler.mjs\n\nimport { CacheHandler } from \"@fortedigital/nextjs-cache-handler\";\n\nCacheHandler.onCreation(() =\u003e {\n  // setup\n});\n\nexport default CacheHandler;\n```\n\n---\n\n#### Instrumentation\n\n**Before:**\n\n```js\n// instrumentation.ts\n\nexport async function register() {\n  if (process.env.NEXT_RUNTIME === \"nodejs\") {\n    const { registerInitialCache } = await import(\n      \"@neshca/cache-handler/instrumentation\"\n    );\n    const CacheHandler = (await import(\"../cache-handler.mjs\")).default;\n    await registerInitialCache(CacheHandler);\n  }\n}\n```\n\n**After:**\n\n```js\n// instrumentation.ts\n\nexport async function register() {\n  if (process.env.NEXT_RUNTIME === \"nodejs\") {\n    const { registerInitialCache } = await import(\n      \"@fortedigital/nextjs-cache-handler/instrumentation\"\n    );\n    const CacheHandler = (await import(\"../cache-handler.mjs\")).default;\n    await registerInitialCache(CacheHandler);\n  }\n}\n```\n\n## Instrumentation\n\n### Initial cache registration\n\nBy default, `registerInitialCache` populates the cache by overwriting any existing\nentries with values generated from build-time artifacts (fetch calls, pages, routes).\n\n#### Initial cache write strategy\n\nIf you want to preserve values that may already exist in the cache (for example,\nentries written at runtime by another instance), you can enable the\n`setOnlyIfNotExists` option:\n\n```ts\nawait registerInitialCache(CacheHandler, {\n  setOnlyIfNotExists: true,\n});\n```\n\nWhen enabled, cache writes performed during the initial cache registration will only\noccur if the corresponding cache key does not already exist. This allows you to\nexplicitly choose the cache population strategy instead of enforcing a single default.\n\n## Handlers\n\n### `redis-strings`\n\nA Redis-based handler for key- and tag-based caching. Compared to the original implementation, it prevents memory leaks caused by growing shared tag maps by implementing TTL-bound hashmaps.\n\n**Features:**\n\n- Key expiration using `EXAT` or `EXPIREAT`\n- Tag-based revalidation\n- Automatic TTL management\n- Default `revalidateTagQuerySize`: `10_000` (safe for large caches)\n\n```js\nimport createRedisHandler from \"@fortedigital/nextjs-cache-handler/redis-strings\";\n\nconst redisHandler = await createRedisHandler({\n  client: createClient({\n    url: process.env.REDIS_URL,\n  }),\n  keyPrefix: \"myApp:\",\n  sharedTagsKey: \"myTags\",\n  sharedTagsTtlKey: \"myTagTtls\",\n});\n```\n\n#### Redis Cluster (Experimental)\n\n```js\nimport { createCluster } from \"@redis/client\";\nimport createRedisHandler from \"@fortedigital/nextjs-cache-handler/redis-strings\";\nimport { withAdapter } from \"@fortedigital/nextjs-cache-handler/cluster/adapter\";\n\nconst { hostname: redisHostName } = new URL(process.env.REDIS_URL);\nredis = withAdapter(\n  createCluster({\n    rootNodes: [{ url: process.env.REDIS_URL }],\n\n    // optional if you use TLS and need to resolve shards' ip to proper hostname\n    nodeAddressMap(address) {\n      const [_, port] = address.split(\":\");\n\n      return {\n        host: redisHostName,\n        port: Number(port),\n      };\n    },\n  })\n);\n\n// after using withAdapter you can use redis cluster instance as parameter for createRedisHandler\nconst redisCacheHandler = createRedisHandler({\n  client: redis,\n  keyPrefix: CACHE_PREFIX,\n});\n```\n\n**Note:** Redis Cluster support is currently experimental and may have limitations or unexpected bugs. Use it with caution.\n\n---\n\n### `local-lru`\n\nThe local-lru Handler uses a lru-cache ↗ instance as the cache store. It stores the cache in memory and evicts the least recently used entries when the cache reaches its limits. You can use this Handler as a fallback cache when the shared cache is unavailable.\n\n\u003e ⚠️ The local-lru Handler is not suitable for production environments. It is intended for development and testing purposes only.\n\n**Features:**\n\n- Key expiration using `EXAT` or `EXPIREAT`\n- Tag-based revalidation\n- Automatic TTL management\n- Default `revalidateTagQuerySize`: `10_000` (safe for large caches)\n\n```js\nimport createLruHandler from \"@fortedigital/nextjs-cache-handler/local-lru\";\n\nconst localHandler = createLruHandler({\n  maxItemsNumber: 10000,\n  maxItemSizeBytes: 1024 * 1024 * 500,\n});\n```\n\n---\n\n### `composite`\n\nRoutes cache operations across multiple underlying handlers.\n\n**Features:**\n\n- Multiple backend support\n- Custom routing strategies\n- First-available read strategy\n\n```js\nimport createCompositeHandler from \"@fortedigital/nextjs-cache-handler/composite\";\n\nconst compositeHandler = createCompositeHandler({\n  handlers: [handler1, handler2],\n  setStrategy: (data) =\u003e (data?.tags.includes(\"handler1\") ? 0 : 1),\n});\n```\n\n### ⚠️ `buffer-string-decorator` | **REMOVED IN 2.0.0!** - integrated into the core package\n\n#### Features:\n\nThis cache handler converts buffers from cached route values to strings on save and back to buffers on read.\n\nNext 15 decided to change types of some properties from String to Buffer which conflicts with how data is serialized to redis. It is recommended to use this handler with `redis-strings` in Next 15 as this handler make the following adjustment.\n\n- **Converts `body` `Buffer` to `string`**  \n  See: https://github.com/vercel/next.js/blob/f5444a16ec2ef7b82d30048890b613aa3865c1f1/packages/next/src/server/response-cache/types.ts#L97\n- **Converts `rscData` `string` to `Buffer`**  \n  See: https://github.com/vercel/next.js/blob/f5444a16ec2ef7b82d30048890b613aa3865c1f1/packages/next/src/server/response-cache/types.ts#L76\n- **Converts `segmentData` `Record\u003cstring, string\u003e` to `Map\u003cstring, Buffer\u003e`**  \n  See: https://github.com/vercel/next.js/blob/f5444a16ec2ef7b82d30048890b613aa3865c1f1/packages/next/src/server/response-cache/types.ts#L80\n\n```js\nimport createBufferStringDecoratorHandler from \"@fortedigital/nextjs-cache-handler/buffer-string-decorator\";\n\nconst bufferStringDecorator =\n  createBufferStringDecoratorHandler(redisCacheHandler);\n```\n\n## Examples\n\n### 2.x.x\n\n#### Full example\n\n[Example project](./examples/redis-minimal)\n\n#### Example `cache-handler.js`.\n\n```js\nimport { createClient } from \"redis\";\nimport { PHASE_PRODUCTION_BUILD } from \"next/constants.js\";\nimport { CacheHandler } from \"@fortedigital/nextjs-cache-handler\";\nimport createLruHandler from \"@fortedigital/nextjs-cache-handler/local-lru\";\nimport createRedisHandler from \"@fortedigital/nextjs-cache-handler/redis-strings\";\nimport createCompositeHandler from \"@fortedigital/nextjs-cache-handler/composite\";\n\nCacheHandler.onCreation(() =\u003e {\n  // Important - It's recommended to use global scope to ensure only one Redis connection is made\n  // This ensures only one instance get created\n  if (global.cacheHandlerConfig) {\n    return global.cacheHandlerConfig;\n  }\n\n  // Important - It's recommended to use global scope to ensure only one Redis connection is made\n  // This ensures new instances are not created in a race condition\n  if (global.cacheHandlerConfigPromise) {\n    return global.cacheHandlerConfigPromise;\n  }\n\n  // You may need to ignore Redis locally, remove this block otherwise\n  if (process.env.NODE_ENV === \"development\") {\n    const lruCache = createLruHandler();\n    return { handlers: [lruCache] };\n  }\n\n  // Main promise initializing the handler\n  global.cacheHandlerConfigPromise = (async () =\u003e {\n    let redisClient = null;\n\n    if (PHASE_PRODUCTION_BUILD !== process.env.NEXT_PHASE) {\n      const settings = {\n        url: process.env.REDIS_URL,\n        pingInterval: 10000,\n      };\n\n      // This is optional and needed only if you use access keys\n      if (process.env.REDIS_ACCESS_KEY) {\n        settings.password = process.env.REDIS_ACCESS_KEY;\n      }\n\n      try {\n        redisClient = createClient(settings);\n        redisClient.on(\"error\", (e) =\u003e {\n          if (typeof process.env.NEXT_PRIVATE_DEBUG_CACHE !== \"undefined\") {\n            console.warn(\"Redis error\", e);\n          }\n          global.cacheHandlerConfig = null;\n          global.cacheHandlerConfigPromise = null;\n        });\n      } catch (error) {\n        console.warn(\"Failed to create Redis client:\", error);\n      }\n    }\n\n    if (redisClient) {\n      try {\n        console.info(\"Connecting Redis client...\");\n        await redisClient.connect();\n        console.info(\"Redis client connected.\");\n      } catch (error) {\n        console.warn(\"Failed to connect Redis client:\", error);\n        await redisClient\n          .disconnect()\n          .catch(() =\u003e\n            console.warn(\n              \"Failed to quit the Redis client after failing to connect.\"\n            )\n          );\n      }\n    }\n\n    const lruCache = createLruHandler();\n\n    if (!redisClient?.isReady) {\n      console.error(\"Failed to initialize caching layer.\");\n      global.cacheHandlerConfigPromise = null;\n      global.cacheHandlerConfig = { handlers: [lruCache] };\n      return global.cacheHandlerConfig;\n    }\n\n    const redisCacheHandler = createRedisHandler({\n      client: redisClient,\n      keyPrefix: \"nextjs:\",\n    });\n\n    global.cacheHandlerConfigPromise = null;\n\n    // This example uses composite handler to switch from Redis to LRU cache if tags contains `memory-cache` tag.\n    // You can skip composite and use Redis or LRU only.\n    global.cacheHandlerConfig = {\n      handlers: [\n        createCompositeHandler({\n          handlers: [lruCache, redisCacheHandler],\n          setStrategy: (ctx) =\u003e (ctx?.tags.includes(\"memory-cache\") ? 0 : 1), // You can adjust strategy for deciding which cache should the composite use\n        }),\n      ],\n    };\n\n    return global.cacheHandlerConfig;\n  })();\n\n  return global.cacheHandlerConfigPromise;\n});\n\nexport default CacheHandler;\n```\n\n### 1.x.x\n\n```js\n// @neshca/cache-handler dependencies\nimport { CacheHandler } from \"@neshca/cache-handler\";\nimport createLruHandler from \"@neshca/cache-handler/local-lru\";\n\n// Next/Redis dependencies\nimport { createClient } from \"redis\";\nimport { PHASE_PRODUCTION_BUILD } from \"next/constants\";\n\n// @fortedigital/nextjs-cache-handler dependencies\nimport createCompositeHandler from \"@fortedigital/nextjs-cache-handler/composite\";\nimport createRedisHandler from \"@fortedigital/nextjs-cache-handler/redis-strings\";\nimport createBufferStringHandler from \"@fortedigital/nextjs-cache-handler/buffer-string-decorator\";\nimport { Next15CacheHandler } from \"@fortedigital/nextjs-cache-handler\";\n\n// Usual onCreation from @neshca/cache-handler\nCacheHandler.onCreation(() =\u003e {\n  // Important - It's recommended to use global scope to ensure only one Redis connection is made\n  // This ensures only one instance get created\n  if (global.cacheHandlerConfig) {\n    return global.cacheHandlerConfig;\n  }\n\n  // Important - It's recommended to use global scope to ensure only one Redis connection is made\n  // This ensures new instances are not created in a race condition\n  if (global.cacheHandlerConfigPromise) {\n    return global.cacheHandlerConfigPromise;\n  }\n\n  // You may need to ignore Redis locally, remove this block otherwise\n  if (process.env.NODE_ENV === \"development\") {\n    const lruCache = createLruHandler();\n    return { handlers: [lruCache] };\n  }\n\n  // Main promise initializing the handler\n  global.cacheHandlerConfigPromise = (async () =\u003e {\n    /** @type {import(\"redis\").RedisClientType | null} */\n    let redisClient = null;\n    if (PHASE_PRODUCTION_BUILD !== process.env.NEXT_PHASE) {\n      const settings = {\n        url: process.env.REDIS_URL, // Make sure you configure this variable\n        pingInterval: 10000,\n      };\n\n      // This is optional and needed only if you use access keys\n      if (process.env.REDIS_ACCESS_KEY) {\n        settings.password = process.env.REDIS_ACCESS_KEY;\n      }\n\n      try {\n        redisClient = createClient(settings);\n        redisClient.on(\"error\", (e) =\u003e {\n          if (typeof process.env.NEXT_PRIVATE_DEBUG_CACHE !== \"undefined\") {\n            console.warn(\"Redis error\", e);\n          }\n          global.cacheHandlerConfig = null;\n          global.cacheHandlerConfigPromise = null;\n        });\n      } catch (error) {\n        console.warn(\"Failed to create Redis client:\", error);\n      }\n    }\n\n    if (redisClient) {\n      try {\n        console.info(\"Connecting Redis client...\");\n        await redisClient.connect();\n        console.info(\"Redis client connected.\");\n      } catch (error) {\n        console.warn(\"Failed to connect Redis client:\", error);\n        await redisClient\n          .disconnect()\n          .catch(() =\u003e\n            console.warn(\n              \"Failed to quit the Redis client after failing to connect.\"\n            )\n          );\n      }\n    }\n    const lruCache = createLruHandler();\n\n    if (!redisClient?.isReady) {\n      console.error(\"Failed to initialize caching layer.\");\n      global.cacheHandlerConfigPromise = null;\n      global.cacheHandlerConfig = { handlers: [lruCache] };\n      return global.cacheHandlerConfig;\n    }\n\n    const redisCacheHandler = createRedisHandler({\n      client: redisClient,\n      keyPrefix: \"nextjs:\",\n    });\n\n    global.cacheHandlerConfigPromise = null;\n\n    // This example uses composite handler to switch from Redis to LRU cache if tags contains `memory-cache` tag.\n    // You can skip composite and use Redis or LRU only.\n    global.cacheHandlerConfig = {\n      handlers: [\n        createCompositeHandler({\n          handlers: [\n            lruCache,\n            createBufferStringHandler(redisCacheHandler), // Use `createBufferStringHandler` in Next15 and ignore it in Next14 or below\n          ],\n          setStrategy: (ctx) =\u003e (ctx?.tags.includes(\"memory-cache\") ? 0 : 1), // You can adjust strategy for deciding which cache should the composite use\n        }),\n      ],\n    };\n\n    return global.cacheHandlerConfig;\n  })();\n\n  return global.cacheHandlerConfigPromise;\n});\n\nexport default CacheHandler;\n```\n\n---\n\n## Reference to Original Package\n\nThis project was originally based on [`@neshca/cache-handler`](https://www.npmjs.com/package/@neshca/cache-handler). Versions prior to `2.0.0` wrapped or extended the original. As of `2.0.0`, this project is fully independent and no longer uses or requires `@neshca/cache-handler`.\n\nFor context or historical documentation, you may still reference the [original project](https://caching-tools.github.io/next-shared-cache).\n\n## neshClassicCache\n\n⚠️ Deprecated: This function was migrated from @neshca for compatibility purposes only. Use with caution - no further development or support is planned.\n\n`neshClassicCache` allows you to cache the results of expensive operations, like database queries, and reuse them across multiple requests. Unlike the [`neshCache`](/functions/nesh-cache) or [`unstable_cache` ↗](https://nextjs.org/docs/app/api-reference/functions/unstable_cache) function, `neshClassicCache` must be used in a Next.js Pages Router allowing users to cache data in the `getServerSideProps` and API routes.\n\n\n\u003e [!NOTE]\n\u003e\n\u003e Cache entries created with `neshClassicCache` can be revalidated only by the [`revalidateTag` ↗](https://nextjs.org/docs/app/api-reference/functions/revalidateTag) method.\n\n### Parameters\n\n#### `fetchData`\n\nThis is an asynchronous function that fetches the data you want to cache. It must be a function that returns a `Promise`.\n\n#### `commonOptions`\n\nThis is an object that controls how the cache behaves. It can contain the following properties:\n\n- `tags` - An array of tags to associate with the cached result. Tags are used to revalidate the cache using the `revalidateTag` and `revalidatePath` functions.\n\n- `revalidate` - The revalidation interval in seconds. Must be a positive integer or `false` to disable revalidation. Defaults to `export const revalidate = time;` in the current route.\n\n- `argumentsSerializer` - A function that serializes the arguments passed to the callback function. Use it to create a cache key. Defaults to `JSON.stringify(args)`.\n\n- `resultSerializer` - A function that serializes the result of the callback function.Defaults to `Buffer.from(JSON.stringify(data)).toString('base64')`.\n\n- `resultDeserializer` - A function that deserializes the string representation of the result of the callback function. Defaults to `JSON.parse(Buffer.from(data, 'base64').toString('utf-8'))`.\n\n- `responseContext` - The response context object. If provided, it is used to set the cache headers acoording to the `revalidate` option. Defaults to `undefined`.\n\n### Returns\n\n`neshClassicCache` returns a function that when invoked, returns a `Promise` that resolves to the cached data. If the data is not in the cache, the provided function will be invoked, and its result will be cached and returned. The first argument is the `options` which can be used to override the common [`options`](/functions/nesh-classic-cache#commonoptions). In addition, there is a `cacheKey` option that can be used to provide a custom cache key.\n\n### Example\n\n```jsx filename=\"src/pages/api/api-example.js\" copy\nimport { neshClassicCache } from '@fortedigital/nextjs-cache-handler/functions';\nimport axios from 'axios';\n\nexport const config = {\n  runtime: 'nodejs',\n};\n\nasync function getViaAxios(url) {\n  try {\n    return (await axios.get(url.href)).data;\n  } catch (_error) {\n    return null;\n  }\n}\n\nconst cachedAxios = neshClassicCache(getViaAxios);\n\nexport default async function handler(request, response) {\n  if (request.method !== 'GET') {\n    return response.status(405).send(null);\n  }\n\n  const revalidate = 5;\n\n  const url = new URL('https://api.example.com/data.json');\n\n  // Add tags to be able to revalidate the cache\n  const data = await cachedAxios(\n    { revalidate, tags: [url.pathname], responseContext: response },\n    url,\n  );\n\n  if (!data) {\n    response.status(404).send('Not found');\n\n    return;\n  }\n\n  response.json(data);\n}\n```\n\n---\n\n## Contributing\n\nThis project uses [Turborepo](https://turbo.build/repo) to manage the monorepo structure with the main package and examples.\n\n### Prerequisites\n\n- Node.js \u003e= 22.0.0\n- pnpm \u003e= 9.0.0\n\n### Development Workflow\n\n- **Start dev server**: `pnpm dev` (runs all dev servers in parallel)\n- **Run all tests**: `pnpm test`\n\n---\n\n## License\n\nLicensed under the [MIT License](./LICENSE), consistent with the original `@neshca/cache-handler`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffortedigital%2Fnextjs-cache-handler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffortedigital%2Fnextjs-cache-handler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffortedigital%2Fnextjs-cache-handler/lists"}