Provider-agnostic instruction file for AI coding assistants developing Quartz community plugins.
This repository is a template for building, testing, and publishing Quartz community plugins. It uses a factory-function API where plugins are created by functions returning objects with a name and lifecycle hooks.
Plugins are not mutually exclusive. A single plugin can implement multiple types.
- Transformer: Modifies content during the build (remark/rehype). Use if you need to change how Markdown is parsed or rendered.
- Filter: Decides which files to include in the final site. Use for drafts, private notes, or path-based exclusions.
- Emitter: Generates new files (JSON, RSS, CNAME, etc.). Use for site-wide manifests or integration files.
- Page Type: Defines custom routes and page generation logic. Use for virtual pages or non-Markdown content.
- Component: Provides UI elements for Quartz layouts. Use for navigation, sidebars, or custom widgets.
- Bases View: Registers custom views in the
@quartz-community/bases-pagesystem.
src/: All plugin logic, components, and styles.package.json: Plugin manifest (quartzfield), dependencies, and metadata.src/i18n/: Translations for multi-language support.
dist/: Build output. Gitignored. Built on install for git sources, pre-built in npm packages..github/: CI/CD workflows.ci.ymlruns checks,release.ymlhandles Changesets publishing..changeset/: Changesets configuration. Do not modifyconfig.json.tsup.config.ts: Build configuration. Defines SINGLETON_EXTERNALS and bundling strategy. Only modify to add native dep exclusions.
- Define Options: Create an interface for plugin configuration in
src/types.ts. - Implement Logic: Create the plugin factory in a new file (e.g.,
src/my-plugin.ts). - Export: Add the plugin to
src/index.ts. - Manifest: Update the
quartzfield inpackage.jsonwith category and default options. - Test: Add a test case in
src/tests/and runnpm test. - Build: Run
npm run buildto verify the build succeeds. - Changeset: Run
npx changesetto create a version bump description.
The quartz field is required for discovery and configuration:
{
"quartz": {
"name": "my-plugin",
"category": ["transformer", "component"],
"defaultOptions": { "enabled": true },
"optionSchema": { "enabled": { "type": "boolean" } },
"components": { "MyComponent": { "defaultPosition": "right" } }
}
}- Types: Import from
@quartz-community/types. - Utils: Import from
@quartz-community/utils. - Runtime: Use
vfilefor content manipulation in transformers.
- Add keys to
src/i18n/locales/en-US.ts. - Create other locales in
src/i18n/locales/. - Use the
i18nhelper in your plugin or component.
- Missing Exports: Forgetting to export the plugin factory from
src/index.ts. - Wrong Category: Not matching the
categoryinpackage.jsonwith the implemented hooks. - Peer Dependencies: Adding
preactorvfileasdependenciesinstead ofpeerDependencies. - Committing dist/: The
dist/directory is gitignored. npm packages ship pre-built; git sources build on install. - Bundling native deps: Plugins using
sharp,@napi-rs/*, or other NAPI packages must exclude them fromnoExternal.
Use vitest. Mock the BuildCtx and ProcessedContent when testing transformers or emitters.
-
npm run buildcompletes without errors. -
npm testpasses all cases. -
npm run buildoutput is correct (CI builds from source). -
package.jsonmanifest is complete and accurate. -
README.mddocuments all options.
- SINGLETON_EXTERNALS:
SINGLETON_EXTERNALSintsup.config.tsdefines packages that must NOT be bundled — they must be the same instance across all plugins (preact,vfile,unified,@jackyzha0/quartz). Everything else is bundled intodist/. - .inline.ts: Files ending in
.inline.tsare bundled as raw strings for client-side injection. - .scss: Styles are compiled to CSS strings and attached to components via
Component.css. - Branded Types: Use
FullSlugandFilePathfrom@quartz-community/typesfor path safety.