vite-plugin-ember
v0.3.1
Published
Vite plugin for rendering live Ember components in VitePress documentation
Maintainers
Readme
vite-plugin-ember
A Vite plugin that lets you render live, interactive Ember components inside VitePress documentation pages.
Write .gjs / .gts code fences in markdown and see them rendered on the page — no full Ember app required.
Features
- Inline code fences — use
```gjs livein markdown for instant interactive previews - Preview mode — add
previewto show a collapsible source code panel alongside the rendered component - Full Ember support — class components,
@trackedstate,{{on}}modifier, and TypeScript via.gts - Zero-config compilation — content-tag preprocessing, Babel template compilation, decorator transforms, and
@ember/*/@glimmer/*module resolution handled automatically @embroider/macrosshim — runtime stubs soember-sourceESM imports just work- Vue wrapper — ships a
<CodePreview>component for seamless VitePress integration
Quick Start
1. Install
Install the plugin along with Ember packages your components need:
pnpm add vite-plugin-ember ember-source @glimmer/componentNote:
ember-sourceand@glimmer/componentare peer dependencies — you manage their versions in your project.
2. Configure VitePress
// .vitepress/config.ts
import { defineConfig } from 'vitepress';
import vitePluginEmber, { emberFence } from 'vite-plugin-ember';
export default defineConfig({
vite: {
plugins: [vitePluginEmber()],
},
markdown: {
config(md) {
emberFence(md);
},
},
});3. Register the component
// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme';
import { setupEmber } from 'vite-plugin-ember/setup';
import type { Theme } from 'vitepress';
export default {
...DefaultTheme,
enhanceApp({ app }) {
setupEmber(app);
},
} satisfies Theme;4. Write a live demo
In any markdown file:
```gjs live
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { on } from '@ember/modifier';
export default class Counter extends Component {
@tracked count = 0;
increment = () => { this.count += 1; };
<template>
<button {{on "click" this.increment}}>
Clicked {{this.count}} times
</button>
</template>
}
```Start the dev server with pnpm dev and see it live.
Documentation
Full docs (built with this plugin!) are in the docs/ directory. Run locally:
pnpm install
pnpm devProject Structure
├── vite-plugin-ember/ # The Vite plugin (publishable package)
│ └── src/
│ ├── index.ts # Plugin + Ember compilation pipeline
│ └── vitepress/
│ ├── ember-fence.ts # markdown-it plugin for ```gjs live fences
│ ├── code-preview.vue # Vue wrapper component
│ ├── setup.ts # One-call theme setup helper
│ ├── create-owner.ts # Minimal Ember owner factory
│ └── constants.ts # Shared injection keys
├── docs/ # VitePress documentation site
│ ├── demos/ # .gjs/.gts demo components
│ └── guide/ # Documentation pages
├── package.json # Workspace root
└── pnpm-workspace.yamlLimitations
Components are rendered standalone via @ember/renderer. By default there is no Ember application container, which means:
@serviceinjection requires callingsetupEmberwith aservicesoption (see below)- Initializers and instance-initializers are not executed
- Routing (
LinkTo,RouterService) is not available
Components that rely only on @tracked state, @action, modifiers, and helpers work out of the box.
Enabling service injection
To support @service in your demos, pass a services map to setupEmber:
// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme';
import { setupEmber } from 'vite-plugin-ember/setup';
import type { Theme } from 'vitepress';
import GreetingService from '../demos/greeting-service';
export default {
...DefaultTheme,
enhanceApp({ app }) {
setupEmber(app, {
services: {
greeting: new GreetingService(),
},
});
},
} satisfies Theme;All <CodePreview> instances (including those from ```gjs live fences) will then use the @service decorator for dependency injection.
Requirements
- Node.js ≥ 20
- pnpm ≥ 10
