docs: add AGENTS.md, ARCHITECTURE.md, and EXAMPLES.md for LLM-assisted plugin development

This commit is contained in:
saberzero1 2026-04-03 19:07:39 +02:00
parent bc03ed7366
commit ea06f6850c
No known key found for this signature in database
3 changed files with 295 additions and 0 deletions

90
AGENTS.md Normal file
View file

@ -0,0 +1,90 @@
# Quartz Community Plugin Template
Provider-agnostic instruction file for AI coding assistants developing Quartz community plugins.
## Project Overview
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.
## Plugin Type Decision Tree
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-page` system.
## Files to Modify
- `src/`: All plugin logic, components, and styles.
- `package.json`: Plugin manifest (`quartz` field), dependencies, and metadata.
- `src/i18n/`: Translations for multi-language support.
## Leave Alone
- `dist/`: Build output.
- `.github/`: CI/CD workflows (unless customizing publishing).
- `tsup.config.ts`: Build configuration.
## Plugin Creation Workflow
1. **Define Options**: Create an interface for plugin configuration in `src/types.ts`.
2. **Implement Logic**: Create the plugin factory in a new file (e.g., `src/my-plugin.ts`).
3. **Export**: Add the plugin to `src/index.ts`.
4. **Manifest**: Update the `quartz` field in `package.json` with category and default options.
5. **Test**: Add a test case in `src/tests/` and run `npm test`.
6. **Build**: Run `npm run build` to verify the bundle.
## Package.json Quartz Manifest
The `quartz` field is required for discovery and configuration:
```json
{
"quartz": {
"name": "my-plugin",
"category": ["transformer", "component"],
"defaultOptions": { "enabled": true },
"optionSchema": { "enabled": { "type": "boolean" } },
"components": { "MyComponent": { "defaultPosition": "right" } }
}
}
```
## Import Patterns
- **Types**: Import from `@quartz-community/types`.
- **Utils**: Import from `@quartz-community/utils`.
- **Runtime**: Use `vfile` for content manipulation in transformers.
## i18n Setup
1. Add keys to `src/i18n/locales/en-US.ts`.
2. Create other locales in `src/i18n/locales/`.
3. Use the `i18n` helper in your plugin or component.
## Common Mistakes
- **Missing Exports**: Forgetting to export the plugin factory from `src/index.ts`.
- **Wrong Category**: Not matching the `category` in `package.json` with the implemented hooks.
- **Peer Dependencies**: Adding `preact` or `vfile` as `dependencies` instead of `peerDependencies`.
## Testing Patterns
Use `vitest`. Mock the `BuildCtx` and `ProcessedContent` when testing transformers or emitters.
## Checklist Before Submission
- [ ] `npm run build` completes without errors.
- [ ] `npm test` passes all cases.
- [ ] `package.json` manifest is complete and accurate.
- [ ] `README.md` documents all options.
## Build System Quirks
- **.inline.ts**: Files ending in `.inline.ts` are 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 `FullSlug` and `FilePath` from `@quartz-community/types` for path safety.

73
ARCHITECTURE.md Normal file
View file

@ -0,0 +1,73 @@
# Architecture Reference
Machine-readable architecture overview for the Quartz community plugin template.
## Plugin Lifecycle
Quartz plugins are factory functions that return an object with a `name` and lifecycle hooks.
1. **Loading**: Quartz imports the plugin from the `externalPlugins` list in `quartz.config.ts`.
2. **Initialization**: The factory function is called with user-provided options.
3. **Build Integration**:
- **Transformers**: Run during the `transform` phase (remark/rehype).
- **Filters**: Run after transformation to prune the content list.
- **Emitters**: Run during the `emit` phase to generate files.
- **Page Types**: Run to generate virtual pages or custom routes.
- **Components**: Rendered during the HTML generation phase.
## Build System
The template uses `tsup` for bundling and declaration output.
- **Inline Scripts**: Files ending in `.inline.ts` are bundled as raw strings for client-side injection.
- **Styles**: `.scss` files are compiled to CSS strings and attached to components via `Component.css`.
- **Entry Points**:
- `index.ts`: Main plugin exports.
- `types.ts`: Shared type definitions.
- `components/index.ts`: UI component exports.
## Type System
The template relies on `@quartz-community/types` for core Quartz types.
- **Branded Types**: `FullSlug` and `FilePath` are used for path safety.
- **vfile DataMap**: Augmented with `QuartzPluginData` for plugin-specific metadata.
- **Plugin Interfaces**: `QuartzTransformerPlugin`, `QuartzFilterPlugin`, `QuartzEmitterPlugin`, `QuartzPageTypePlugin`, `QuartzComponentConstructor`.
## Export Conventions
- **Default Exports**: Used for components.
- **Named Exports**: Used for plugin factories and types.
- **Re-exports**: `src/index.ts` re-exports all public APIs.
## Dependency Management
- **peerDependencies**: `preact`, `vfile`, and `@jackyzha0/quartz` (optional).
- **dependencies**: `@quartz-community/types`, `@quartz-community/utils`.
- **devDependencies**: Build tools, linters, and test runners.
## Testing Infrastructure
- **vitest**: Test runner.
- **test helpers**: Mock `BuildCtx` and `ProcessedContent` for plugin testing.
## CI/CD Pipeline
- **GitHub Actions**: Runs `npm run check` on PRs and publishes to npm on version tags (`v*`).
## Directory Structure
- `src/`: Source code.
- `components/`: UI components.
- `scripts/`: Client-side scripts (`.inline.ts`).
- `styles/`: Component styles (`.scss`).
- `i18n/`: Internationalization.
- `util/`: Utility functions.
- `index.ts`: Main entry point.
- `types.ts`: Type definitions.
- `transformer.ts`: Transformer implementation.
- `filter.ts`: Filter implementation.
- `emitter.ts`: Emitter implementation.
- `dist/`: Build output.
- `package.json`: Manifest and dependencies.
- `tsup.config.ts`: Build configuration.

132
EXAMPLES.md Normal file
View file

@ -0,0 +1,132 @@
# Plugin Examples
Minimal, annotated examples for each Quartz plugin type.
## 1. Minimal Transformer
Wraps an existing remark plugin to enforce hard line breaks.
```ts
import remarkBreaks from "remark-breaks";
import type { QuartzTransformerPlugin } from "@quartz-community/types";
export const HardLineBreaks: QuartzTransformerPlugin<void> = () => ({
name: "HardLineBreaks",
markdownPlugins() {
// Return a list of unified/remark plugins
return [remarkBreaks];
},
});
```
## 2. Minimal Filter
Excludes pages marked as `draft: true` in frontmatter.
```ts
import type { QuartzFilterPlugin } from "@quartz-community/types";
export const RemoveDrafts: QuartzFilterPlugin<void> = () => ({
name: "RemoveDrafts",
shouldPublish(_ctx, [_tree, vfile]) {
// Access frontmatter from vfile data
const draft = vfile.data?.frontmatter?.draft;
// Return false to exclude the page from the build
return draft !== true;
},
});
```
## 3. Minimal Emitter
Writes a `CNAME` file to the output directory.
```ts
import fs from "node:fs/promises";
import path from "node:path";
import type { QuartzEmitterPlugin } from "@quartz-community/types";
export const CNAME: QuartzEmitterPlugin<{ domain: string }> = (opts) => ({
name: "CNAME",
async emit(ctx, _content, _resources) {
// ctx.argv.output is the destination directory
const filePath = path.join(ctx.argv.output, "CNAME");
await fs.writeFile(filePath, opts.domain);
// Return the list of emitted file paths
return [filePath as any];
},
});
```
## 4. Minimal Component
Renders a simple spacer div with custom CSS.
```tsx
import type { QuartzComponent, QuartzComponentConstructor } from "@quartz-community/types";
export default ((opts?: { height?: string }) => {
const Component: QuartzComponent = () => {
return <div class="spacer" style={{ height: opts?.height ?? "1rem" }} />;
};
// Attach CSS string to the component
Component.css = ".spacer { width: 100%; }";
return Component;
}) satisfies QuartzComponentConstructor;
```
## 5. Minimal Page Type
Generates a virtual "About" page if it doesn't exist.
```ts
import type { QuartzPageTypePlugin } from "@quartz-community/types";
export const AboutPage: QuartzPageTypePlugin<void> = () => ({
name: "AboutPage",
// Match the slug to handle
match: (slug) => slug === "about",
// Generate the page content
generate: async (_ctx, _content) => ({
slug: "about" as any,
frontmatter: { title: "About" },
content: "This is a virtual about page.",
}),
});
```
## 6. Minimal Bases View Registration
Registers a custom view for the `@quartz-community/bases-page` system.
```ts
import { viewRegistry } from "@quartz-community/bases-page";
export function init() {
// Register a view that can be used in bases-page layouts
viewRegistry.register("my-custom-view", (props) => {
return <div>Custom View for {props.fileData.slug}</div>;
});
}
```
## 7. Minimal i18n Setup
Per-plugin translations with a fallback mechanism.
```ts
// src/i18n/locales/en-US.ts
export default {
hello: "Hello",
};
// src/i18n/index.ts
import enUS from "./locales/en-US";
const locales = { "en-US": enUS };
export function i18n(locale: string) {
// Fallback to en-US if locale is not found
return locales[locale as keyof typeof locales] || enUS;
}
```