Skip to content

Hook Execution

If you only remember one thing about plugin hooks, remember this: choose the latest hook that still gives you the control you need.

That keeps plugins easier to reason about and reduces accidental interference with other plugins.

Hook decision table

NeedHook
modify user config before defaults are appliedconfigureRawConfig
inspect or alter resolved defaultsconfigureResolvedConfig
call engine APIs and register behaviorconfigureEngine
rewrite style items before extractiontransformStyleItems
rewrite selector chainstransformSelectors
rewrite nested style definitionstransformStyleDefinitions
observe engine events onlysync notification hooks

Payload chaining

Async hooks can return a new payload. That new payload is passed to the next plugin in order.

ts
import { defineEnginePlugin } from '@pikacss/core'

export const asyncHookPlugin = defineEnginePlugin({
	name: 'async-hook-example',

	// Async hook: modify the raw config before it is resolved.
	// Return the modified config to pass it to the next plugin,
	// or return void/undefined to keep the current value.
	configureRawConfig(config) {
		config.prefix = 'pk-'
		return config
	},

	// Async hook: transform selectors during style extraction.
	// The returned array replaces the input for the next plugin.
	transformSelectors(selectors) {
		return selectors.map(s => s.replace('$hover', '&:hover'))
	},
})

The practical consequence is simple: plugins that return transformed payloads should be explicit and conservative, because later plugins will see that modified result.

Error isolation

Hook errors are caught and logged so one broken plugin does not break the full chain by default. That is good for resilience, but it also means silent plugin failure can look like missing behavior if you do not inspect logs.

Notification hooks are for observation

Notification hooks exist so integrations or plugins can react to changes such as preflight updates, atomic style generation, or autocomplete updates.

ts
import { defineEnginePlugin } from '@pikacss/core'

export const plugin = defineEnginePlugin({
	name: 'example',

	// Sync — called when a new atomic style is generated
	atomicStyleAdded(atomicStyle) {
		console.log(`New atomic style: ${atomicStyle.id}`)
	},

	// Sync — called when preflights are updated
	preflightUpdated() {
		console.log('Preflights updated')
	},

	// Sync — called when autocomplete config changes
	autocompleteConfigUpdated() {
		console.log('Autocomplete config updated')
	},
})

A practical rule for plugin authors

Start with configureEngine. Only move earlier or deeper into transforms when a concrete limitation forces you there.

Next