{"id":25238055,"url":"https://github.com/coana-tech/next-plugin-metadata-extractor","last_synced_at":"2026-02-12T08:33:52.369Z","repository":{"id":276795370,"uuid":"928344461","full_name":"coana-tech/next-plugin-metadata-extractor","owner":"coana-tech","description":"Next.js plugin to automatically extract metadata from pages","archived":false,"fork":false,"pushed_at":"2025-02-17T10:00:14.000Z","size":84,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-09-20T03:01:58.274Z","etag":null,"topics":["extractor","metadata","nextjs","plugin","searchindex","webpack"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coana-tech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2025-02-06T13:37:17.000Z","updated_at":"2025-02-17T08:10:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"2366d2f8-6c16-449f-af45-2477ecfa4a1b","html_url":"https://github.com/coana-tech/next-plugin-metadata-extractor","commit_stats":null,"previous_names":["coana-tech/next-plugin-metadata-extractor"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/coana-tech/next-plugin-metadata-extractor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coana-tech%2Fnext-plugin-metadata-extractor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coana-tech%2Fnext-plugin-metadata-extractor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coana-tech%2Fnext-plugin-metadata-extractor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coana-tech%2Fnext-plugin-metadata-extractor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coana-tech","download_url":"https://codeload.github.com/coana-tech/next-plugin-metadata-extractor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coana-tech%2Fnext-plugin-metadata-extractor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29361819,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T01:03:07.613Z","status":"online","status_checked_at":"2026-02-12T02:00:06.911Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["extractor","metadata","nextjs","plugin","searchindex","webpack"],"created_at":"2025-02-11T16:43:11.416Z","updated_at":"2026-02-12T08:33:52.354Z","avatar_url":"https://github.com/coana-tech.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @coana-tech/next-plugin-metadata-extractor\n\nA Next.js plugin that automatically extracts page metadata to a JSON file for site-wide search functionality.\n\n## Features\n\n- Automatically collects static metadata from Next.js pages during development and build\n- Updates metadata in real-time during development\n- TypeScript support\n- Zero configuration required\n\n## Example Metadata Output\n\n```json\n// metadata.json\n[\n  {\n    \"pathname\": \"/home\",\n    \"metadata\": {\n      \"title\": \"Home Page\",\n      \"description\": \"Home Page Description\"\n    }\n  },\n  {\n    \"pathname\": \"/about\",\n    \"metadata\": {\n      \"title\": \"About Page\",\n      \"description\": \"About Page Description\",\n      \"keywords\": [\"about\", \"page\", \"description\"]\n    }\n  }\n]\n```\n\n## Installation\n\n```bash\nnpm install @coana-tech/next-plugin-metadata-extractor\n# or\npnpm add @coana-tech/next-plugin-metadata-extractor\n# or\nyarn add @coana-tech/next-plugin-metadata-extractor\n```\n\n## Usage\n\n1. Add the plugin to your `next.config.js`:\n\n```js\n// next.config.js\nconst { MetadataCollectorPlugin } = require('@coana-tech/next-plugin-metadata-extractor');\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  webpack: (config, { isServer, dev }) =\u003e {\n    if (isServer) {\n      config.plugins.push(new MetadataCollectorPlugin({ dev }));\n    }\n    return config;\n  }\n};\n\nmodule.exports = nextConfig;\n```\n\n2. Define static metadata in your pages:\n\n```tsx\n// app/page.tsx\nimport type { Metadata } from 'next';\n\nexport const metadata: Metadata = {\n  title: \"My Page\",\n  description: \"My Page Description\",\n};\n```\n\nSee the [Next.js documentation](https://nextjs.org/docs/app/building-your-application/optimizing/metadata) for more information about defining metadata.\n\n**NOTE:** The plugin does not support dynamically computed metadata.\n\n\n3. Start the development server:\n\n```bash\nnpm run dev\n```\n\n4. Fetch the `metadata.json` file from the `public` directory:\n\n```tsx\n// app/components/Metadata.tsx\nimport { useState, useEffect } from 'react';\nimport type { PageMetadata } from '@coana-tech/next-plugin-metadata-extractor';\n\nfunction Component() {\n  const [metadata, setMetadata] = useState\u003cPageMetadata[]\u003e([]);\n\n  useEffect(() =\u003e {\n    fetch('/metadata.json')\n      .then(res =\u003e res.json())\n      .then(setMetadata);\n  }, []);\n\n  return (\n    \u003cdiv\u003e\n      {metadata.map(item =\u003e (\n        \u003cdiv key={item.pathname}\u003e{item.metadata.title}\u003c/div\u003e\n      ))}\n    \u003c/div\u003e\n  );\n}\n```\n\n## Configuration\n\nThe MetadataCollectorPlugin accepts the following configuration options:\n\n\n| Option | Description | Default |\n|--------|-------------|---------|\n| `outputPath` | Set output path for the metadata file, must end with `.json` | `public/metadata.json` |\n| `dir` | Set directory to search for page files | `app` |\n| `files` | Set files to collect from metadata, supports glob patterns | `[\"**/page.tsx\", \"**/page.ts\", \"**/page.jsx\", \"**/page.js\"]` |\n| `keys` | Set keys to collect from metadata | `['title', 'description', 'keywords', 'category']` |\n| `dev` | Enable development mode with debouncing | `false` |\n| `debounceTime` | Debounce time in milliseconds for dev mode updates | `1000` |\n\n\n## Advanced Usage\n\n### Server-side usage\n\nIf you don't want the metadata file to be public, set the `outputPath` to a server directory and create a server action to fetch the metadata.\n\nHere's an example:\n\n```tsx\n// next.config.js\nconst nextConfig = {\n  webpack: (config, { isServer, dev }) =\u003e {\n    isServer \u0026\u0026 config.plugins.push(new MetadataCollectorPlugin(\n      { \n        dev, \n        outputPath: 'src/actions/metadata.json', // \u003c-- output path\n      }\n    ));\n    return config;\n  }\n};\n\n// src/actions/metadata.ts\nimport metadata from './metadata.json';\nexport async function getMetadata() {\n  const { userId } = auth();\n\n  if (!userId) {\n    throw new Error('Unauthorized');\n  }\n\n  return metadata;\n} \n\n```\n\n### Adding Fuzzy Search\n\nYou can enhance the search functionality with fuzzy matching using libraries like Fuse.js. Here's an example:\n\n```typescript\nimport Fuse from 'fuse.js';\nimport type { PageMetadata } from '@coana-tech/next-plugin-metadata-extractor';\n\nfunction FuzzySearch() {\n  const [fuse, setFuse] = useState\u003cFuse\u003cPageMetadata\u003e | null\u003e(null);\n  const [results, setResults] = useState\u003cPageMetadata[]\u003e([]);\n\n  useEffect(() =\u003e {\n    // Load metadata and initialize Fuse.js\n    fetch('/metadata.json')\n      .then(res =\u003e res.json())\n      .then(data =\u003e {\n        setFuse(new Fuse(data, {\n          keys: ['metadata.title', 'metadata.description'],\n          threshold: 0.3,\n          distance: 100\n        }));\n      });\n  }, []);\n\n  const handleSearch = useCallback((term: string) =\u003e {\n    if (!fuse || !term.trim()) {\n      setResults([]);\n      return;\n    }\n    setResults(fuse.search(term).map(result =\u003e result.item));\n  }, [fuse]);\n\n  return (\n    \u003cdiv\u003e\n      \u003cinput type=\"text\" onChange={e =\u003e handleSearch(e.target.value)} /\u003e\n      \u003cul\u003e\n        {results.map(result =\u003e (\n          \u003cli key={result.pathname}\u003e{result.metadata.title}\u003c/li\u003e\n        ))}\n      \u003c/ul\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\nSee [Fuse.js documentation](https://fusejs.io/) for more configuration options.\n\n## Compatibility\n\nThis plugin is tested with Next.js 14.\n\n## License\n\nMIT","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoana-tech%2Fnext-plugin-metadata-extractor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoana-tech%2Fnext-plugin-metadata-extractor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoana-tech%2Fnext-plugin-metadata-extractor/lists"}