astro-slidev
v0.1.0
Published
Use Astro components inside Slidev slides via the Astro Container API.
Readme
astro-slidev
Use Astro components inside Slidev slides, via the experimental Astro Container API.
.astro files are rendered to static HTML at module-load time and surfaced as Vue components, so they can be referenced from a slide just like any other component.
Install
pnpm add -D astro-slidev astroastro is a peer dependency. vue and vite are also peers and are normally already provided by Slidev.
Setup
Register the Vite plugin in vite.config.ts:
import { defineConfig } from "vite";
import astroSlidev from "astro-slidev";
export default defineConfig({
// `slidev` is a Slidev-specific Vite config extension.
// @ts-expect-error Vite's base config type does not know about it.
slidev: {
components: {
extensions: ["vue", "astro"],
},
},
plugins: [astroSlidev()],
});Place a .astro file under ./components/ and reference it from a slide by its filename:
# Slide
<MyComponent />What works
- Frontmatter scripts and expression interpolation (
{value},.map(...)in markup) - TypeScript syntax in the frontmatter (
interface, type annotations,ascasts) — types are stripped via Vite's oxc transform before the module is loaded - Scoped
<style>blocks — emitted CSS chunks are routed through Vite's CSS pipeline and participate in HMR - HMR on
.astrosource changes (including transitive.astrodeps) .astroimporting another.astro(e.g.import Card from "./Card.astro"), with paths resolved through Vite's resolver (so aliases / tsconfig paths work)
Limitations
- No framework integrations. Renderers for React / Vue / Svelte / Solid / Preact islands are not registered on the container, so components that depend on them fail to render. By extension,
client:load/client:idle/client:visibledirectives — which only apply to framework islands — aren't usable either. - No prop pass-through from slides. A
.astrofile is rendered once at module-load time with empty props, so attributes written on the component tag in a slide (e.g.<Greeting name="World" />) don't reachAstro.props. Frontmatter constants and Astro-side defaults work as usual. - Container API is experimental upstream and may break across Astro minor/patch releases.
How it works
@astrojs/compilertransforms the entry.astro(and its transitive.astrodeps, resolved via Vite) to JS modules.- Each module is run through Vite's oxc transform to strip TypeScript syntax (the Astro compiler preserves frontmatter verbatim, so
interface/ type annotations would otherwise reach Node's ESM loader as-is). - Each module is written into a per-render session directory under
node_modules/.astro-slidev/with.astro → .astroimports rewritten to sibling.mjsfiles, then the entry is dynamically imported. Bare-specifier imports (astro/runtime/server/index.jsetc.) resolve through the project's normal node resolution. experimental_AstroContainer.renderToStringproduces an HTML string.- The plugin emits a Vue component that renders that HTML via
innerHTML. - Scoped CSS chunks reported by the compiler — across the entry and its deps — are exposed as virtual
.cssmodules and side-effect-imported from the generated component. - Dep
.astrofiles are registered withaddWatchFile, so editing a child.astroinvalidates the entry and triggers HMR.
