CoordiationCSS
Menu
Docs/Core concepts/Plugin API

CORE CONCEPT · COMPLETE

Plugin API

Package a reusable Coordiation extension once, then use the same validated utility, variant, theme, and source-scanning behavior from the compiler, Vite, or PostCSS.

A plugin is code, not configuration data. Load only trusted packages, keep setup() synchronous, and inspect the compile manifest before an agent generates plugin-owned classes.

01

Define an identifiable plugin

Give every plugin a stable lowercase package-style name and version. The factory brands the object so unvalidated lookalikes cannot enter the compiler pipeline.

interface-kit.js
import { defineCoordiationPlugin } from "@coordiation/css";

export const interfaceKit = defineCoordiationPlugin({
  name: "@acme/coordiation-interface-kit",
  version: "1.0.0",
  setup(api) {
    // Register the extension here.
  },
});
02

Add static or functional utilities

Object keys omit the configured utility prefix. Property names may use CSS syntax or camel case, and functional patterns reuse the same co-value() and co-modifier() contract as CSS-first custom utilities.

Plugin setup
setup({ addUtilities }) {
  addUtilities({
    "content-auto": {
      contentVisibility: "auto",
      containIntrinsicSize: "auto 1000px",
    },
    "editor-tab-*": {
      tabSize: "co-value(--co-tab-size-*, integer, [integer])",
    },
  });
}
03

Share variants and theme values

A single string creates a selector or conditional wrapper. An ordered array creates a compound variant around the generated rule.

Plugin setup
setup({ addVariant, extendTheme }) {
  extendTheme({
    colors: { accent: "oklch(62% 0.18 260)" },
    tabSizes: { editor: "8" },
  });

  addVariant("workspace", "&:where([data-workspace] *)");
  addVariant("can-hover", [
    "@media (any-hover: hover)",
    "&:hover",
  ]);
}
Template
<main class="workspace:co-bg-accent md:can-hover:!co-underline">
  ...
</main>
04

Extend source discovery explicitly

Register an extension-specific extractor for a custom template language and safelist only complete literal candidates. Extractors may be asynchronous; plugin setup may not.

Plugin setup
setup({ addExtractor, addSafelist }) {
  addExtractor(".widget", async (source, context) => {
    return parseWidgetClasses(source, context.file);
  });

  addSafelist([
    "co-bg-accent",
    "workspace:co-content-auto",
  ]);
}
05

Use one plugin in every JavaScript integration

The same plugins array works in direct compilation, Vite, and PostCSS. Vite also adds plugin-owned source extensions to its watch boundary.

vite.config.js
import { defineConfig } from "vite";
import coordiation from "@coordiation/vite";
import { interfaceKit } from "./interface-kit.js";

export default defineConfig({
  plugins: [coordiation({
    content: ["src"],
    cssFile: "src/coordiation.css",
    plugins: [interfaceKit],
  })],
});
Direct compiler
const result = compile(inputCss, candidates, {
  plugins: [interfaceKit],
});

DETERMINISTIC PRECEDENCE

Project ownership remains final

Registrations are merged in one documented order.

  1. 01

    Plugin array: plugins run left to right; a later plugin replaces an identical plugin pattern or variant.

  2. 02

    Application options: explicitly supplied theme, utility, or variant definitions replace plugin defaults.

  3. 03

    CSS entry: @co-theme, @co-utility, and @co-variant remain the final authority.

  4. 04

    Output: all successful candidates continue through canonical ordering and static CSS generation.

06

Audit the effective plugin surface

Compile results expose identity and registered names without leaking or attempting to serialize runtime extractor functions.

JavaScript
console.log(result.plugins);
// [{
//   name: "@acme/coordiation-interface-kit",
//   version: "1.0.0",
//   utilities: ["content-auto", "editor-tab-*"],
//   variants: ["workspace", "can-hover"],
//   theme: { colors: ["accent"], tabSizes: ["editor"] },
//   extractors: [".widget"],
//   safelist: ["co-bg-accent"]
// }]

AI GENERATION CONTRACT

Resolve identity before capability

Agents should use the effective manifest and compiler result instead of guessing from a package name.

  • Match the exact plugin name and version before using its registered surface.
  • Generate only utility patterns and variant names present in the effective project contract.
  • Keep safelist and extractor output as complete literal candidates.
  • Respect plugin, application-option, and CSS-first precedence.
  • Report rejected candidates and plugin validation errors instead of inventing a fallback.