| name | cue-kind-definition |
| license | Apache-2.0 |
| description | Author CUE kind definitions for grafana-app-sdk apps - schemas, versioning, field constraints, named type definitions, custom routes, and codegen configuration. Scaffolds kinds via `grafana-app-sdk project kind add`, writes spec/status schemas with type constraints (regex, enum, range), defines `#`-prefixed named types for reusable structs, registers versions in the app manifest, and runs `grafana-app-sdk generate` with explicit error recovery. Use when working with CUE kinds, adding a new resource type, adding a version to an existing kind, writing schema field constraints, defining `#Definition` types, adding custom routes, editing files under `kinds/`, or when the user asks to "model a resource", "add a CUE schema", or "write a kind" — even without saying "CUE" explicitly. |
CUE Kind Definition
Common Workflows
Adding a new kind
grafana-app-sdk project kind add MyKind --overwrite
grafana-app-sdk generate
ls pkg/generated/
If generate fails with CUE errors:
- Read the error — CUE prints the offending file + line + which constraint failed
- Common causes: missing required field, type mismatch (e.g.
string field assigned an int), unresolved reference between version files
- Fix the
.cue source, re-run grafana-app-sdk generate. Never edit files under pkg/generated/ — they're overwritten on every run.
Adding a new version to an existing kind
cp kinds/mykind_v1alpha1.cue kinds/mykind_v1.cue
grafana-app-sdk generate
ls pkg/generated/
Breaking changes (removing fields, changing types, adding required fields) must go into a new version — never modify a stable version (v1, v2) in place.
Kind file structure
The CLI produces a flat layout under kinds/:
kinds/
├── manifest.cue # App manifest + version list declarations
├── mykind.cue # Common (cross-version) kind metadata
└── mykind_v1alpha1.cue # v1alpha1 schema + codegen config
For multi-version kinds, additional version files sit alongside (mykind_v1.cue, etc.). For very large kind sets (10+ kinds), consider the per-kind subdirectory layout — full kind anatomy reference in references/kind-layout.md.
CUE Kind Anatomy
Three layers per kind:
1. Common kind metadata
// kinds/mykind.cue
package kinds
myKind: {
kind: "MyKind" // Required: PascalCase kind name
// other cross-version fields (scope, pluralName, validation, mutation, conversion, …)
// Full field reference in references/kind-layout.md.
}
2. Per-version schema
// kinds/mykind_v1alpha1.cue
package kinds
myKindv1alpha1: myKind & {
schema: {
spec: { // desired state — user-set
title: string
description: string | *""
count: int & >=0
enabled: bool | *true
}
status: { // observed state — operator-set
lastObservedGeneration: int | *0
state: string | *""
message: string | *""
}
}
codegen: {
ts: { enabled: true }
go: { enabled: true }
}
}
3. App manifest
// kinds/manifest.cue
package kinds
App: {
appName: "my-app"
versions: {
"v1alpha1": { schema: myKindv1alpha1 }
}
}
Codegen configuration
Control what gets generated per kind per version:
codegen: {
ts: { enabled: true | false } // TypeScript types
go: { enabled: true | false } // Go types + client
}
Disabling go for frontend-only apps avoids unused Go code. Disabling ts for backend-only resources reduces bundle size. Both default to true when omitted.
References
External resources