Contributing
How to contribute to the Qwik Astro integration.
Quick start
Clone the repository and install dependencies:
git clone https://github.com/QwikDev/astro.git
cd astro
pnpm install
Note that we only use pnpm. Please don’t make any PR’s that introduce lock files of other package managers.
dev:
pnpm dev
build:
pnpm build
preview:
pnpm preview
Project structure
This project is a pnpm workspace monorepo:
.
├── apps/
│ ├── demo/ # Standard Astro demo app
│ ├── deno-demo/ # Deno runtime demo
│ ├── node-demo/ # Node.js runtime demo
│ └── website/ # Documentation site
└── libs/
└── qwikdev-astro/
├── src/
│ ├── index.ts # Integration entrypoint
│ ├── constants.ts # Configuration constants
│ ├── plugins.ts # Vite plugin helpers
│ ├── scan.ts # Entrypoint scanning
│ └── types.ts # TypeScript types
├── server.ts # SSR renderer
└── package.json
There are two major files to be aware of: index.ts and server.ts.
index.ts
The integration entrypoint, built with astro-integration-kit’s defineIntegration. It registers Qwik as an Astro renderer and configures the Vite plugins.
Astro hooks
-
astro:config:setup— Registers the Qwik renderer viaaddRenderer(), defines thevirtual:qwikdev-astrovirtual module for runtime render options, resolves source/build paths, and configuresqwikVite()with file filters, entry points, and output directories. In build mode, it stripsoutputOptionsfrom qwikVite so Astro controls output directories. -
astro:build:setup— Overrides Astro’sbuildAppto run the Qwik client build before prerender. Scans for Qwik entrypoints usingscanQwikEntrypoints(), runsrunQwikClientBuild()to produce the manifest, then calls the original Astro build.
Why a separate build step?
Unlike other integrations, Qwik needs the client build manifest available during SSR. The astro:build:setup hook intercepts Astro’s build pipeline to run runQwikClientBuild() first, which produces symbol-to-chunk mappings that the server renderer needs.
Entrypoint discovery
scanQwikEntrypoints() in scan.ts uses grep to find files containing Qwik imports (matching @qwik.dev/core, @qwik.dev/react, or .qwik. patterns). It respects the include/exclude filter options.
plugins.ts
createQwikManifestPlugin
Virtual module plugin for @qwik-client-manifest that provides the manifest JSON from the standalone client build. Pre-enforced to override qwikVite’s built-in manifest.
runQwikClientBuild
Standalone Vite build just for Qwik client code. Runs before Astro’s prerender in astro:build:setup. Takes scanned entrypoints, generates client bundles with symbols split, and captures the manifest via callback.
createAstroQwikPostPlugin
Post-enforced plugin that undoes qwikVite’s output directory overrides so Astro retains control of the final output structure.
server.ts
The SSR renderer implementing Astro’s renderer interface.
check
Determines if a component is renderable by Qwik using isQwikComponent().
renderToStaticMarkup
Main rendering function called by Astro. Handles two component types:
- Inline components — Plain functions using Qwik JSX (detected by
_jsxSorted,_jsxSplit,_jsxQ,_jsxC,_jsxSidentifiers). Called directly with props. - Regular components —
component$wrapped components with serializable state. Converts Astro slots to Qwik format, creates element tree viajsx(), and callsrenderToStream()with the manifest.
Uses containerAttributes: { style: "display: contents" } and containerTagName: "div".
Client Router support
Injects a script that handles Astro view transitions — resets Qwik state on before-swap and re-dispatches lifecycle events (qinit, qidle, qvisible) on after-swap.
Code style
This project uses Biome to lint and format all code.
- Run
pnpm run checkto verify code style - Run
pnpm run fixto auto-fix safe issues
When committing, an automatic git hook (via lefthook) checks staged files for linting and formatting errors. If there’s an error, the commit will be aborted.
Reporting issues
If you find a bug or have a feature request, please open an issue on GitHub.