Getting Started
Deploy type-safe Kubernetes infrastructure in 5 minutes.
Prerequisites
- Node.js 18+ or Bun installed
- kubectl configured to access a Kubernetes cluster
Installation
bun add typekro arktype
# or: npm install typekro arktype5-Minute Quick Start
Step 1: Create Your App
Create hello-world.ts:
import { type } from 'arktype';
import { kubernetesComposition } from 'typekro';
import { Deployment, Service } from 'typekro/simple';
const AppSpec = type({
name: 'string',
image: 'string'
});
export const app = kubernetesComposition(
{
name: 'hello-world',
apiVersion: 'example.com/v1alpha1',
kind: 'HelloWorld',
spec: AppSpec,
status: type({ ready: 'boolean' })
},
(spec) => {
const deployment = Deployment({
id: 'deploy', // Enables status references (see Resource IDs guide)
name: spec.name,
image: spec.image,
ports: [{ containerPort: 80 }]
});
Service({
id: 'svc',
name: `${spec.name}-service`,
selector: { app: spec.name },
ports: [{ port: 80, targetPort: 80 }]
});
// ✨ Natural JavaScript - automatically converted to CEL
return { ready: deployment.status.readyReplicas > 0 };
}
);Step 2: Deploy It
Create deploy.ts:
import { app } from './hello-world.js';
const factory = app.factory('direct', { namespace: 'default' });
await factory.deploy({
name: 'hello-world',
image: 'nginx:latest'
});
console.log('🚀 Deployed! Check with: kubectl get pods');Run it:
bun run deploy.tsStep 3: Verify
kubectl get pods
# Should show: hello-world-xxx Running🎉 Success! You've deployed your first type-safe Kubernetes app.
What You Just Built
Your simple app demonstrates TypeKro's core concepts:
- 📋 Schema Definition: Type-safe specification using
arktype - 🏗️ Resource Composition: Automatic resource creation and registration
- 🔗 Status Expressions: Dynamic status using CEL expressions
- 🆔 Resource IDs: The
idfield enables cross-resource references (learn more) - 🚀 Direct Deployment: Immediate cluster deployment with TypeScript
Write Natural JavaScript!
TypeKro automatically converts JavaScript expressions to CEL. No special syntax needed:
// ✅ Just write normal JavaScript - TypeKro handles the rest
return {
ready: deployment.status.readyReplicas > 0,
url: `https://${service.status.clusterIP}`,
phase: deployment.status.readyReplicas > 0 ? 'running' : 'pending'
};See JavaScript to CEL for all supported patterns.
When is id Required?
The id field is required when you need to reference a resource in status expressions or from other resources.
| Scenario | id Required? |
|---|---|
Reference in status: deploy.status.readyReplicas | ✅ Yes |
Cross-resource reference: service.status.clusterIP | ✅ Yes |
| Standalone resource with no references | ❌ Optional |
id vs name:
id: TypeKro's internal identifier for CEL paths (e.g.,${deploy.status.readyReplicas})name: The Kubernetes resource name inmetadata.name(what you see inkubectl)
Example: Deployment({ id: 'webApp', name: 'web-app', ... }) creates a Deployment named web-app that you reference as webApp in expressions.
See Resource IDs for complete documentation.
When is Kro Required?
The example above uses Direct mode which deploys resources immediately without any additional controllers.
You don't need Kro for:
- Development and testing
- Simple deployments
- Static configurations
You need Kro for:
- Runtime CEL evaluation (status updates as cluster state changes)
- Continuous reconciliation
- Self-healing infrastructure
See Deployment Modes for details.
Advanced Features Preview
TypeKro offers much more power. Here's a taste of what's possible:
Cross-Resource References:
import { kubernetesComposition } from 'typekro';
import { Deployment, Service } from 'typekro/simple';
// Inside a composition function:
const database = Deployment({ id: 'db', name: 'db', image: 'postgres:15' });
const dbService = Service({
id: 'dbSvc',
name: 'db-svc',
selector: { app: 'db' },
ports: [{ port: 5432 }]
});
const app = Deployment({
id: 'app',
name: 'app',
image: 'myapp:latest',
env: {
// ✨ JavaScript template literals work seamlessly
DATABASE_URL: `postgres://user:pass@${dbService.status.clusterIP}:5432/mydb`
}
});External References Between Compositions:
import { externalRef } from 'typekro';
import { Deployment } from 'typekro/simple';
// Reference a resource deployed by another composition
const dbRef = externalRef<DbSpec, DbStatus>(
'db.example.com/v1',
'Database',
'shared-db',
'databases' // namespace
);
const app = Deployment({
id: 'app',
name: 'app',
image: 'myapp:latest',
env: { DATABASE_HOST: dbRef.status.host }
});Conditional Logic:
import { kubernetesComposition } from 'typekro';
import { Ingress } from 'typekro/simple';
// Inside a composition function:
const ingress = spec.environment === 'production'
? Ingress({
id: 'ingress',
name: `${spec.name}-ingress`,
host: `${spec.name}.example.com`,
serviceName: spec.name,
servicePort: 80
})
: null;
// Status with JavaScript expressions
return {
ready: deployment.status.readyReplicas > 0,
url: ingress ? `https://${spec.name}.example.com` : 'http://localhost'
};What's Next?
Ready to dive deeper? Here's the recommended progression:
- Magic Proxy System - Understand TypeKro's reference system
- JavaScript to CEL - How expressions are converted
- External References - Connect multiple compositions
- Deployment Modes - Direct, Kro, and GitOps strategies
Quick Help
Issues? Check that kubectl can connect to your cluster:
kubectl cluster-infoNeed more help? Open an issue or check our Troubleshooting Guide.