https://github.com/stacksjs/vite-plugin-layouts
🧩 Router-based layouts for your application.
https://github.com/stacksjs/vite-plugin-layouts
hmr layouts plugin router vite vite-plugin vue
Last synced: 6 months ago
JSON representation
🧩 Router-based layouts for your application.
- Host: GitHub
- URL: https://github.com/stacksjs/vite-plugin-layouts
- Owner: stacksjs
- License: mit
- Created: 2025-03-17T17:35:47.000Z (7 months ago)
- Default Branch: main
- Last Pushed: 2025-03-31T14:06:25.000Z (6 months ago)
- Last Synced: 2025-04-01T01:21:56.922Z (6 months ago)
- Topics: hmr, layouts, plugin, router, vite, vite-plugin, vue
- Language: TypeScript
- Homepage: https://vite-plugin-layouts.netlify.app
- Size: 669 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: .github/CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE.md
- Code of conduct: .github/CODE_OF_CONDUCT.md
- Security: .github/SECURITY.md
Awesome Lists containing this project
README
[![npm version][npm-version-src]][npm-version-href]
[![GitHub Actions][github-actions-src]][github-actions-href]
[](http://commitizen.github.io/cz-cli/)# vite-plugin-layouts
> Router based layouts for Vue 3 applications using Vite.
## Features
- 📁 **File Based** _Layouts are stored in `/src/layouts` as standard Vue components_
- 🔄 **Sensible Defaults** _Pages without a layout use `default.vue` automatically_
- 🌐 **Multiple Layouts** _Support for multiple layout directories_
- 🎨 **Meta Configuration** _Specify layouts via route blocks in your pages_
- 🔌 **Router Integration** _Pairs with `unplugin-vue-router`_
- 📱 **HMR Optimized** _Client-side layout mode for faster HMR_
- 🛠️ **Flexible Configuration** _Customize layout directories, exclusions, and more_## Install
```bash
npm install -D vite-plugin-layouts
# or
yarn add -D vite-plugin-layouts
# or
pnpm add -D vite-plugin-layouts
# or
bun add -D vite-plugin-layouts
```## Get Started
```ts
// vite.config.ts
import Vue from '@vitejs/plugin-vue'
import { defineConfig } from 'vite'
import Layouts from 'vite-plugin-layouts'
import Pages from 'vite-plugin-pages'export default defineConfig({
plugins: [
Vue(),
Pages(),
Layouts()
]
})
```Then in your main.ts file:
```ts
// main.ts
import { setupLayouts } from 'virtual:generated-layouts'
import { createRouter } from 'vue-router'
import generatedRoutes from '~pages'const routes = setupLayouts(generatedRoutes)
const router = createRouter({
// ...
routes,
})
```If you're using `unplugin-vue-router`:
```ts
// main.ts
import { setupLayouts } from 'virtual:generated-layouts'
import { createRouter } from 'vue-router/auto'const router = createRouter({
// ...
extendRoutes: routes => setupLayouts(routes),
})
```### TypeScript Support
If you want type definition for the virtual modules, add the following to your `tsconfig.json`:
```json
{
"compilerOptions": {
"types": ["vite-plugin-layouts/client"]
}
}
```## Usage
Layouts are stored in the `/src/layouts` folder by default and are standard Vue components with a `` in the template.
You can specify which layout to use for a page by using a route block:
```vue
meta:
layout: users```
This will look for `/src/layouts/users.vue` for the page's layout. If no layout is specified, it will use `default.vue`.
## Configuration
```ts
// vite.config.ts
import Vue from '@vitejs/plugin-vue'
import { defineConfig } from 'vite'
import Layouts from 'vite-plugin-layouts'
import Pages from 'vite-plugin-pages'export default defineConfig({
plugins: [
Vue(),
Pages(),
Layouts({
layoutsDirs: 'src/layouts', // default: 'src/layouts'
pagesDirs: 'src/pages', // default: 'src/pages'
defaultLayout: 'default', // default: 'default'
exclude: [], // Patterns to exclude from layout loading
})
]
})
```### Available Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `layoutsDirs` | `string \| string[]` | `'src/layouts'` | Path(s) to the layouts directory. Supports globs. |
| `pagesDirs` | `string \| string[] \| null` | `'src/pages'` | Path(s) to the pages directory. Set to null to watch all files. |
| `defaultLayout` | `string` | `'default'` | Name of the default layout to use when none is specified. |
| `exclude` | `string[]` | `[]` | Patterns to exclude from layout loading. Files named `__*__.vue` are automatically excluded. |### Advanced Configuration: ClientSideLayout
For faster HMR and more efficient loading, you can use the ClientSideLayout mode:
```ts
// vite.config.ts
import Vue from '@vitejs/plugin-vue'
import { defineConfig } from 'vite'
import { ClientSideLayout } from 'vite-plugin-layouts'
import Pages from 'vite-plugin-pages'export default defineConfig({
plugins: [
Vue(),
Pages(),
ClientSideLayout({
layoutsDir: 'src/layouts', // default: 'src/layouts'
defaultLayout: 'default', // default: 'default'
importMode: 'sync' // Auto-detect: 'sync' for SSG, 'async' for others
})
]
})
```## How It Works
The `setupLayouts` function transforms your routes by:
1. Replacing pages with their specified layouts
2. Making the original pages children of their layoutsThis creates nested routes with the same paths, giving you full access to the vue-router API.
## Common Patterns
### Transitions Between Routes
To add transitions between routes, including when using the same layout:
```html
```
### Passing Data from Layout to Page
Use props to pass data down from layout to page:
```html
```
### Setting Static Data for a Layout
Use the route's meta property in your page:
```vue
Contentmeta:
layout: default
bgColor: yellow```
Then in your layout:
```vue
import { useRouter } from 'vue-router'
```
### Dynamic Data from Page to Layout
Use custom events to pass data from page to layout:
```vue
import { defineEmits } from 'vue'
const emit = defineEmits(['setColor'])if (2 + 2 === 4)
emit('setColor', 'green')
else
emit('setColor', 'red')```
Listen for the events in your layout:
```vue
import { ref } from 'vue'
const bgColor = ref('yellow')
function setBg(color) {
bgColor.value = color
}
```
## Testing
```bash
bun test
```## Changelog
Please see our [releases](https://github.com/stacksjs/vite-plugin-layouts/releases) page for more information on what has changed recently.
## Contributing
Please review the [Contributing Guide](https://github.com/stacksjs/contributing) for details.
## Community
For help, discussion about best practices, or any other conversation that would benefit from being searchable:
[Discussions on GitHub](https://github.com/stacksjs/stacks/discussions)
For casual chit-chat with others using this package:
[Join the Stacks Discord Server](https://discord.gg/stacksjs)
## Postcardware
"Software that is free, but hopes for a postcard." We love receiving postcards from around the world showing where `vite-plugin-layouts` is being used! We showcase them on our website too.
Our address: Stacks.js, 12665 Village Ln #2306, Playa Vista, CA 90094, United States 🌎
## Sponsors
We would like to extend our thanks to the following sponsors for funding Stacks development. If you are interested in becoming a sponsor, please reach out to us.
- [JetBrains](https://www.jetbrains.com/)
- [The Solana Foundation](https://solana.com/)## Credits
- [JohnCampionJr](https://github.com/JohnCampionJr) - Creator of original vite-plugin-vue-layouts
- [Chris Breuer](https://github.com/chrisbbreuer)
- [All Contributors](https://github.com/stacksjs/vite-plugin-layouts/contributors)## License
The MIT License (MIT). Please see [LICENSE](https://github.com/stacksjs/stacks/tree/main/LICENSE.md) for more information.
Made with 💙
[npm-version-src]: https://img.shields.io/npm/v/vite-plugin-layouts?style=flat-square
[npm-version-href]: https://npmjs.com/package/vite-plugin-layouts
[github-actions-src]: https://img.shields.io/github/actions/workflow/status/stacksjs/vite-plugin-layouts/ci.yml?style=flat-square&branch=main
[github-actions-href]: https://github.com/stacksjs/vite-plugin-layouts/actions?query=workflow%3Aci