React

Poops speaks React three ways. Which you pick depends on whether you want the HTML rendered in the browser, at build time, or both.

1. Client-side React (the scripts pipeline)

The simplest option: point a scripts entry at your .jsx/.tsx entry and mount with createRoot on the client.

{
  "scripts": [
    {
      "in": "src/js/app.jsx",
      "out": "dist/js/app.js",
      "options": { "minify": true, "format": "iife", "jsx": "automatic" }
    }
  ]
}

"jsx": "automatic" uses React 17+'s JSX runtime, so you don't import React in every file. Omit it (or set "transform") for the classic React.createElement transform.

This is a normal client-rendered SPA โ€” nothing is rendered until the JS runs. See Build a React App for the full setup.

2. Build-time pre-rendering (the reactor key)

reactor renders a React component to HTML at build time with renderToString, and exposes that HTML to your templates. Optionally it also ships a client bundle that hydrates it โ€” so the page is real HTML immediately and becomes interactive after hydration.

{
  "reactor": [
    {
      "component": "src/js/App.jsx",
      "inject": "app_html",
      "in": "src/js/app-hydrate.jsx",
      "out": "dist/js/app-hydrate.js",
      "options": { "minify": true, "target": "es2019" }
    }
  ]
}
  • component โ€” file that default-exports the component to render.
  • inject โ€” template global name holding the rendered HTML.
  • in / out (optional) โ€” client hydration entry and its bundle.
  • options (optional) โ€” esbuild options for the client bundle.

In your template, drop the rendered HTML in and load the hydration bundle:

<div id="root">{{ app_html | safe }}</div>
<script src="js/app-hydrate.min.js"></script>

Server-only (no hydration)? Omit in/out:

{
  "reactor": [
    { "component": "src/js/App.jsx", "inject": "app_html" }
  ]
}

Info

reactor is its own pipeline with its own watcher and build step. Changes to the component re-render and re-bundle; markup recompiles only when the rendered output actually changes. Plain JS/TS edits only trigger the scripts pipeline โ€” the two are independent.

Note

Poops does not depend on react/react-dom. They are resolved from your project's node_modules. Install them yourself: npm i react react-dom.

Which should I use?

Goal Use
Interactive SPA, SEO not critical scripts + createRoot
Static HTML pages that don't need JS reactor (no in/out)
Static HTML that hydrates into an app reactor with in/out

Worked examples: React components, A complete React static site, and Build a React App.