Frontend Plugin API
Where possible we reuse the API from the tools and libraries we are already using rather than defining our own.
Manifest
This uses the vite manifest format to define which files are part of the plugin.
It's a vite-specific JSON-structure designed to allow a backend to serve the asset files.
See https://vitejs.dev/guide/backend-integration#backend-integration for more info.
WARNING
Don't confuse this manifest with a PWA manifest.
Usually, if you were following the plugin development guide, this would be automatically be created for you by setting manifest: true
. You can also create them manually, which could be useful for simple cases.
Here is a minimal example of a manually created manifest:
{
"main.js": {
"file": "assets/main.js",
"isEntry": true,
"css": [
"assets/main.css"
]
},
"main.css": {
"file": "assets/main.css"
}
}
A few points:
- put this in
manifest.json
or.vite/manifest.json
relative to your frontend plugin root dir - the first entry marked
isEntry: true
will be used as the entry
These files will be served up by the backend at paths such as:
/api/plugins/assets/<plugin-name>/<path-to-asset>
e.g.:
/api/plugins/assets/my-plugin/assets/app.js
Entry point
Inside the entrypoint file it should export a default object with 3 optional fields:
export default {
boot (context) {},
setup () {},
slots: {},
}
boot
This is a Quasar boot function, it is passed a context object with lots of useful things on it.
It's good for:
- registering new routes
- configuring libraries
- configure theme colours
- configuring anything about the vue app before it loads
See https://quasar.dev/quasar-cli-vite/boot-files/ for more about what you can do here.
setup
This is a vue setup()
function. It's run when the app first boots.
This is where you can:
- register app-wide composition hooks
- any other configuration that needs an instantiated app instance to work
See https://vuejs.org/api/composition-api-setup for more about setup()
functions.
slots
You can pass components to these to replace certain sections of the Karrot interface:
import SomeComponent from './SomeComponent.vue'
export default {
slots: {
about: SomeComponent,
groupActivities: () => import('./MyAsyncComponent.vue'),
groupWall: SomeComponent,
sidenav: SomeComponent,
}
}
You can register components for these slots:
about
- the "about" modal dialog when you click "About Karrot" in the left sidenavgroupActivities
- the main content on the group activities pagegroupWall
- the main content on the group wall pagesidenav
- the whole left sidenav
Inside your component you can use <slot />
to choose where the original component content goes (or leave it out entirely):
<template>
<h1>This will appear above the original component</h1>
<slot />
<p>This will appear below the original component</p>
</template>
Or wrap it:
<!-- This will put the original component in a red box -->
<template>
<div class="example">
<slot />
</div>
</template>
<style scoped>
.example {
border: 1px solid red;
}
</style>