Skip to content

Setup

Phaze uses the JSX automatic transform — same configuration shape as Preact and React, just a different jsxImportSource. The tabs below show the equivalent setup for each framework. The phaze (God Mode) tab adds the compile-time tooling that unlocks the namespace DSL (on:click, class:hidden, bind:value, use:NAME, <For for:item>) and the auto-thunked macros (c(expr), watch(expr), s.async(expr), inc(count), 3-arg timeout/interval).

Terminal window
pnpm add @madenowhere/phaze
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "@madenowhere/phaze"
}
}
import { render, signal } from '@madenowhere/phaze'
function App() {
const count = signal(0)
return (
<button onClick={() => count.set(count.current() + 1)}>
{count}
</button>
)
}
render(App, document.getElementById('app')!)
  • No hooks. Phaze uses signal() at module or component scope. There is no rules-of-hooks constraint and no useEffect; reactive computations are effect() and run when their dependencies change.
  • render(component, container) takes the component function directly, not a JSX element. Returns a dispose function.
  • {count} in JSX binds the signal directly to a text node. Phaze’s JSX runtime detects function children and wires reactive bindings.
  • No className. Use class — same as Preact.

If you use Vite directly (without an integration), set the JSX import source there too:

vite.config.ts
import { defineConfig } from 'vite'
export default defineConfig({
esbuild: {
jsx: 'automatic',
jsxImportSource: '@madenowhere/phaze',
},
})

If you use Astro with the @madenowhere/phaze-astro integration, both the plain and God Mode setups are configured for you — the integration adds phaze-compile to the Vite plugin chain automatically, so you only wire phaze-vite + phazeChunks() yourself.