Skip to content

Plugin API

ExtForge plugins are TypeScript objects implementing ExtForgePluginV1. They register hooks during setup() and the runner fires those hooks at well-defined points in the build.

EntryDescriptor

Describes a single entry point to be bundled by esbuild.

MemberTypeDescription
namestringLogical name used to derive the output filename.
filestringAbsolute or root-relative path to the entry source file.
format"esm" | "iife"Output bundle format.
esbuildOptions?Record<string, unknown> | undefinedExtra esbuild options merged into this entry’s build.
isContentScript?boolean | undefinedWhether this entry is a content script (affects IIFE wrapping).

PluginHooks

Hook registration methods available inside a plugin’s setup() call.

MemberTypeDescription
onConfigResolved(fn: (config: ExtForgeConfig) => void | Promise<void>) => voidCalled once after config resolution, before any build.
onManifestTransform(fn: (manifest: ManifestObject, browser: Browser) => ManifestObject | Promise<ManifestObject>) => voidCalled for each browser after the manifest is assembled, allowing mutation.
onBuildStart(fn: (info: { browser: Browser; dev: boolean; }) => void | Promise<void>) => voidCalled at the start of each browser build.
onBuildEntry(fn: (entry: EntryDescriptor) => EntryDescriptor | void | Promise<EntryDescriptor | void>) => voidCalled once per entry point, allowing plugins to mutate or replace the descriptor.
onBuildEnd(fn: (result: BuildResult) => void | Promise<void>) => voidCalled after all entries for a browser have been bundled.
onDevReload(fn: (event: HMRUpdate) => void | Promise<void>) => voidCalled in dev mode each time the HMR server dispatches a reload event.

PluginContext

Runtime context injected into every plugin’s setup() function.

MemberTypeDescription
configExtForgeConfigThe resolved ExtForge configuration for the current build.
paths{ readonly root: string; readonly src: string; readonly dist: string; }Resolved absolute paths for the project root, source, and output directories.
loggerLoggerLogger instance scoped to the plugin runner.
hooksPluginHooksHook registration object for this plugin’s subscriptions.
addEntry(entry: EntryDescriptor) => voidAdds a synthetic entry point to the build without touching the config.
emitFile(rel: string, contents: string | Uint8Array<ArrayBufferLike>) => voidWrites a file to the output directory at the given relative path.

ExtForgePluginV1

A plugin written against the v1 ExtForge plugin API.

MemberTypeDescription
namestringUnique-ish identifier; surfaces in logs and error messages.
apiVersion1Required discriminator; routes the runner to the modern API.
setup(ctx: PluginContext) => void | Promise<void>Called once after config resolution. Plugins register hooks here.

ExtForgePluginLegacy

Thin legacy plugin shape accepted for backwards compatibility.

MemberTypeDescription
namestringUnique-ish identifier; surfaces in logs and error messages.
setup?((config: ExtForgeConfig) => void | Promise<void>) | undefinedOptional hook called once with the resolved config.
buildStart?(() => void | Promise<void>) | undefinedOptional hook called at the start of each build.
buildEnd?((result: unknown) => void | Promise<void>) | undefinedOptional hook called after each build completes.

Example

import type { ExtForgePluginV1 } from 'extforge/plugins';
export function presetTailwind(): ExtForgePluginV1 {
return {
name: 'extforge:preset-tailwind',
apiVersion: 1,
setup({ hooks, logger }) {
hooks.onBuildEntry((entry) => entry);
},
};
}