Astrobook
The minimal UI component playground

Astrobook is a UI component playground that supports multiple frameworks including React, Vue, Preact, Svelte, Solid, Lit, and Astro. It offers a unified environment to develop, test, and showcase components.
Try it Online
-
An example of using multiple UI rendering frameworks (React, Preact, Vue, Svelte, Solid, Lit, Astro) with Astrobook.
Online demo: astrobook.pages.dev

-
An example of using custom <head>
tags with Astrobook.

-
An example that shows how to add Astrobook into an existing Astro project.

-
An example of using TailwindCSS with Astrobook.

-
An example of using UnoCSS with Astrobook.

-
An example of using PandaCSS with Astrobook.

Quick start
[!NOTE]
Astrobook supports various frameworks. We use React as an example here. Check the Astro docs for other integrations.
-
Install the packages
npm install astro @astrojs/react astrobook
-
Create astro.config.mjs
and add the astrobook
integration
import { defineConfig } from 'astro/config'
import react from '@astrojs/react'
import astrobook from 'astrobook'
export default defineConfig({
integrations: [react(), astrobook()],
})
-
Add scripts to your package.json
"scripts": {
"dev": "astro dev",
"build": "astro build"
}
-
Write stories. Astrobook scans all .stories.{ts,tsx,js,jsx,mts,mjs}
files. It's compatible with a limited subset of Storybook's Component Story Format v3. In particular, args
and decorators
properties are supported.
import { Button, type ButtonProps } from './Button.tsx'
import { Container } from './Container.tsx'
export default {
component: Button,
}
export const PrimaryButton = {
args: { variant: 'primary' } satisfies ButtonProps,
}
export const SecondaryButton = {
args: { variant: 'secondary' } satisfies ButtonProps,
}
-
Run npm run dev
and open http://localhost:4321
to see your stories.
Decorators
Decorators are objects that have a property for the component and the props that will be passed to it on render. This component must have a slot for children to be rendered. Currently, decorators only support styling changes and are not able to change a component's context or any client-side behaviors. Any decorators are rendered into HTML by Astro and sent to the client.
You can use decorators to wrap a component with a custom style.
For example, this is a React decorator that adds a green border to a component and an Astro decorator that adds a red border to a component.
import type { ComponentChildren } from 'react'
export function GreenBorderDecorator({
width = 2,
children,
}: {
width?: number
children?: ComponentChildren
}) {
return <div style={{ border: `solid ${width}px green` }}>{children}</div>
}
<!-- AstroRedBorderDecorator.astro -->
<div style="border: solid 2px red;">
<slot />
</div>
In your stories, you can use the decorators like this:
import { Button, type ButtonProps } from './Button.tsx'
import { GreenBorderDecorator } from './ReactGreenBorderDecorator.tsx'
import RedBorderDecorator from './AstroRedBorderDecorator.astro'
export default {
component: Button,
}
export const PrimaryButton = {
args: { variant: 'primary' } satisfies ButtonProps,
decorators: [
{ component: GreenBorderDecorator, props: { width: 10 } },
{ component: RedBorderDecorator },
],
}
This will render the button, wrapped in a red border, which is then wrapped in a green border.
Options
directory
You can use the directory
option to specify the directory to scan for stories. The default directory is current working directory.
import { defineConfig } from 'astro/config'
import astrobook from 'astrobook'
export default defineConfig({
integrations: [
astrobook({
directory: 'src/components',
}),
],
})
subpath
You can run Astrobook as a standalone app. You can also add it to your existing Astro project. In the latter case, you can use the subpath
option to specify the subpath of Astrobook.
import { defineConfig } from 'astro/config'
import astrobook from 'astrobook'
export default defineConfig({
integrations: [
astrobook({
subpath: '/playground',
}),
],
})
In the example above, Astrobook will be available at http://localhost:4321/playground
.
Notice that the subpath
option is relative to your Astro project's base path. For example, if you configure both Astro's base
and astrobook
's subpath
, like so:
import { defineConfig } from 'astro/config'
import astrobook from 'astrobook'
export default defineConfig({
base: '/docs',
integrations: [
astrobook({
subpath: '/playground',
}),
],
})
Your Astro project will be available at http://localhost:4321/docs
and Astrobook will be available at http://localhost:4321/docs/playground
.
css
You can customize the styles by using the css
option to specify the CSS files to be imported into your Astrobook site.
import { defineConfig } from 'astro/config'
import astrobook from 'astrobook'
export default defineConfig({
integrations: [
astrobook({
css: [
'./src/styles/custom.css',
],
}),
],
})
head
You can further customize your Astrobook project by providing a custom head
options. It's a path to an Astro component that includes custom tags to the <head>
of your Astrobook site. It should only include elements permitted inside <head>
, like <link>
, <style>
, <script>
, etc.
Below is an example of a custom head component that configures the global styles and fonts.
<!-- Load custom fonts -->
<link rel="preconnect" href="https://rsms.me/" />
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
<!-- Apply global styles -->
<style is:global>
html {
font-family: 'Inter', sans-serif;
}
</style>
import { defineConfig } from 'astro/config'
import astrobook from 'astrobook'
export default defineConfig({
integrations: [
astrobook({
head: './src/components/CustomHead.astro',
}),
],
})
title
You can set the title for your website.
import { defineConfig } from 'astro/config'
import astrobook from 'astrobook'
export default defineConfig({
integrations: [
astrobook({
title: 'My Components Playground',
}),
],
})
Advanced
Enable Astrobook only on development
You can enable Astrobook only on development by using the process.env.NODE_ENV
to conditionally include the astrobook
integration. This is useful when you
want to include Astrobook in your existing Astro project but don't want to build
it in production.
import { defineConfig } from 'astro/config'
import astrobook from 'astrobook'
export default defineConfig({
integrations: [
process.env.NODE_ENV === 'development'
? astrobook({ subpath: '/astrobook' })
: null,
],
})
Toggle theme via message
If you're running Astrobook in an iframe, you can toggle the theme via a message.
const theme = 'light'
iframe.contentWindow.postMessage({ type: 'astrobook:set-theme', theme }, '*')
Who's using Astrobook?
Add your project
License
MIT