Kubernetes deployments in TypeScript. Type-safe, composable, from npm.
// chart.ts
import { Chart } from "c8x";
export default (): Chart => ({
namespace: { apiVersion: "v1", kind: "Namespace", metadata: { name: "app" } },
components: [
{ apiVersion: "apps/v1", kind: "Deployment", metadata: { name: "web" },
spec: { replicas: $env.get("REPLICAS") ?? 2,
selector: { matchLabels: { app: "web" } },
template: { metadata: { labels: { app: "web" } },
spec: { containers: [{ name: "web", image: "nginx" }] } } } },
{ apiVersion: "v1", kind: "Service", metadata: { name: "web" },
spec: { selector: { app: "web" }, ports: [{ port: 80 }] } },
],
});c8x up chart.tsThat's it. TypeScript compiles, validates, and deploys to your cluster. Full IDE autocompletion for every Kubernetes field.
npm install -g @c8x/clic8x up chart.ts # deploy (install or upgrade, like docker compose up)
c8x down wordpress # remove everything (like docker compose down)
c8x inspect chart.ts # preview YAML without deploying
c8x diff chart.ts # show what would change
c8x rollback wordpress # rollback to previous revision
c8x history wordpress # show all revisions
c8x status wordpress # show current statenpm install c8x @c8x/wordpressimport { Chart } from "c8x";
import wordpress from "@c8x/wordpress";
export default (): Chart => wordpress();echo "C8X_WP_DOMAIN=blog.example.com" > .env
c8x up chart.ts| Chart | Description |
|---|---|
| @c8x/wordpress | WordPress + MariaDB |
| @c8x/nextcloud | Nextcloud + PostgreSQL |
| @c8x/youtrack | JetBrains YouTrack |
| @c8x/monitoring | Prometheus + Grafana + node-exporter |
# Helm: Go templates in YAML
{{- if and .Values.ingress.enabled (gt (len .Values.ingress.hosts) 0) }}
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- end }}
{{- end }}
{{- end }}// c8x: just TypeScript
values.ingress.hosts
.filter(h => h.enabled)
.map(host => ({
host: host.name,
http: { paths: host.paths.map(p => ({ path: p.path, pathType: "Prefix" })) },
}))| Helm | c8x | |
|---|---|---|
| Templating | Go templates | TypeScript |
| Packaging | Custom | npm |
| Configuration | --set x.y.z=1 |
.env |
| Type safety | None | Full IDE support |
| Validation | At apply time | Before deploy ($assert) |
| Code sharing | Copy _helpers.tpl |
npm install |
| Cluster awareness | None | $cluster API |
Charts run sandboxed. External access requires explicit flags (like Deno):
c8x up chart.ts # safe globals only
c8x up chart.ts --allow-file # $file.read
c8x up chart.ts --allow-http # $http requests
c8x up chart.ts --allow-cluster # $cluster queries
c8x up chart.ts -A # allow allAlways available: $env, $chart, $base64, $hash, $log, $assert, $yaml
With --allow-file: $file.read(path), $file.exists(path)
With --allow-http: $http.get, $http.getJSON, $http.post, $http.postJSON
With --allow-cluster: $cluster.version(), $cluster.versionAtLeast(v), $cluster.apiAvailable(api), $cluster.nodeCount(), $cluster.exists(...), $cluster.list(...), $release.*
// Validate before deploy
$assert($env.get("DB_PASSWORD") !== "changeme", "Set a real password");
// Load TLS certs from disk
data: { "tls.crt": $base64.encode($file.read("certs/tls.crt")) }
// Config hash for rolling updates
annotations: { "c8x/config-hash": $hash.sha256(JSON.stringify(config)) }
// Fetch secrets from Vault
const secret = $http.getJSON("https://vault.internal/v1/secret/data/db",
{ headers: { "X-Vault-Token": $env.get("VAULT_TOKEN") } });
// Adapt to cluster capabilities
const ingress = $cluster.apiAvailable("gateway.networking.k8s.io/v1")
? GatewayRoute({ domain })
: Ingress({ domain });
// Migration only on first deploy
if (!$release.exists) components.push(MigrationJob());
// Conditional components
components: [
App(values),
...(enableRedis ? [Redis()] : []),
]Stored as ConfigMaps in the namespace. Enables up, down, rollback, history, status, diff.
$ c8x history wordpress
REVISION STATUS TRIGGER RESOURCES DEPLOYER DEPLOYED
1 superseded ci 5 runner@gh-actions-12 2026-04-06 10:00:00
2 superseded manual 5 niklas@mbp 2026-04-07 15:00:00
3 deployed rollback 5 niklas@mbp 2026-04-08 22:00:00