# Framework integration


The library uses React 18/19. Download and verify the package using [the website installation guide](start.md), then install that tarball in the consuming application. This package contains JavaScript, TypeScript declarations and precompiled styles; it does not require the documentation app's server dependencies or path aliases. Import `ic-blocks/styles.css` once in the app. The stylesheet includes Tailwind's base reset and theme tokens. Its utility classes are generated from the public import graph and starter recipes, excluding documentation previews. If you add arbitrary Tailwind classes in your site, configure your own Tailwind build or supply equivalent CSS.

The tarball also contains editable source under `source/` and inventoried sample SVGs under `assets/`. Follow `source/README.md` when copying source into an application: unlike the compiled exports, these reference files preserve `@/` aliases. Copy desired `assets/previews` files to your public directory. Third-party/client media is excluded.

Without a provider, components render ordinary anchors and images. Interactive components need the host's React hydration. The `use client` directive is retained for Next.js; Astro still requires an explicit client directive. The packaged JavaScript has no CSS side-effect imports, so plain Node SSR can load it. `styles.css` includes the composition styles; those are also available separately as `ic-blocks/composition.css`.

## Next.js

Wrap the application in `NextFrameworkProvider` from `ic-blocks/adapters/next`. This enables Next Link and Next Image while preserving ordinary component props. Import styles from the root layout or `_app`. Configure permitted image hosts in Next's image configuration. Next remains an optional peer used only by this adapter.

## Astro

Install the official `@astrojs/react` integration. Use components without a client directive for static output. For interactive sections, compose their callbacks, icons and React children in a `.tsx` wrapper, then render that wrapper with `client:load` (navigation/forms) or `client:visible` (deferred content). Functions cannot cross Astro's hydrated-prop serialization boundary. No provider is required for ordinary navigation/images.

## Gatsby

Pass Gatsby's `Link` to `createRouterAdapter` from `ic-blocks/runtime`, then use the resulting adapter with `FrameworkProvider` in both `gatsby-browser` and `gatsby-ssr` via `wrapRootElement`. External URLs, hash links, downloads and non-self targets remain anchors. Images work as ordinary images; Gatsby's GraphQL image data requires an application-owned image adapter rather than treating URL strings as `GatsbyImage` data.

## React Router / Remix and Vite React

React Router's `Link` uses the same `createRouterAdapter` API. Place the provider inside the router, identically for server rendering and hydration. Vite React can use native links without a provider. Remix/React Router route loaders, actions and form submission remain application responsibilities.

## Vue / Nuxt, Svelte / SvelteKit, Angular and plain browser hosts

Use `mountComponent` from `ic-blocks/client` inside a host component's browser mount lifecycle, call `update` when props change, and `unmount` during teardown. The result is a React island; it is not a native Vue/Svelte/Angular component. Do not mount during SSR. The optional `hydrate` setting is only for markup produced by the same React tree on the server. React context and state belong inside the island.

## Custom integrations

`FrameworkProvider` accepts a scoped partial adapter with `Link` and/or `Image` components. Link adapters receive `href` and must forward anchor props/ref. Image adapters receive source, alt, dimensions, fill, priority and load callbacks and must forward the image ref. Nested providers inherit unspecified adapters. Keep adapters consistent between server and browser, and declare adapter functions in client React modules for Next/Astro boundaries.

Validation status and runnable host fixtures are recorded separately; source compatibility is not a claim that every component has been visually checked in every framework/version.


## React adapter example

```tsx
import { Link as RouterLink } from 'react-router'
import { FrameworkProvider, createRouterAdapter } from 'ic-blocks/runtime'
import 'ic-blocks/styles.css'

const adapter = createRouterAdapter(RouterLink)
// Render inside the host router, on both server and browser when using SSR.
export function LibraryBoundary({ children }: { children: React.ReactNode }) {
  return <FrameworkProvider adapter={adapter}>{children}</FrameworkProvider>
}
```

For Gatsby, import `Link` from `gatsby` instead and use the boundary in both root wrappers. Runnable fixture sources are in `examples/frameworks/`; the preparation script supplies their shared demo. Host routing, forms and image pipelines stay owned by the application.

## Browser-island lifecycle example

```ts
import { mountComponent } from 'ic-blocks/client'
import { Button } from 'ic-blocks/ui/button'

// Call after the host has mounted this element in the browser.
const island = mountComponent(element, Button, {
  children: 'Continue',
  onClick: () => advance(),
})
island.update({ children: 'Next step', onClick: () => advance() })
// Call from Vue onBeforeUnmount, Svelte cleanup, or Angular ngOnDestroy.
island.unmount()
```

The bridge does not translate framework templates or share framework-specific context. Place related React controls within one island. Native host SSR requires a separate React server-rendering integration; the default bridge is client-mounted.


## Verified hosts — September 11, 2026

| Host | Verification |
| --- | --- |
| Astro 7.3.2 / React 18.3.1 | Static production build, hydration and four desktop/mobile × light/dark browser cases |
| Gatsby 5.16.1 / React 18.3.1 | Production build, hydration, Gatsby client navigation and four browser cases |
| Vite 8.3.0 / React Router 7.9.1 / React 19.1.0 | Production build, router SSR check, client navigation and four browser cases |
| Next.js 16.3.4 / React 19.1.0 | App Router production/type-check build, Next image adapter, client navigation and four browser cases |
| Browser island bridge | Mount, update, callback and teardown verified in the Vite fixture |

Every host's browser pass checks stateful controls, accordion expansion, images, active animation keyframes, mobile menus, desktop dropdowns and horizontal overflow. Screenshots were visually inspected. The Astro fixture initially exposed two real packaging/hydration issues that were corrected and rechecked. These are representative integration tests, not a visual certification of every component under every framework version.

Vue/Nuxt, Svelte/SvelteKit and Angular lifecycle wrappers are provided in `examples/frameworks/bridges/`. Their underlying bridge is browser-tested; those native host applications have not each been built in this matrix. Nuxt can use the Vue wrapper as a `.client.vue` component. SvelteKit uses its browser-only mount lifecycle; Angular's wrapper explicitly skips mounting on the server. Remix uses the React Router adapter contract; a separate Remix application build is not part of this matrix.

Sources: [Astro React integration](https://docs.astro.build/en/guides/integrations-guide/react/), [Astro hydration and prop boundaries](https://docs.astro.build/en/guides/framework-components/), [Gatsby Link](https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-link/), [React Router Link](https://reactrouter.com/api/components/Link). Saved results are in `docs/verification/framework-hosts/`.

Built-in placeholder images, sample artwork and default logos use embedded SVG data URLs. They do not require the documentation application’s `public` directory. Supply your own image URLs or static imports for production content.

For editable starter sites, the packaged `ic-blocks` CLI provides `create`, `recipes`, `search`, and `describe`. See [agent scaffolding](start.md).

Router adapters receive `to` and ordinary anchor props. Next-only `prefetch` and `scroll` options are stripped, so a router may define its own prefetch type without a TypeScript conflict.
