GitHub. Website.

Quick start

StackBlitz demo.

Scaffold your app

If you have an existing VitePress app, you can skip this step.

You can create a new VitePress project following the official guide.

cd into your project directory and install dependencies with npm install.


whyframe comes in two packages, the core library and the UI framework, in this case, Vue.

# Install the core library
$ npm install -D @whyframe/core

# Install the Vue integration
$ npm install -D @whyframe/vue


whyframe works on the bundler level, so the packages are simply Vite plugins. You can initialize these plugins in your .vitepress/config.js:

import { defineConfig } from 'vitepress'
import { whyframe } from '@whyframe/core'
import { whyframeVue } from '@whyframe/vue'

export default defineConfig({
  vite: {
    plugins: [
      // Initialize core plugin
        defaultSrc: '/frames/default' // provide our own html

      // Initialize Vue integration plugin
        include: /\.(?:vue|md)$/ // also scan in markdown files

As whyframe’s default HTML doesn’t work in VitePress, a custom HTML source is required. See HTML source for more information.

To setup /frames/default, or in other words http://localhost:5173/frames/default, create an empty /frames/ file. Since we want to start from an empty layout, some VitePress configuration is required.

To not inherit VitePress’ special layouts, we need to extend VitePress’ default theme. Create .vitepress/theme/index.js with this:

import Theme from 'vitepress/theme'
import DynamicLayout from '../components/DynamicLayout.vue'

export default {
  // use our custom layout component that we'll create next
  Layout: DynamicLayout

Create .vitepress/components/DynamicLayout.vue with this:

<script setup>
import { useRoute } from 'vitepress'
import Theme from 'vitepress/theme'
// the default layout we'll create next
import FrameDefaultLayout from './FrameDefaultLayout.vue'

const route = useRoute()

    replace with the layout entirely for `/frames/default`
    so we don't inherit from `Theme.Layout`
  <FrameDefaultLayout v-if="route.path.startsWith('/frames/default')" />
  <Theme.Layout v-else />

Create .vitepress/components/FrameDefaultLayout.vue with this:

<script setup>
import { ref, onMounted } from 'vue'
// Special api to mount the app
import { createApp } from 'whyframe:app'

const el = ref()

onMounted(() => {
  // Mount the app to the ref

  <div ref="el"></div>

And done! You can also add more code and styles to FrameDefaultLayout.vue if you prefer.


In (or any page), you can create an iframe like below:

<iframe data-why>
  Hello world!

Start your app with npm run dev and watch Hello world! rendered within the iframe as-is!

Check out Features for more things you can do with whyframe.