Introduction
This guide takes you from an empty project to your own indicator showing up on the Velitask canvas. It is deliberately practical: what to get, what to install, what to connect, what to build, and where to click. The exact contract of the SDK classes is not covered here — for that there is JavaDoc and the reference-plugin documentation (see Next steps).
Velitask is deliberately open — to give developers maximum freedom. All project data is stored in a local SQLite database, and the plugin works with it directly: it reads source and sensor data, and it can create its own tables to store its own analytics.
🔓 The source code of all official plugins is open
The code of plugin-official — every plugin shipped with Velitask — is fully open. You can:
- study it and use it as a basis for your own indicators;
- copy and modify it however you like, for your own needs;
- extend and evolve the existing indicators;
- send improvements via pull request — they are welcome.
Don't start from scratch: fork a working plugin and reshape it for yourself.
Your fork replaces the official plugin. A plugin is identified by its ID (UID). If your build keeps the same UID as a built-in plugin, Velitask loads only one of them — the one built more recently. You don't need to bump the version: just rebuild your fork, and the system picks up your fresh JAR by file date instead of the built-in one.
Plugin and indicator
A plugin is a JAR file that adds one or more indicators to Velitask Desktop. Velitask finds plugins in configured folders, loads them at startup, and can reload them on the fly during development.
An indicator is a visual component drawn on top of the frame in a project (in the composition Velitask calls a Mixel). The indicator reads source data — speed, distance, elevation, coordinates, time — and renders it the way you programmed it: a speedometer, text, a chart, a map. The user adds the indicator to the canvas, adjusts its properties, and sees the result right in the preview.
A single plugin can contain several indicators. The minimal working plugin is one plugin class (the entry point) plus one indicator class.
Where things live
| What | Where | Why you need it |
|---|---|---|
| Velitask SDK | github.com/velitask/velitask-sdk, binaries on JitPack | The set of contracts (interfaces) your plugin compiles against. Added as a dependency, not bundled inside the plugin. |
| plugin-example | github.com/velitask/plugin-example | A minimal working plugin. The recommended starting point — fork it and reshape it for yourself. |
| plugin-official | github.com/velitask/plugin-official | The production plugin shipped with Velitask (speedometer, distance, slope chart, map, etc.). The canonical reference for non-trivial indicators. |
| JavaDoc | https://javadoc.jitpack.io/com/github/velitask/velitask-sdk/<version>/javadoc/ | The exact contract of every SDK class and method. In the IDE — hover or Ctrl+Q on any SDK class. |
| Velitask Desktop | velitask.com | The application your indicator will run in. Must be installed. |
What we'll build
In this course you will:
- install the tools and grab the reference project — Prerequisites;
- connect the SDK and build a JAR — Build and connect the SDK;
- install the plugin into Velitask and put the indicator on the canvas — Install and run;
- set up hot reload so edits are picked up without a restart — Development loop;
- learn where to find API details when you want more — Next steps.
By the end you'll have your own indicator on the canvas and a working loop where a code change is almost immediately visible in the app.
Next: Prerequisites.
Prerequisites
Before building a plugin, set up your environment and grab the reference project.
Tools
| Tool | Version | Why |
|---|---|---|
| JDK | 21 or newer | Plugins compile against Java 21. Any OpenJDK build works (Temurin, Liberica, Zulu, etc.). |
| Gradle | 8+ | The build system. Install it on your machine — see Installing Gradle below. |
| IDE | — | Optional but convenient. Visual Studio Code or NetBeans with Gradle and Java 21 support will do. |
| Velitask Desktop | current | The application the plugin will run in. Download and install it from velitask.com. |
Check that Java is visible in the console:
java -version
The version must be 21 or higher.
Installing Gradle
The full official guide is at gradle.org/install. In short, by platform:
- Windows — easiest via a package manager:
- Chocolatey:
choco install gradle - Scoop:
scoop install gradle - or manually: download the ZIP from gradle.org/releases, unpack it, and add the
binfolder to yourPATH(see the steps in the official guide).
- Chocolatey:
- macOS / Linux — via SDKMAN:
sdk install gradle, orbrew install gradle(macOS, Homebrew).
Check the installation:
gradle -v
The Gradle version must be 8 or higher, and the JVM line must show Java 21+.
The reference project also contains a Gradle Wrapper (
gradlew/gradlew.bat) that downloads the required Gradle version itself. If you prefer the wrapper, replacegradlewith./gradlew(orgradlew.baton Windows) in all commands below.
The reference project
Don't start from an empty project — grab plugin-example. It's a minimal working plugin with one indicator, a properly configured build, a manifest, and localization. You'll reshape it for yourself afterward.
Fork the repository on GitHub and clone your fork, or clone it directly:
git clone https://github.com/velitask/plugin-example.git
cd plugin-example
Verifying the environment
Build the reference project as-is — this confirms the JDK and Gradle are set up correctly before you change anything:
gradle jar
The build should finish successfully, and a JAR file should appear in build/libs/. If something fails here, the problem is in the environment (most often the wrong Java version) and must be fixed before the next step.
Next: Build and connect the SDK.
Build and connect the SDK
Here we go over what, in a plugin project, is responsible for connecting the SDK and for making Velitask recognize the built JAR. In plugin-example all of this is already set up — below we explain what each piece does, so you can reproduce it in your own project.
Connecting the SDK
The SDK is published through JitPack. In build.gradle you need the JitPack repository and the SDK dependency:
plugins {
id 'java'
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
dependencies {
compileOnly 'com.github.velitask:velitask-sdk:1.0.+'
}
The key point is compileOnly. The SDK is needed only for compilation: at runtime it is provided by the Velitask application itself. If you bundle the SDK inside the plugin JAR (implementation instead of compileOnly), the classes get duplicated and the plugin won't load. So the SDK is always compileOnly.
1.0.+ takes the latest version of the 1.0 branch. For a reproducible build, replace it with a specific version from Releases.
The JAR manifest
Velitask finds a plugin by an attribute in the JAR manifest. Without it, the application won't recognize it as a plugin. It's configured in the jar task:
jar {
archiveBaseName = 'my-indicator'
manifest {
attributes(
'Velitask-Plugin-Class': 'com.example.myplugin.MyPlagin',
'Velitask-Plugin-Localization': 'strings/strings'
)
}
}
| Attribute | Purpose |
|---|---|
Velitask-Plugin-Class | Required. The fully qualified name of the plugin's entry-point class. This class must implement the IPlagin interface. Velitask instantiates exactly this class on load. |
Velitask-Plugin-Localization | Optional. The base path to localization files inside the JAR (e.g. strings/strings → strings/strings.properties, strings/strings_ru.properties). |
The entry point and the indicator itself are your plugin's code; in plugin-example they're already written, and how they work is covered in that project's documentation (see Next steps). At this step it's enough to know: the class from Velitask-Plugin-Class implements IPlagin and returns a list of indicators.
Building the JAR
gradle jar
The result is build/libs/<archiveBaseName>-<version>.jar. That's the finished plugin: a single file you'll hand to Velitask in the next step.
Next: Install and run.
Install and run
The JAR is built — now hand it to Velitask and put the indicator on the canvas.
1. Where to put the plugin
Velitask loads plugins from configured folders. There are two ways.
Option A — the standard plugins folder
Copy the JAR into the user plugins folder:
| OS | Folder |
|---|---|
| Windows | %USERPROFILE%\.velitask\plugins\ |
| macOS | ~/.velitask/plugins/ |
| Linux | ~/.velitask/plugins/ |
Option B — point to the build folder (handy during development)
To avoid copying the JAR after every build, point Velitask at the build/libs folder itself:
- Open Tools → Settings….
- Select the Plugin folders category.
- Click Add… and choose your project's
build/libsfolder.
Changes apply immediately — Velitask rescans the folders in the background, no restart needed. In the same category the folder list can be reordered (Up / Down) and removed (Remove).
2. Open a canvas
An indicator is drawn on top of the frame in a Mixel — the source's composition. To get a canvas:
- Create or open a project: File → New Project… or File → Open Project….
- Add a source (video, GPX, etc.) to the project if there isn't one yet.
- Double-click the source in the Project panel to open its editor — the Mixel canvas appears in the center.
3. Put the indicator on the canvas
- Open the Indicators panel (View → Indicators; on the left by default).
- Find your indicator by name in the search box.
- Drag it from the list onto the canvas — or open the indicator's context menu and choose Add to Mixel.
The indicator appears on the canvas as a new layer. Select it in the Layers panel — on the right, in the Properties panel, its settings become available (the very ones declared in the indicator's code).
Don't see your indicator in the list? An indicator is shown and can be added only if it's compatible with the data type of the current source. Also check that the JAR is in a connected folder and built without errors. Common causes and how to investigate them — in Next steps and the
plugin-exampledocumentation.
After the indicator appears on the canvas, set up a convenient development loop so edits are picked up without manual copying and restarts.
Next: Development loop.
Development loop
Once the indicator is on the canvas, the main pain is the "rebuild → restart Velitask" cycle. The Dev API removes it: a local HTTP endpoint through which Gradle pushes the fresh JAR into the running application and reloads the plugin in place, without a restart and without losing the open project.
1. Enable the Dev API (once)
- Open Tools → Settings… → Plugin folders.
- In the Dev API (HTTP) section, enable Enable local API for plugin reload.
- The default port is
19809(you can change it).
The reload endpoint (the settings window shows it too):
GET http://127.0.0.1:19809/api/plugins/v1/plugin/reload/{uid}
{uid} is your plugin's identifier (the one returned by getUID()). Access is localhost-only.
2. A Gradle task to rebuild and reload
Add a task to build.gradle that builds the JAR, places it in the plugins folder, and triggers a reload:
tasks.register('installAndReload') {
group = 'velitask'
description = 'Build jar, install it, and reload the plugin in a running Velitask'
dependsOn 'jar'
doLast {
def home = System.getProperty('user.home')
def pluginsDir = file("${home}/.velitask/plugins")
pluginsDir.mkdirs()
def srcJar = jar.archiveFile.get().asFile
def dstJar = new File(pluginsDir, srcJar.name)
dstJar.bytes = srcJar.bytes
logger.lifecycle("[installAndReload] installed: ${dstJar}")
def port = (project.findProperty('devApiPort') ?: '19809') as int
def uid = 'com.example.myplugin' // ← your plugin's uid (matches getUID())
def url = new URL("http://127.0.0.1:${port}/api/plugins/v1/plugin/reload/${uid}")
try {
def conn = (HttpURLConnection) url.openConnection()
conn.requestMethod = 'GET'
conn.connectTimeout = 3000
conn.readTimeout = 65000
logger.lifecycle("[installAndReload] ${url} → ${conn.responseCode}")
} catch (Throwable ex) {
logger.warn("[installAndReload] reload skipped: ${ex.message} (is Velitask running? Dev API enabled?)")
}
}
}
tasks.named('build').configure { finalizedBy 'installAndReload' }
The last line attaches the reload to every build: the IDE's Build button runs gradle build, and therefore installAndReload too.
3. The daily loop
- Velitask is running, your indicator is on the canvas.
- You edit the code in the IDE.
- You hit Build (or
gradle buildin the console). - Velitask reloads the plugin and repaints the canvas with the new version.
If Velitask isn't running or the Dev API is off, the task simply places the JAR and the reload step is skipped; the build won't fail.
On reload, Velitask creates a new plugin instance in a fresh classloader and unloads the old one. So the plugin must release its resources correctly on unload; what exactly handles that is covered in the
plugin-exampledocumentation (see Next steps).
Next: Next steps.
Next steps
Your own indicator on the canvas, a working loop with hot reload — the foundation is ready. Next comes the substantive part: what the indicator shows and how it looks. This documentation is a general guide to the plumbing; API details and techniques live in three places.
Reference plugins
- plugin-example — the minimal plugin you forked. Its code and wiki break down the "skeleton": the plugin class, the indicator, declaring properties, localization, the DB schema. The best starting point when you need to understand "how it works in the small".
- plugin-official — the production plugin shipped with Velitask (speedometer, distance, slope chart, map, etc.). The canonical reference for non-trivial indicators: reading sensors, drawing charts and maps, skins, figures. Look at it when your indicator outgrows "hello world".
JavaDoc
The exact contract of every SDK class and method is in the JavaDoc:
- in the IDE — hover or
Ctrl+Qon any SDK class; - online, after a release is published to JitPack:
https://javadoc.jitpack.io/com/github/velitask/velitask-sdk/<version>/javadoc/.
JavaDoc is the primary source for signatures and behavior. Conceptual overviews (this course, the plugin wikis) complement it — they don't replace it.
What to look for by task
| I want to… | Where to look |
|---|---|
| understand the plugin entry point, version, list of indicators | IPlagin (JavaDoc) + plugin-example |
| draw an indicator and declare settings | IIndicator / Indicator (JavaDoc) + plugin-example |
| add user properties (color, font, text template, SVG) | the properties package (JavaDoc) + plugin-official |
| read source data (speed, distance, coordinates) | ISource / sensors (JavaDoc) + plugin-official |
| have the plugin's own database | PluginDatabase (JavaDoc) + plugin-example |
| localize strings | localization in plugin-example |
If something doesn't work
- The plugin didn't appear in the indicator list — check that the JAR is in a connected folder, the manifest contains
Velitask-Plugin-Class, and the named class implementsIPlagin. An indicator is visible only when compatible with the current source type. - The plugin didn't load / an error on load — Velitask checks the plugin's bytecode against a whitelist of allowed APIs. If the plugin accesses forbidden classes (network, file system, launching processes), loading is rejected. The allowed APIs and restrictions are covered in the
plugin-exampledocumentation. - Fresh edits aren't applied — make sure the Dev API is on and the
installAndReloadtask actually triggers the reload (see Development loop).
Back to the start: Introduction · Home.