# Package runtimes and automatic assets ## User experience Installing an advanced package should be enough: ```bash bun add @wrnexus/captcha ``` Then use its component: ```wrn ``` The user does not copy JavaScript, add a public asset, add a script tag, or duplicate the component. ## Declaring a package plugin ```json { "name": "@example/maps", "wrnexus": { "plugin": { "plugin": "./src/plugin.ts", "export": "default", "factory": true } } } ``` ```ts import { definePlugin } from "@wrnexus/plugin"; export default function mapsPlugin() { return definePlugin({ name: "@example/maps", componentDirs: [new URL("../components", import.meta.url).pathname], clientRuntimes: [ { id: "maps", entry: new URL("../client/maps.ts", import.meta.url).pathname, type: "module", load: "defer", singleton: true, }, ], styleSources: [ { id: "maps-components", source: new URL("../components", import.meta.url).pathname, }, ], }); } ``` The rendered component declares: ```html
``` ## Development behavior - Runtime URL defaults to `/__wrnexus/assets/maps.js`. - JavaScript files can be served directly. - TypeScript/TSX entries are bundled for the browser. - MIME type is JavaScript and `X-Content-Type-Options: nosniff` is set. - Assets use `no-cache` during development. - Workspace package sources participate in HMR. ## Production behavior - Runtime entries are browser-bundled and minified when required. - The emitted filename includes a SHA-256 content hash. - The asset is served with an immutable cache policy. - The final HTML includes the runtime only when its marker appears. - Multiple instances inject one script. - Build reports list plugins, runtime chunks, assets, component directories, routes, and migrations. ## CSR navigation Before replacing `#app`, WRNexusJS calls package `unmount` hooks for runtimes used by the current content. It imports script attributes from the fetched document, loads missing chunks once, then calls `mount` for the new page. ## Security requirements - Runtime and asset IDs are validated. - Duplicate IDs and public paths fail startup/build. - Local package asset paths cannot contain traversal segments. - Production builds do not rely on application public-directory copies. - Secrets must remain server-side; browser runtimes receive only public configuration and one-use response tokens.