Getting started
Kinetica builds with the JetBrains Kotlin Toolchain (the Amper successor): declarative YAML modules, a ./kotlin wrapper CLI, no Gradle.
Project layout
A project is a project.yaml listing modules; a module is a directory with a module.yaml. A minimal browser app (the apply template wires the mandatory compiler plugin — without it every state/event call throws MissingKineticaPluginException at runtime):
# module.yaml
product: js/app
apply:
- ../../common.module-template.yaml # registers io.heapy.kinetica:kinetica-compiler
dependencies:
- ../../kinetica-browser
- ../../kinetica-runtime// src/main.kt
package app
import io.heapy.kinetica.*
import io.heapy.kinetica.browser.mountKineticaApp
@UiComponent
fun ComponentScope.App() {
var name by state { "world" }
column {
textInput(value = name, onInput = event<String> { name = it })
text("Hello, $name!")
}
}
fun main() {
mountKineticaApp("#app") { App() }
}<!-- web/index.html -->
<div id="app"></div>
<script type="module" src="../../../build/tasks/_my-app_linkJs/my-app.mjs"></script>Build and run
./kotlin build -m my-app # emits build/tasks/_my-app_linkJs/my-app.mjs
./kotlin test -m my-module # run a module's tests
./kotlin show modules # inspect the project modeljs/app output is an ES-module graph; serve the repository root with any static file server and open the page. JVM apps (product: jvm/app) run with ./kotlin run -m my-server and package to an executable jar with ./kotlin package.
Components are plain functions
There is no component class and no special file type. A component is a function with ComponentScope as receiver that emits nodes:
@UiComponent
fun ComponentScope.Badge(label: String) {
host("span", props = mapOf("class" to "badge")) {
text(label)
}
}Composition is a function call: Badge("New"). State lives in slots whose identity the mandatory compiler plugin assigns at compile time — every component is a @UiComponent fun ComponentScope.X(...), and every state/derived/effect call site gets its own slot automatically. Lists still key their rows explicitly: each(items, key = { … }).
Mounting choices
| Entry point | Use for |
|---|---|
mountKineticaApp(selector) { App() } | Browser apps (renderer details) |
KineticaRuntime().render { App() }.tree.toSafeHtml() | Server-side HTML (server components) |
KineticaTest.render { App() } | Headless tests (testing) |
mountKineticaApp defaults to KineticaRuntime(debug = true) — journaling, duplicate-key checks and debug DOM attributes. Pass KineticaRuntime(debug = false) for production mounts.