Create the first application
Build and verify a standalone API-only application with the published Cloud package.
Build Cloud applications in their own repositories. A standalone application owns its source, dependencies, image, version, and release cycle while Cloud supplies the gateway and shared platform services.
Start with the Cloud app starter
Use the Cloud app starter for a working to-do app with SSR, live updates, permissions, notifications, and a
@k2b/uiworkspace.Choose Use this template on GitHub, then follow its README to connect the app to your existing Cloud development stack.
This guide creates an API-only inventory service with one endpoint:
GET /api/inventory/healthThe first direct request proves the application package and process. A later request through the gateway proves that deployment networking, registration, and route discovery agree.
Work with a coding agent
Install the cloud-dev Agent Skill from your project directory with Bun:
bunx skills add k2b-dev/cloud --full-depth --skill cloud-dev--full-depth finds the skill in the repository's documentation directory;
--skill cloud-dev selects only the development skill, not cloud-cli.
Add --global to install it for your user instead of the current project.
The Agents dialog in the documentation footer provides another installation
option.
The skill supplies stable application boundaries for standalone and built-in Cloud applications and routes the agent to current documentation instead of duplicating API details.
For documentation access, configure a streamable HTTP MCP server named
cloud-dev-mcp at https://cloud.k2b.dev/_fibel/mcp, then restart the agent
session. The agent should call list_collections, search_docs, and read_doc
before choosing an implementation.
Prepare a standalone project
Install Bun and create a repository:
mkdir cloud-inventory
cd cloud-inventory
bun init -y
mkdir -p srcAdd the Cloud package and its public peer dependencies:
bun add @k2b/cloud hono solid-js zod
bun add --dev @types/bun typescriptPin @k2b/cloud to the version used by the target Cloud deployment
before committing the lockfile. An application and its platform must agree on
their public runtime contracts.
Create tsconfig.json:
{
"compilerOptions": {
"lib": ["ESNext", "DOM", "DOM.AsyncIterable"],
"target": "ESNext",
"module": "Preserve",
"moduleDetection": "force",
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
"strict": true,
"skipLibCheck": true,
"noUncheckedIndexedAccess": true
},
"include": ["src/**/*.ts", "src/**/*.tsx"]
}The application imports only published package entry points. It does not need the Cloud source repository, workspace aliases, or another application package.
Declare the service boundary
Create src/config.ts:
import { defineApp } from "@k2b/cloud";
export const app = defineApp({
id: "inventory",
name: "Inventory",
icon: "ti ti-packages",
description: "Track stock and warehouse movements.",
baseUrl: "http://inventory:3000",
routes: ["/api/inventory"],
});The declaration is the service's public platform identity:
idremains stable across releases;baseUrlis the private address the gateway can reach;routescontains only prefixes the service actually handles.
This API-only application declares no page, asset, or administration prefix. See Define an application for every declaration option and Routes and discovery for prefix ownership.
Handle one request
Create src/index.ts:
import { Hono } from "hono";
import { app } from "./config";
const router = new Hono().get("/api/inventory/health", (c) =>
c.json({
app: app.meta.id,
status: "ok",
}),
);
export default await app.start({
fetch: router.fetch,
});defineApp() does not create routes. Hono owns request matching and the
application passes its final Fetch handler to app.start().
This public health endpoint needs no caller identity or platform settings. Add request middleware when a route needs request context, authentication, settings, logging, or rate limits.
Verify the process directly
Use an initialized Cloud development deployment. Configure DATABASE_URL,
REDIS_URL, NATS_SERVERS, SYNC_NAMESPACE and APP_SECRET for that deployment,
then start the application. Shared platform tables are required even when the
application has no domain schema. See
Deployment requirements.
bun src/index.tsIn another terminal, request the application directly:
curl http://127.0.0.1:3000/api/inventory/healthThe response is:
{
"app": "inventory",
"status": "ok"
}This check proves the public package, application declaration, Hono router, and process startup. It does not prove gateway routing, shared identity, or other platform services.
Connect the application to Cloud
Run the application on the same private network as the target Cloud deployment. The deployment must provide:
- a gateway and Core;
- Valkey through
REDIS_URL; - NATS JetStream through
NATS_SERVERS, with the deployment'sSYNC_NAMESPACE; - the deployment-wide
APP_SECRET; - initialized Postgres through
DATABASE_URL; - any optional platform service the application uses.
The hostname and port in baseUrl must resolve from the gateway. After the
application starts, call the same route through the public gateway origin:
curl https://cloud.example/api/inventory/healthA gateway 502 means no usable live service owns the prefix. A 404 means the
gateway reached the application but Hono did not match the path. Follow the
route diagnosis before
adding application logic.
Do not expose the application container as a second public origin. The gateway is the public boundary for routing, identity, and platform-wide policy.
Grow by responsibility
The first version needs only two files:
src/
├── config.ts
└── index.tsAdd a file or directory only when that responsibility exists:
src/
├── config.ts
├── index.ts
├── contracts.ts
├── migrate.ts
├── api/
├── data/
├── service/
└── frontend/| Path | Responsibility |
|---|---|
config.ts |
Application identity and declarative platform integrations |
index.ts |
Middleware order, route mounting, and app.start() |
contracts.ts |
Input and output schemas shared across boundaries |
migrate.ts |
Idempotent application-schema changes |
api/ |
HTTP transport |
data/ |
Queries and repositories |
service/ |
Domain rules |
frontend/ |
SSR pages and interactive islands |
Keep business rules and persistence out of route handlers. Domain services receive explicit inputs instead of a Hono context.