{"id":15155393,"url":"https://github.com/phildl/vite-plugin-frontmatter-collection","last_synced_at":"2026-02-26T02:46:42.654Z","repository":{"id":256714965,"uuid":"856199712","full_name":"PhilDL/vite-plugin-frontmatter-collection","owner":"PhilDL","description":"🗂️ Collect the frontmatter of your MD(X) files, parse, typecheck and create importable virtual module of the entries.","archived":false,"fork":false,"pushed_at":"2024-09-12T07:41:57.000Z","size":135,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-07T00:07:37.403Z","etag":null,"topics":["frontmatter","markdown","mdx","vite-plugin"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/vite-plugin-frontmatter-collection","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/PhilDL.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2024-09-12T06:57:04.000Z","updated_at":"2024-09-20T15:35:50.000Z","dependencies_parsed_at":"2024-09-12T17:15:46.281Z","dependency_job_id":null,"html_url":"https://github.com/PhilDL/vite-plugin-frontmatter-collection","commit_stats":null,"previous_names":["phildl/vite-plugin-frontmatter-collection"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilDL%2Fvite-plugin-frontmatter-collection","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilDL%2Fvite-plugin-frontmatter-collection/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilDL%2Fvite-plugin-frontmatter-collection/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilDL%2Fvite-plugin-frontmatter-collection/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PhilDL","download_url":"https://codeload.github.com/PhilDL/vite-plugin-frontmatter-collection/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252008690,"owners_count":21679623,"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":["frontmatter","markdown","mdx","vite-plugin"],"created_at":"2024-09-26T18:21:15.147Z","updated_at":"2026-02-26T02:46:42.627Z","avatar_url":"https://github.com/PhilDL.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vite-plugin-frontmatter-collection\n\nParse the frontmatter of your collection of MD(X) files, and make it accessible through a fully type-safe virtual module. With Zod schemas, auto-generated ambient types declaration, and frontmatter validation with HMR.\n\n## Features\n\n- 🗂️ Parse your collection of MD(X) files and create virtual module of the frontmatter data\n- ✨ Zod schema validation and auto generation of a d.ts file for the virtual module.\n- 🦾 Enforce the schema on the frontmatter data of your content while editing!\n- 🔥 Hot module reload when the content frontmatter change.\n\n## Usage\n\nInstall\n\n```bash\nnpm i vite-plugin-frontmatter-collection -D\n# pnpm add vite-plugin-restart -D\n```\n\nAdd it to `vite.config.js`\n\n```ts\n// vite.config.js\nimport { defineConfig } from \"vite\";\nimport {\n  defineCollection,\n  frontmatterCollectionPlugin,\n} from \"vite-plugin-frontmatter-collection\";\nimport { z } from \"zod\";\nimport { FormationCollectionSchema } from \"./app/content-collections-schemas\";\n\nexport default defineConfig({\n  plugins: [\n    frontmatterCollectionPlugin({\n      typesPath: \"./types/frontmatter-collection.d.ts\",\n      collections: [\n        defineCollection({\n          name: \"blogEntries\",\n          include: \"./app/routes/_frontend+/blog/**/*.mdx\",\n          schema: z.object({\n            title: z.string().optional(),\n            description: z.string().optional(),\n            author: z.string(),\n            date: z.date(),\n            category: z.string().optional(),\n            filePath: z.string(),\n          }),\n          sort: (a, b) =\u003e {\n            const aTime = new Date(a.date ?? \"\").getTime();\n            const bTime = new Date(b.date ?? \"\").getTime();\n            return aTime \u003e bTime ? -1 : aTime === bTime ? 0 : 1;\n          },\n        }),\n        defineCollection({\n          name: \"formationsEntries\",\n          include: \"./app/routes/_frontend+/formations/**/*.mdx\",\n          // imported zod schema\n          schema: FormationCollectionSchema,\n        }),\n      ],\n    }),\n  ],\n});\n```\n\nNow you can import the collection in your code\n\n```ts\nimport { blogEntries, formationsEntries } from \"virtual:frontmatter-collection\";\n```\n\nWith default options, you have types that are auto-generated from the schemas and collection names you provided.\n\n```ts\n// This file is auto-generated. Do not edit manually.\ndeclare module \"virtual:frontmatter-collection\" {\n  export const blogEntries: {\n    title?: string | undefined;\n    description?: string | undefined;\n    author: string;\n    date: Date;\n    category?: string | undefined;\n    filePath: string;\n  }[];\n  export const formationsEntries: {\n    meta: {\n      [x: string]: string;\n    }[];\n    handle?: any | undefined;\n    headers?:\n      | {\n          [x: string]: string;\n        }\n      | undefined;\n    date: Date;\n    image: string;\n    thumbnail: string;\n    tags?: string[] | undefined;\n    title?: string | undefined;\n    description?: string | undefined;\n    level?: number;\n    durationHours: number;\n    durationDays: number;\n    price: number;\n    nextStartDate?: Date | undefined;\n    groupSize?: string | undefined;\n    filePath: string;\n  }[];\n}\n```\n\nIf the `.d.ts` file is generated in the `types` folder at the root of your project, make sure that the folder si parsed by your `tsconfig.json`:`\n\n```json\n{\n  \"include\": [\n    \"types/**/*\",\n    //...\n  /...\n```\n\n## Plugin Options\n\n```ts\nexport type FrontMatterCollectionPluginConfig = {\n  typesPath?: string;\n  generateDTS?: boolean;\n  debug?: boolean;\n  collections: FrontmatterCollectionConfig[];\n};\n```\n\n- `typesPath` (optionnal) Path to the generated types file.\n- `generateDTS` (optionnal, default=`true`) Generate the `.d.ts` file for the virtual module. Deactivate to handle the create the ambient declaration file yourself.\n- `debug` (optionnal, default=`false`) Enable debug logs that show you the parsed content.\n- `collections` (required) Array of collection definitions.\n\n### `collection` definition:\n\n- `name` (required) The name of the collection, will also be the name of the export.\n- `include` (required) A glob pattern to match the files to include.\n\nYou have the choice between giving a `schema` or a `parseFrontMatter` function to parse the frontmatter of the included files into the desired shape.\n\n- `schema` (optionnal) A zod schema to validate the frontmatter data.\n- `parseFrontMatter` (optionnal) A function to parse the frontmatter of the included files into the desired shape.\n\nA Zod `schema` will auto-generate the `.d.ts` module declaration file, but if instead you give it a `parseFrontMatter` function, you will have to manually create the types.\n\nThere is also some utilities to sort and filter the results before export.\n\n- `sort` (optionnal) An optionnal function to sort the collection.\n- `filter` (optionnal) An optional filter function to filter the collection.\n\nTo have typesafety in the `sort` and `filter` function you should define the collection object with the `defineCollection` helper.\n\n#### `collection` api\n\n````ts\nexport type FrontmatterCollectionConfig\u003cT = any\u003e = {\n  /**\n   * The name of the collection, will also be the name of the export\n   */\n  name: string;\n  /**\n   * A glob pattern to match the files to include\n   */\n  include: string;\n  /**\n   * Instead of a zod schema, you can provide a function to parse\n   * the frontmatter of the included files into the desired shape.\n   * You will not get automatic generation of the virtual module declaration file.\n   *\n   * @param fm - The frontmatter object\n   * @returns The parsed frontmatter\n   * @example\n   * ```ts\n   * parseFrontMatter: (fm) =\u003e {\n   *   return {\n   *     title: fm.attributes.meta.find((m) =\u003e m.title)?.title ?? \"\",\n   *     description: fm.attributes.meta.find((m) =\u003e m.name === \"description\")?.content ?? \"\",\n   *     date: fm.attributes.date,\n   *   };\n   * }\n   * ```\n   */\n  parseFrontMatter?: (fm: { [key: string]: any; filePath: string }) =\u003e T;\n  /**\n   * A Zod schema to validate the frontmatter, this provides automatic\n   * generation of the virtual module declaration file.\n   *\n   * @example\n   * ```ts\n   * schema: z.object({\n   *  title: z.string().optional(),\n   *  description: z.string().optional(),\n   *  author: z.string(),\n   *  date: z.date(),\n   *  filePath: z.string(),\n   * })\n   */\n  schema?: z.ZodSchema\u003cT\u003e;\n  /**\n   * An optionnal function to sort the collection\n   * @param a - The first item to compare\n   * @param b - The second item to compare\n   * @returns A number indicating the sort order\n   * @example\n   * ```ts\n   * sort: (a, b) =\u003e {\n   *   const aTime = new Date(a.date ?? \"\").getTime();\n   *   const bTime = new Date(b.date ?? \"\").getTime();\n   *   return aTime \u003e bTime ? -1 : aTime === bTime ? 0 : 1;\n   * }\n   * ```\n   */\n  sort?: (a: T, b: T) =\u003e number;\n  /**\n   * An optional filter function to filter the collection\n   * @param a - The item to filter\n   * @returns A boolean indicating if the item should be included\n   * @example\n   * ```ts\n   * filter: (a) =\u003e a.published\n   * ```\n   */\n  filter?: (a: T) =\u003e boolean;\n  /**\n   * An optional glob pattern to ignore files\n   */\n  ignore?: string | string[];\n};\n````\n\n## Motivation\n\nI wanted an easy way to import my posts collection, make sure I don't forget any attributes and hot module reload while I edit MDX content.\n\n## License\n\nMIT License © 2024 [L'ATTENTION Philippe](https://github.com/PhilDL)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphildl%2Fvite-plugin-frontmatter-collection","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphildl%2Fvite-plugin-frontmatter-collection","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphildl%2Fvite-plugin-frontmatter-collection/lists"}