Navigation
Community

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 via addRenderer(), defines the virtual:qwikdev-astro virtual module for runtime render options, resolves source/build paths, and configures qwikVite() with file filters, entry points, and output directories. In build mode, it strips outputOptions from qwikVite so Astro controls output directories.

  • astro:build:setup — Overrides Astro’s buildApp to run the Qwik client build before prerender. Scans for Qwik entrypoints using scanQwikEntrypoints(), runs runQwikClientBuild() 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, _jsxS identifiers). Called directly with props.
  • Regular componentscomponent$ wrapped components with serializable state. Converts Astro slots to Qwik format, creates element tree via jsx(), and calls renderToStream() 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 check to verify code style
  • Run pnpm run fix to 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.