Krom Mini-App StudioFull IDE support for KromScript ( FeaturesLanguage intelligence (
|
| Pack | Components | Module |
|---|---|---|
| forms | MaskedField, CurrencyField, PhoneField, SignaturePad, RatingField, FormWizard, FieldError, FormBody, Field, SubmitButton |
forms.email/phone/required/minLength/maxLength/range/digits/luhn/validate/group |
| media | MediaGrid, MediaThumb, PhotoView, CameraButton |
media.pickImage/captureImage/pickVideo/pickMultiple/toBase64 |
| charts | LineChart, AreaChart, DonutChart, Sparkline, StackedBarChart, ScatterChart, ChartLegend |
charts.palette/formatNumber/percent/niceScale |
Color props of lib components accept theme roles ("primary", "onSurface",
"scrim", …) — the completion offers the exact roles each pack resolves. Using a pack
that isn't declared in requires produces a warning with a quick fix that adds it.
Manifest validation (manifest.json)
The app manifest is validated two ways:
- JSON Schema (
schemas/manifest.schema.json, wired throughcontributes.jsonValidation) — field presence, types, enums, and completions while editing. - Custom consistency diagnostics that a schema cannot express:
entrymust reference an existing key inpages.- Every
tabBar.list[].pagePathmust reference an existing key inpages. - Each page
source, everyutils[]entry,iconpaths,tabBaricon paths, andsubpackagespages must resolve to a file that exists on disk.
Only KromScript app manifests (objects with entry + pages) are checked, so unrelated
manifest.json files in a workspace are left alone.
Recognized manifest fields:
{
"id": "com.example.app", // required
"name": "My App", // required
"version": "1.0.0", // required
"entry": "home", // required — a key in `pages`
"icon": "assets/icon.png",
"description": "…",
"pages": { // required
"home": { "name": "Home", "icon": "home", "source": "pages/home.ks" }
},
"utils": ["utils/theme.ks"],
"requires": ["forms", "media", "charts"], // library packs (see above)
"minSdk": "1.1.0",
"license": "MIT",
"customWidgets": { "RatingStars": { "childType": "none" } },
"permissions": ["storage", "network"],
"networkTimeout": { "request": 10000 },
"window": {
"navigationBarTitleText": "My App",
"navigationBarBackgroundColor": "#2196F3",
"navigationBarTextStyle": "white"
},
"tabBar": {
"list": [{ "pagePath": "home", "text": "Home", "iconPath": "assets/home.png" }]
},
"subpackages": [{ "root": "packageA", "pages": ["detail.ks"] }]
}
Integrated commands
Run from the Command Palette (all under the Krom category), or click the
⚡ <app> v<version> status bar item to open the Krom menu. The extension knows the
current project from its manifest.json (the id slug plus the CLI-managed appId) —
no ID is ever typed or copied. Commands invoke the krom CLI (from the krom_bundler
package) in the project folder, streaming output to a dedicated Krom output channel.
| Command | CLI | Description |
|---|---|---|
| Krom: Build | krom build |
Production build from manifest.json. |
| Krom: Connect | krom login --with-token |
Set the backend URL and Personal Access Token. |
| Krom: Publish | krom publish |
Build, create the app if needed, deploy a DRAFT version. |
| Krom: Link Project | krom link |
Attach to the backend app and write appId into the manifest. |
| Krom: Bind to Super-App | krom bind |
Pick the super-apps (by name, multi-select) this mini-app is available in. |
| Krom: Dev (hot reload) | krom dev |
Start the dev server with hot reload. |
| Krom: Stop Dev Server | — | Stop the running dev server. |
| Krom: Device Preview | — | Device-only preview inside VSCode (model selector, rotate). |
| Krom: Open Preview | — | Full preview (inspector, logs, network) in the browser. |
| Krom: Menu | — | The status-bar menu with all of the above. |
Requirements
- The
kromCLI (fromkrom_bundler) must be installed and on yourPATHto use the Build / Publish / Dev commands. If it lives elsewhere, setkromscript.cliPath.
Extension settings
| Setting | Default | Description |
|---|---|---|
kromscript.inlayHints.enabled |
true |
Show widget closing-name inlay hints. |
kromscript.formatOnSave |
true |
Format .ks files on save. |
kromscript.cliPath |
"krom" |
Path to the krom CLI executable. |
kromscript.remoteUrl |
"" |
Krom backend base URL (set via Krom: Connect). |
kromscript.previewPort |
3000 |
Port of the krom dev preview server. |
The KromScript language at a glance
@use './utils/theme.ks'
let count = Obs(0)
fn increment() {
count.set(count.value + 1)
}
fn onInit() {
println("page ready")
}
fn build() {
return Scaffold({
appBar: AppBar({ title: "Counter" }),
body: Center({}, [
Column({ spacing: 12, crossAxisAlignment: "center" }, [
Text("Count: " + toString(count.value), { fontSize: 20 }),
Button("Increment", { variant: "filled", onTap: "increment" })
])
])
})
}
- Reactivity —
Obs(value)(.value,.set,.update,.toggle) andList([…])(.add,.clear,.map, …). Wrap reactive UI inObx({ builder: "…" }). - Lifecycle hooks —
onInit,onShow,onHide,onDispose. - Imperative UI —
ui.toast,ui.showModal,ui.showBottomSheet,ui.pop, …
Native APIs
These are implemented in the kmini_program runtime and surfaced through completions and hover.
storage.* — persistent key/value storage
Values are strings; serialize objects with jsonStringify / jsonParse.
storage.setItem('authToken', token)
let saved = storage.getItem('authToken') // string | null
storage.removeItem('authToken')
storage.clear()
nav.* — page navigation
Pages are referenced by their key in manifest.json → pages.
nav.navigateTo('detail', { id: 42 }) // push, with optional params
nav.redirect('home') // replace current page (alias: nav.redirectTo)
nav.back() // pop to the previous page
device.* — platform & device info
let p = device.platform() // 'ios' | 'android' | 'web' | 'macos' | …
let info = device.systemInfo() // { platform, osVersion, model, screenWidth, screenHeight, pixelRatio }
request(...) — HTTP requests
The interpreter is synchronous, so request returns nothing — results arrive through the
onSuccess / onError callbacks. onSuccess(res) receives { statusCode, data, headers, ok }
and onError(err) receives { error, statusCode }.
request(
{ url: 'https://api.example.com/users', method: 'GET' },
fn (res) {
if (res.ok) {
ui.toast('Got ' + toString(res.statusCode))
println(res.data)
}
},
fn (err) {
ui.toast('Failed: ' + err.error)
}
)
Release notes
See CHANGELOG.md.