Skip to content

Qwik

Terminal window
npm install @kadal/deck-qwik @qwik.dev/core
vite.config.ts
import { deckQwikDefine, deckQwikFiles } from "@kadal/deck-qwik/build";
export default defineConfig({
plugins: [deck({ entry: "deck.mdx" }), react({ exclude: [...deckQwikFiles] })],
define: { ...deckQwikDefine },
});
counter.qwik.tsx
/** @jsxImportSource @qwik.dev/core */
import { component$, useSignal, useTask$ } from "@qwik.dev/core";
import { deckQwik } from "@kadal/deck-qwik";
export const Counter = deckQwik(
component$((props: { step: { value: number } }) => {
/* … */
}),
);
src/main.tsx
registerLazyRenderer("qwik", () => import("@kadal/deck-qwik").then((m) => m.qwikRenderer));
  1. component$() is not optional. An inline component — a plain function returning JSX — renders exactly once and is then inert: its signals change and the DOM never moves, with no error. Wrapped in component$() it works, optimizer or not.
  2. deckQwikDefine. The runtime references __EXPERIMENTAL__ in many unguarded places that Qwik’s optimizer would substitute; without the define, the first render throws before anything reaches the slide.
  3. useTask$, never useVisibleTask$. The visible variant waits for an event fired by Qwik’s loader, which is not present — and an island is only alive while its slide is up, so it is already visible.

Resumability does not apply here. Qwik resumes server-rendered HTML without hydration; an island has no server-rendered HTML — it exists only once its slide is shown. What remains is a good fine-grained reactive framework, and that is what the renderer drives. Props arrive as signals, so a component reads props.step.value.