Astro
Set up Vortex in an existing Astro project with React islands.
Install the packages
Vortex components are React components, so add Astro's React integration first:
bunx astro add reactVortex packages are private and available by invitation. Complete the package access prerequisites before installing.
bun add @vortexlabs/vortex @vortexlabs/vortex-themesbun add -d postcss@^8 @csstools/postcss-global-data postcss-custom-media cssnanoGenerate your theme
Create vortex.config.ts at your project root. Replace acme with your theme name; an empty definition inherits Vortex's defaults.
import type { VortexThemeConfig } from "@vortexlabs/vortex-themes";
const config: VortexThemeConfig = {
themes: {
acme: {},
},
};
export default config;Add a script to your existing package.json:
"scripts": {
"build:theme": "vortex-themes theming --output ./src/themes"
}bun run build:themeThis creates src/themes/acme/. Run it again after changing vortex.config.ts or upgrading Vortex packages, before starting or building your site.
Configure PostCSS
Vortex styles use @custom-media breakpoint queries that your build must resolve. Add the package's PostCSS preset:
import { config } from "@vortexlabs/vortex/config/postcss";
export default config;If you already have a PostCSS config, merge the preset's plugins into it. If you customize breakpoints, point PostCSS at your generated definitions; see Custom breakpoints.
Bundle Vortex for server rendering
Add Vortex to vite.resolve.noExternal so Astro processes its CSS Modules when rendering pages. Without it, the build fails. Keep your existing integrations and options.
import react from "@astrojs/react";
import { defineConfig } from "astro/config";
export default defineConfig({
integrations: [react()],
vite: {
resolve: {
noExternal: ["@vortexlabs/vortex"],
},
},
});Restart the dev server after configuration changes.
Set up the base layout
Import the generated theme once in your base layout, and set the theme attributes on <html> so the first paint uses the right theme:
---
import "../themes/acme/globals.css";
---
<html lang="en" data-vortex-theme="acme" data-vortex-color-mode="light">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Vortex app</title>
</head>
<body>
<slot />
</body>
</html>Add a provider to each island
Each React island is a separate React tree, so wrap each one in its own VortexProvider. scoped keeps the island's theme and color mode local; the layout sets the page's initial theme. Components that share provider state must be in the same island.
import { Button, Stack, Text, VortexProvider } from "@vortexlabs/vortex";
const Hero = () => (
<VortexProvider scoped defaultTheme="acme" defaultColorMode="light">
<Stack gap={4}>
<Text as="h1" size={{ xs: "heading-xl-mobile", sm: "heading-xl-desktop" }}>Hello Vortex</Text>
<Button variant="primary">Get started</Button>
</Stack>
</VortexProvider>
);
export default Hero;Render the island with a client:* directive so it hydrates:
---
import Layout from "../layouts/Layout.astro";
import Hero from "../components/Hero";
---
<Layout>
<Hero client:load />
</Layout>bun run devFonts
Vortex doesn't load font files. Follow the Fonts guide to load the default fonts or your own.