A collection of Vite plugins for Frappe applications that handle common development tasks like dev server proxying, icon auto-imports, TypeScript type generation, boot data injection, and production builds.
npm install frappe-uiAdd the plugin to your vite.config.js:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import frappeui from 'frappe-ui/vite'
export default defineConfig({
plugins: [
frappeui({
frontendRoute: '/g',
frappeTypes: {
input: {
app_name: ['doctype_1', 'doctype_2'],
},
},
}),
vue(),
],
})All plugins except frappeTypes are enabled by default. frontendRoute
and frappeTypes require explicit configuration — frontendRoute sets the app route,
and frappeTypes needs an input map of app names to doctype names. Pass
custom options to override any plugin, or false to disable it.
The route where your app is served (e.g. '/g'). This top-level option is
shared across plugins and controls:
- Dev server site banner — prints clickable URLs for all sites where the app is installed on startup.
- Build output path —
indexHtmlPathis auto-inferred as../<appName>/www/<path>.html.
frappeui({
frontendRoute: '/g',
})Configures the Vite dev server to proxy backend requests to your Frappe instance.
- Proxies routes like
/api,/app,/assets,/files, etc. - Auto-detects the Frappe port from
common_site_config.json
| Option | Description | Default |
|---|---|---|
port |
Vite dev server port | Auto-calculated from webserver_port |
source |
Regex for routes to proxy | '^/(app|login|api|assets|files|private)' |
frappeui({
frappeProxy: {
port: 8080,
source: '^/(app|login|api|assets|files|private)',
},
})Integrates Lucide icons with auto-import support and a standardized stroke-width of 1.5.
Auto-import — use directly in templates, no import needed:
<template>
<LucideArrowRight class="size-4" />
</template>Explicit import — for use in <script setup>:
import LucideArrowRight from '~icons/lucide/arrow-right'Auto-generates TypeScript interfaces from Frappe DocType JSON files. Interfaces are regenerated only when the source DocType changes.
| Option | Description | Default |
|---|---|---|
input |
Map of app_name → array of doctype names |
(required) |
output |
Output file path for generated types | src/types/doctypes.ts |
frappeui({
frappeTypes: {
input: {
your_app_name: ['doctype1', 'doctype2'],
},
output: 'src/types/doctypes.ts',
},
})Injects a Jinja block that reads keys from the boot context object and sets
them on window. Useful for global values like csrf_token and site_name.
frappeui({
jinjaBootData: true,
})Server side — populate context.boot in your Python handler:
def get_context(context):
context.boot = {
"csrf_token": "...",
"user": frappe.session.user,
"user_info": frappe.session.user_info,
}
return contextClient side — access values directly from window:
console.log(window.user)
console.log(window.user_info)Handles production builds with proper asset paths and HTML output for Frappe's directory structure.
- Configures output directories for build assets
- Sets correct base URLs for Frappe's asset serving
- Copies the built
index.htmlto the specified location (typically inwww/)
| Option | Description | Default |
|---|---|---|
outDir |
Build output directory | '../app_name/public/frontend' (auto) |
baseUrl |
Base URL for assets | '/assets/app_name/frontend/' (auto) |
indexHtmlPath |
Where to copy built index.html |
Inferred from frontendRoute |
emptyOutDir |
Clear output directory before build | true |
sourcemap |
Generate source maps | true |
frappeui({
buildConfig: {
outDir: '../app_name/public/frontend',
baseUrl: '/assets/app_name/frontend/',
indexHtmlPath: '../app_name/www/app_name.html',
emptyOutDir: true,
sourcemap: true,
},
})