Cloud|

Create the first application

Build and verify a standalone API-only application with the published Cloud package.

4 min read Updated 2026-08-12 #applications#getting-started#standalone

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/ui workspace.

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:

text
GET /api/inventory/health

The 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:

bash
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:

bash
mkdir cloud-inventory
cd cloud-inventory
bun init -y
mkdir -p src

Add the Cloud package and its public peer dependencies:

bash
bun add @k2b/cloud hono solid-js zod
bun add --dev @types/bun typescript

Pin @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:

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:

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:

  • id remains stable across releases;
  • baseUrl is the private address the gateway can reach;
  • routes contains 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:

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.

bash
bun src/index.ts

In another terminal, request the application directly:

bash
curl http://127.0.0.1:3000/api/inventory/health

The response is:

json
{
  "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's SYNC_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:

bash
curl https://cloud.example/api/inventory/health

A 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:

text
src/
├── config.ts
└── index.ts

Add a file or directory only when that responsibility exists:

text
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.

Continue by capability

Connect a coding agent

The Cloud skill provides compact working instructions. MCP supplies exact current documentation when details matter.

CLI command
bunx skills add https://docs.example.com

This command installs the working instructions published by this website in the selected coding agent.

For exact, current details, also connect the MCP server through one of the agent tabs.

Installation uses the open-source Vercel Skills CLI.

The skill and MCP complement each other: the skill describes workflows, while MCP supplies current documentation.