Development
Develop against the whole platform.
tako dev brings the production platform with it: workflows, channels, image optimization, secrets, and the same routing model your app uses after deploy.
The platform layer that makes them feel like a PaaS.
Move this project to tako.sh.
Full control. A real server, a real runtime — what runs locally runs in production.
Unapologetically opinionated. No config rabbit holes — Tako picks the defaults so you can ship.
Built for the impatient. Every step is optimized to get your code live fast.
tako dev brings the production platform with it: workflows, channels, image optimization, secrets, and the same routing model your app uses after deploy.
PaaS-style release safety on servers you own.
tako deploy gives you health-gated traffic switches, zero-downtime rollouts, and rollback without moving off your VPS.
Your VPS stays yours. tako-server adds the platform layer: TLS, routing, processes, logs, secrets, rollbacks, and scale-to-zero workers without hiding SSH or the machine.
The same server runs the app primitives agents usually have to provision elsewhere: secrets, env vars, workflows, channels, image optimization, storage, cache, and backups. They stay available from code, so an agent can wire the feature in the repo instead of assembling extra services.
How Tako works →// src/channels/deploys.ts
// durable app events, no realtime vendor
import { defineChannel } from "tako.sh";
// typed messages are stored for replay, then fanned out
// to every connected SSE/WebSocket client
type DeployMessages = {
status: {
release: string;
state: "building" | "healthy";
};
};
export default defineChannel("deploys")
.$messageTypes<DeployMessages>();
// src/routes/deploy.ts
// server-side publish
import deploys from "../channels/deploys";
// late clients can reconnect and catch up from replay
await deploys.publish({
type: "status",
data: {
release: id,
state: "healthy",
},
});// src/workflows/ship-order.ts
// checkpoint steps, park for approval, then resume
import { defineWorkflow } from "tako.sh";
export default defineWorkflow<{ orderId: string }>("ship-order", {
handler: async ({ orderId }, ctx) => {
const event = "approval:" + orderId;
await ctx.run("charge", () => billing.charge(orderId));
// parks the run until a route or webhook sends signal()
const approval = await ctx.waitFor<{ approved: boolean }>(
event,
);
if (!approval?.approved) ctx.bail("not approved");
await ctx.run("ship", () => fulfillment.ship(orderId));
},
});
// src/routes/approve.ts
import { signal } from "tako.sh";
// wakes the waitFor() above
await signal("approval:" + orderId, {
approved: true,
});// src/components/hero-image.tsx
// optimized image URLs from app code
import { imageUrl } from "tako.sh";
export function HeroImage() {
// returns a normal URL backed by /_tako/image
const src = imageUrl("/images/hero.png", {
width: 1200,
format: "webp",
});
return (
<img
src={src}
alt="Product dashboard"
width={1200}
height={720}
/>
);
}// src/config/runtime.ts
// runtime metadata and typed public vars
import { tako } from "tako.sh";
// generated types know your environments and public vars
export const runtime = {
env: tako.env,
isProduction: tako.isProd,
build: tako.build,
};
export const publicConfig = {
origin: process.env.PUBLIC_ORIGIN,
};// src/server/database.ts
// typed secret reads, no env files
import { tako } from "tako.sh";
export function connectDatabase() {
return createClient({
// read the one value you need; never log the bag
url: tako.secrets.DATABASE_URL,
ssl: tako.isProd,
});
}Stop configuring.
Start shipping.