lunx.docs
DocsTutorialsUsing Plugins

Using Plugins

Extend Lunx with official and community plugins. Learn the plugin lifecycle, write custom build actions, and compose multiple plugins safely.

Installing a plugin

Install the plugin package, then add it to the plugins array in lunx.config.ts. Plugin order matters — plugins run in array order during the build.

bash
npm install --save-dev @lunx/plugin-compress @lunx/plugin-pwa
typescriptlunx.config.ts
import { defineConfig }  from 'lunx'
import compress           from '@lunx/plugin-compress'
import pwa                from '@lunx/plugin-pwa'

export default defineConfig({
  framework: 'react',
  plugins: [
    // Plugins run in order — compress before pwa
    compress({ algorithm: 'brotli', threshold: 1024 }),
    pwa({
      name:      'My Lunx App',
      shortName: 'LunxApp',
      themeColor: '#2563eb',
      icons: [
        { src: '/icons/192.png', sizes: '192x192' },
        { src: '/icons/512.png', sizes: '512x512' },
      ],
    }),
  ],
})

Plugin lifecycle hooks

Lunx plugins are plain objects with a name string and optional hook functions. Hooks are called by the Rust compiler orchestrator at the appropriate build stage.

resolveId()

Intercepts module path resolution. Return a custom ID to redirect imports to a virtual module or an alternative path.

load()

Loads module content from a custom source. Return source code as a string to bypass the file system entirely.

transform()

Transform module source code. Receives the source and module ID. Return modified code and optional source map.

generateBundle()

Called after all chunks are generated, before files are written. Modify or add output files programmatically.

closeBundle()

Called after the bundle has been written. Use for post-build tasks like notifications or upload scripts.

Writing a custom plugin

Custom plugins are declared inline in lunx.config.ts or in a separate file. The TypeScript type LunxPlugin provides full autocomplete.

typescriptlunx.config.ts
import { defineConfig, type LunxPlugin } from 'lunx'

// Inline plugin — injects a build banner into every JS chunk
function bannerPlugin(banner: string): LunxPlugin {
  return {
    name: 'banner-plugin',
    generateBundle(options, bundle) {
      for (const [fileName, chunk] of Object.entries(bundle)) {
        if (chunk.type === 'chunk') {
          chunk.code = `/* ${banner} */\n${chunk.code}`
        }
      }
    }
  }
}

// Virtual module plugin — exposes build metadata to the app
function buildInfoPlugin(): LunxPlugin {
  const virtualId = 'virtual:build-info'
  const resolvedId = '\0' + virtualId

  return {
    name: 'build-info',
    resolveId(id) {
      if (id === virtualId) return resolvedId
    },
    load(id) {
      if (id === resolvedId) {
        return `export const buildTime = '${new Date().toISOString()}';
export const version = '${process.env.npm_package_version}';`
      }
    }
  }
}

export default defineConfig({
  framework: 'react',
  plugins: [
    bannerPlugin('Built with Lunx v1.0.0'),
    buildInfoPlugin(),
  ],
})

Using the virtual module in your app

typescript
// src/components/Footer.tsx
import { buildTime, version } from 'virtual:build-info'

export function Footer() {
  return (
    <footer className="text-xs text-gray-500 p-4 text-center">
      v{version}  built {new Date(buildTime).toLocaleDateString()}
    </footer>
  )
}

Transform plugin example

Use the transform hook to modify source code at compile time. The example below strips all console.log calls from production builds.

typescript
function stripConsolePlugin(): LunxPlugin {
  return {
    name: 'strip-console',
    transform(code, id) {
      // Only run in production, skip node_modules
      if (process.env.NODE_ENV !== 'production') return
      if (id.includes('node_modules')) return

      const cleaned = code.replace(
        /console\.log\([^)]*\);?/g,
        '/* console.log removed */'
      )
      return { code: cleaned, map: null }
    }
  }
}
Plugin sandbox
Third-party plugins run inside the Lunx sandbox. They must declare required permissions (network access, file system write) in their package.json manifest. Undeclared permissions are blocked and logged as a fatal error. Run lunx security plugins to audit installed plugins.