Building a Vue 3–Powered Frappe App: Zero-Config Install, Full Control

Integrating a Vue frontend into a Frappe app can be powerful — but it’s easy to get tangled in folders, build tools, and asset serving. In our changelog_claudion app, we set out to make it complete

 · 3 min read

Vue 3 with TypeScript Jump-Start




Integrating a Vue frontend into a Frappe app can be powerful — but it’s easy to get tangled in folders, build tools, and asset serving. In our changelog_claudion app, we set out to:

  1. ✅ Mount a Vue 3 interface inside Frappe Desk
  2. ✅ Use native asset serving via Frappe’s public/js/ structure
  3. ✅ Avoid forcing contributors to use Node/Vite
  4. ✅ Make the app installable via bench get-app with no extra setup
  5. ✅ Still keep the code modular, maintainable, and Vue-authentic

Here’s how we did it.


Goals

We wanted to push raw .vue and .js files to GitHub — just like POS Awesome does — and let Frappe serve them directly. But we also wanted to use Vue 3 syntax, components, and modern tooling like Vite… without splitting folders or requiring external build environments.

The final solution: Vue 3 + Vite compiled inside the Frappe app, all in one folder. No src/, no dist/, just clean output into public/js/changelog_claudion/.


Final Folder Structure


changelog_claudion/
└── public/
   └── js/
       └── changelog_claudion/
           ├── changelog_app.js          # Vue 3 entry point (compiled)
           ├── Home.vue                  # Root component (raw)
           ├── format.js                 # Utility JS
           ├── bus.js                    # Event bus (optional)
           ├── package.json              # Vite project setup
           ├── vite.config.js            # Local build config
           └── components/
               └── ItemCard.vue          # Reusable Vue component



Build Setup: Vue 3 + Vite Inside the App

Instead of keeping the Vue build system in a separate src folder, we placed everything inside the Frappe app’s public directory:


cd public/js/changelog_claudion/
npm init -y
npm install vue@3 vite @vitejs/plugin-vue



vite.config.js:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'

export default defineConfig({
 plugins: [vue()],
 build: {
   lib: {
     entry: path.resolve(__dirname, 'changelog_app.js'),
     name: 'ChangelogApp',
     fileName: 'changelog_app'
   },
   outDir: '.', // Overwrite in-place
   rollupOptions: {
     external: ['vue'] // Provided via CDN
   }
 }
})


package.json:


{
 "name": "changelog-ui",
 "version": "1.0.0",
 "scripts": {
   "build": "vite build"
 },
 "dependencies": {
   "vue": "^3.4.21"
 },
 "devDependencies": {
   "@vitejs/plugin-vue": "^4.5.1",
   "vite": "^4.5.0"
 }
}


To compile:

npm run build



Frappe Integration


add to hooks.py


app_include_js = [
 "public/js/changelog_claudion/changelog_app.js",
 "https://unpkg.com/vue@3.4.21/dist/vue.global.prod.js"
]


Desk Page Setup:

  1. Name: changelog
  2. Module: changelog_claudion
  3. Triggered by: frappe.pages['changelog'].on_page_load


📄 changelog_app.js:

import { createApp } from 'vue'
import Home from './Home.vue'

frappe.pages['changelog'].on_page_load = function(wrapper) {
 const el = document.createElement('div')
 el.id = 'changelog-app'
 wrapper.appendChild(el)

 createApp(Home).mount('#changelog-app')
}


Asset Serving & Debugging

Frappe rewrites assets from:


public/js/changelog_claudion/changelog_app.js


to

/assets/changelog_claudion/js/changelog_claudion/changelog_app.js

So make sure:

  1. You reference public/js/... in hooks.py, not /public/
  2. You run bench build to register assets
  3. You verify the served path manually:


https://your-site.com/assets/changelog_claudion/js/changelog_claudion/changelog_app.js


Outcome

Now the app installs cleanly via:

bench get-app https://github.com/your-org/changelog_claudion.git
bench install-app changelog_claudion


…and the Vue UI is immediately available under:

/app/changelog


No build steps required. Contributors can edit .vue files directly inside the public folder and run npm run build to regenerate changelog_app.js.



💡 Why This Works

FeatureBenefit
Raw .vue in repoEasy for contributors to edit, no tooling required
Vue 3 + ViteModern syntax, modular, fast
In-place buildKeeps everything in one folder
Frappe-native assetsServed via /assets/... without config
GitHub readyFully pushable, installable via bench get-app



Final Thoughts

This setup combines the best of POS Awesome’s simplicity with Vue 3’s modern tooling — all inside a Frappe-compatible layout. It's lean, redistributable, and perfect for open-source collaboration. If you're building apps for the Frappe community, this pattern might be your new baseline.





No comments yet.

Add a comment
Ctrl+Enter to add comment