Skip to content

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:

json
{
  "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:

js
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:

js
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 sidenav
  • groupActivities - the main content on the group activities page
  • groupWall - the main content on the group wall page
  • sidenav - the whole left sidenav

Inside your component you can use <slot /> to choose where the original component content goes (or leave it out entirely):

vue
<template>
  <h1>This will appear above the original component</h1>
  <slot />
  <p>This will appear below the original component</p>
</template>

Or wrap it:

vue
<!-- 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>

Styling & Theming ​

There are some options for changing Karrot style globally.

As we use Quasar for our frontend, we inherit its styling/theming system.

See https://quasar.dev/style/color-palette/#dynamic-change-of-brand-colors-dynamic-theme-colors- for more info there.

The setCssVar function from Quasar is available in your plugin, e.g.:

js
import { setCssVar } from "quasar"

export default {
  boot() {
    // Change the colour scheme!
    // You can see more options at https://quasar.dev/style/color-palette#how-it-works
    setCssVar("primary", "#581845")
  }
}

You can also import normal css files from your main plugin file, e.g.

js
import "./main.css"
css
/* Any css you like */
* {
    color: red !important;
}

/* Can also set quasar theme colours using css vars */
:root {
    --q-primary: blue;
}

There are other variables (defined in sass) that cannot be modified from a plugin. We might be able to fully transition to css vars one day though.