Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

HomeRunner plugin development

A HomeRunner plugin is a React component, an optional server-render module, and a manifest.json that tells the platform what you ship. You submit it as a source zip: you host nothing, and you never build the artifact a customer loads. A HomeRunner reviewer reads your source, runs your build, and publishes the result to the plugin CDN under an immutable version prefix. Customers then install it per feed and configure it in a dashboard form generated from your zod schema. From there your widget renders alongside first-party ones — server-rendered into Declarative Shadow DOM where the request supports it, hydrated by the platform’s shared runtime, or client-mounted on a CSR embed.

A plugin can carry a single widget or a whole suite of them under one version, one review and one publish — including layout widgets that host other widgets in named slots.

Start here

Building one widget? Read Install and versions, then Your first widget. npx create-hr-plugin my-plugin produces exactly this shape, and its dev sandbox and SSR preview both work out of the box.

Building a suite — several widgets, or a layout, or a one-click preset? Scaffold it directly with npx create-hr-plugin my-suite --template suite (create-hr-plugin 0.8.0+), which writes a working three-widget suite including a layout. Do the first-widget page anyway (the component, schema and build steps are identical), then Build a suite and Add a layout widget.

Choose deliberately: the manifest shape is frozen at your first publish, and changing it afterwards needs a brand-new plugin slug. Converting is free until then — but only until then. The two manifest shapes explains the decision and its cost.

How this book is organised

At a glance

# derived from packages/create-hr-plugin/bin/create-hr-plugin.js and both templates' package.json
# non-interactive, argv only: [--template <single|suite>] [--author <name>] [--no-install]
npx create-hr-plugin my-plugin                   # one widget (the default)
npx create-hr-plugin my-suite --template suite   # several widgets + a layout
cd my-plugin

npm run dev        # Vite dev sandbox on http://localhost:3001, MSW-mocked by default
npm run build      # = npm run build:manifest && hr-widget-build
npm run dev:ssr    # SSR preview on http://localhost:3003 — run a build first.
                   #   A suite has no default widget, so name one:
                   #   npm run dev:ssr -- --widget intro-card
npm run preview    # = npm run build && node serve.js  →  http://localhost:3002

npm run build is two steps, not the three older versions of this guide described: your project’s scripts/inject-schema.mjs writes the config and UI schema into the manifest (or into per-widget sub-manifests), then the SDK’s hr-widget-build bin drives every Vite pass, hashes dist/, writes dist/manifest.json and stamps runtime.widgetCore. It rewrites tracked files, so expect manifest.json to be dirty in git afterwards — commit it.

npm run preview (create-hr-plugin 0.8.0+) serves dist/, /manifest.json, the /w/ hashed redirect and the /p/ asset-proxy path, and the page boots the built bundles against the real runtime IIFE. It runs with no mocks, so point its host ids at a real widget and feed first — Your first widget has the details.

SDK versions

You import from one package, @homerunner-next/widget-core. The build stamps the version it used into runtime.widgetCore, and that stamp is what the publish gate reads — never write it by hand.

widget-coreWhat it added
0.10.0Evergreen runtime (/runtime externalized from your bundle). The publish floor.
0.11.0Suites, registerPluginWidget, the hr-widget-build bin, layout widgets, presets.
0.12.0assets.fonts, bundled assets, layout pages, marketplace icon and cover.
0.12.1Slot prefill.
0.12.2createSSRDevServer previews one named widget of a suite (--widget {slug}).
0.12.3The SSR preview links a stylesheet for a widget that exports no getStaticAssets.

This book documents widget-core 0.12.3 and create-hr-plugin 0.8.1, whose templates pin ^0.12.1 (--template single) and ^0.12.3 (--template suite).

Both are on npm as of 2026-09-08 — npx create-hr-plugin <slug> --template suite works straight from the registry. Install and versions owns the version matrix and what each release added.