definePlugin API
The definePlugin function is the entry point for extending Coralite's functionality. It allows you
to
inject server-side logic, register custom templates, and most importantly, bundle and configure client-side
scripts that can be used by your components.
Configuration Options #
The definePlugin function accepts a configuration object with the following properties:
import { definePlugin } from 'coralite'
const myPlugin = definePlugin({
name: 'my-plugin', // Required: Unique name for the plugin
// Optional: Main server-side logic
method: (options, context) => {
// ... implementation
},
// Optional: Register custom components
components: ['./path/to/component.html'],
// Optional: Client-side script configuration
client: {
setup: async () => { /* ... */ },
helpers: { /* ... */ },
imports: [ /* ... */],
config: { /* ... */ }
},
// Optional: Server-side lifecycle hooks
onPageSet: async (data) => { /* ... */ },
// ... other hooks
})
Server-Side Hooks #
Plugins can hook into Coralite's build lifecycle to perform actions when pages or components are processed.
onPageSet(data): Called when a page is created or updated.onPageUpdate(data): Called when a page is updated.onPageDelete(path): Called when a page is deleted.onComponentSet(data): Called when a component is registered.onBeforeBuild(): Called before the build process starts.onAfterBuild(): Called when the entire build process finishes.
Client-Side Scripting #
The client property is powerful: it allows you to inject code that runs in the browser. This code
is bundled with your application.
client.setup #
A client-side function that runs when the plugin is registered in the browser. Use it to prepare data or environment for the plugin in the frontend.
client.helpers #
Define helper functions that will be available to defineComponent scripts in the browser. To safely bridge global plugin configuration with local Web Component instances, Coralite requires client.helpers to be authored using a strict Two-Phase Currying System.
- Phase 1 (Global Context): The outermost function receives the
globalContext(containingimportsand globalconfig). - Phase 2 (Local Instance Context): It must return a second function that receives the local Web Component instance context (
{ values, root, signal }). Here,rootis the component'sHTMLElement(or Document), andsignalis anAbortSignal. - Phase 3 (Execution): It finally returns the final value (which can be a function, object, or primitive) that is injected into the client's
helpersobject for use in the browser script.
Note on signal: The signal is tied natively to the component's mount lifecycle. It triggers .abort() automatically when an imperative component is unmounted from the DOM, making it perfect for cleaning up event listeners. For declarative components, signal is null.
definePlugin({
name: 'utils',
client: {
helpers: {
// Phase 1: Receives Global Context
formatDate(globalContext) {
// Phase 2: Receives Local Instance Context
return ({ values, root, signal }) => {
// Phase 3: The actual helper function
return (date) => {
return new Date(date).toLocaleDateString()
}
}
}
}
}
})
Client Imports #
Use client.imports to make external libraries (npm packages, local files, or remote URLs)
available to your client-side helpers. Coralite handles the bundling and injection for you.
Import Types #
Remote Import (ESM) #
Import a library directly from a CDN.
imports: [
{
specifier: 'https://esm.sh/canvas-confetti@1.6.0',
defaultExport: 'confetti'
}
]
Local Import #
Import a local JavaScript module.
definePlugin({
name: 'analytics',
client: {
config: {
trackingId: 'UA-123456-7',
debug: true
},
// ...
}
})
JSON Import #
Import a JSON file as a module.
imports: [
{
specifier: './data/config.json',
defaultExport: 'config',
attributes: { type: 'json' }
}
]
Import Options #
specifier(string): The path or URL of the module.defaultExport(string): The name to assign to the default export.namedExports(string[]): List of named exports to import. Supports"original as alias"syntax.namespaceExport(string): Import the entire module as a namespace (import * as Name).
Client Configuration #
The client.config object allows you to pass static configuration data from the server (where the
plugin is defined) to the client (where helpers run). This is useful for API keys, theme settings, or feature
flags.
definePlugin({
name: 'analytics',
client: {
config: {
trackingId: 'UA-123456-7',
debug: true
},
// ...
}
})
Context Injection #
Both client.imports and client.config are automatically injected into the
globalContext object (Phase 1) passed to your helper factories.
Access them via:
globalContext.imports: Contains all imported modules/exports.globalContext.config: Contains the configuration object.
// Inside client.helpers
helpers: {
trackEvent: (globalContext) => {
const { trackingId } = globalContext.config;
const { analyticsLib } = globalContext.imports;
return ({ values, root, signal }) => {
return (eventName) => {
analyticsLib.send(trackingId, eventName);
}
}
}
}
Complete Example: Confetti Plugin #
Let's build a plugin that triggers a confetti explosion using a remote library and allows configuration of particle count.
import { definePlugin } from 'coralite'
export default definePlugin({
name: 'confetti-plugin',
client: {
// 1. Import the library
imports: [
{
specifier: 'https://esm.sh/canvas-confetti@1.6.0',
defaultExport: 'confetti'
}
],
// 2. Define default configuration
config: {
particleCount: 100,
spread: 70
},
// 3. Create the curried helper
helpers: {
explode: (globalContext) => {
// Phase 1: Access injected imports and config globally
const confetti = globalContext.imports.confetti
const config = globalContext.config
return ({ values, root, signal }) => {
// Phase 2: Local context (we don't need it for confetti, but must return it)
return () => {
// Phase 3: The actual execution
if (!confetti) {
console.warn('Confetti library not loaded')
return
}
// Use the library with the config
confetti({
particleCount: config.particleCount,
spread: config.spread,
origin: { y: 0.6 }
})
}
}
}
}
}
})
<p><strong>Usage in a component:</strong></p>
<coralite-code-html>
<template id="celebration-button">
<button ref="btn">Celebrate!</button>
</template>
<script type="module">
import { defineComponent } from 'coralite'
export default defineComponent({
script: (context) => {
const { helpers } = context
const btn = helpers.refs('btn')
// The fully curried 'explode' helper is now available
const explode = helpers.explode
btn.addEventListener('click', () => {
explode()
})
}
})
</script>
</coralite-code-html>