# @colineapp/sdk TypeScript SDK for building apps on [Coline](https://coline.app). ## Install ```bash npm install @colineapp/sdk ``` ## Build a Coline App in 5 Minutes ### 1. Define your app ```ts import { ColineApp, ui, actions, createHandler } from "@colineapp/sdk"; const app = new ColineApp({ key: "com.acme.todos", name: "Acme Todos", description: "Track todos inside Coline.", permissions: ["app.home.read", "files.read", "files.write"], hosting: { mode: "external", baseUrl: "https://your-app.example.com" }, }); // Define a file type your app owns app.defineFileType({ typeKey: "todo", name: "Todo", description: "A todo item", storage: "coline_document", indexable: true, homeRenderMode: "cached", }); // Render the app's home screen app.onHomeRender((ctx) => ui.stack([ ui.heading("Todos"), ui.text(`Workspace: ${ctx.workspace.name}`), ui.button("New Todo", { action: actions.createFile({ name: "Untitled Todo", typeKey: "todo", document: { status: "open" }, }), }), ]), ); // Render an individual file app.onFileRender((ctx) => ui.stack([ ui.heading(ctx.file.title ?? "Todo"), ui.badge(String(ctx.document["status"] ?? "open")), ]), ); ``` ### 2. Serve it The SDK gives you one handler that routes all Coline traffic: ```ts const handler = createHandler({ app, secret: process.env.COLINE_DELIVERY_SECRET!, onWebhook: (event) => { console.log("Webhook:", event.type); }, }); ``` Mount it on any framework: ```ts // Hono const server = new Hono(); server.all("/coline/*", (c) => handler(c.req.raw)); // Next.js App Router (app/coline/[...path]/route.ts) export const GET = handler; export const POST = handler; // Cloudflare Workers / Bun / Deno export default { fetch: handler }; // Express (with raw body parsing) app.all("/coline/*", async (req, res) => { const response = await handler(toWebRequest(req)); res.status(response.status).json(await response.json()); }); ``` ### 3. Register on Coline Start your app, then go to [coline.app/developers/apps/new](https://coline.app/developers/apps/new). 1. Enter your app's base URL (e.g. `http://localhost:3100`) 2. Click **Import from app** — the console fetches your manifest from `GET /coline/manifest` 3. Review everything and submit That's it. The console pulls your manifest, permissions, file types, and notification channels directly from the SDK — no copy-pasting JSON. For store-listed apps, submit for review from the app detail page. For private apps, install directly into your workspace. --- ## Routes Your App Exposes `createHandler()` handles these automatically: | Route | Method | Purpose | |-------|--------|---------| | `/coline/manifest` | GET | Returns your app manifest (used by the developer console) | | `/coline/render/home` | POST | Renders your app's home screen | | `/coline/render/file` | POST | Renders a file owned by your app | | `/coline/actions` | POST | Handles UI action callbacks (button clicks, etc.) | | `/coline/events` | POST | Receives webhook events | All POST routes are verified using your delivery secret. --- ## API Client For server-to-server calls (creating files, sending notifications, etc.): ```ts import { ColineApiClient } from "@colineapp/sdk"; const client = new ColineApiClient({ baseUrl: "https://coline.app", apiKey: process.env.COLINE_API_KEY!, }); // Fluent scoped handles const ws = client.workspace("acme"); const app = ws.app("com.acme.todos"); // Create a file const { file } = await app.createFile({ name: "Buy milk", typeKey: "todo", document: { status: "open" }, }); // Update it await app.file(file.id).updateDocument({ status: "done" }); // Send a notification await app.sendNotification({ channelKey: "updates", title: "Todo completed", body: "Buy milk is done!", recipients: [{ userId: "user_123" }], }); ``` ## Webhooks Verify and handle webhook events with typed payloads: ```ts import { webhooks } from "@colineapp/sdk"; // In your webhook handler: const event = await webhooks.constructEvent(rawBody, request.headers, secret); switch (event.type) { case "message.created": console.log(event.data.plaintext); break; case "task.created": console.log(event.data.title, event.data.priority); break; } ``` Or use `createHandler({ onWebhook })` for automatic verification. ## UI Components Build native Coline UI with the `ui` helper: ```ts import { ui, actions } from "@colineapp/sdk"; ui.heading("Title"); ui.text("Body text"); ui.badge("Status"); ui.button("Click me", { action: actions.openFile("file_123") }); ui.stack([...components], { gap: "md" }); ui.row([...components], { gap: "sm" }); ui.divider(); ui.image({ src: "https://...", alt: "Photo" }); ``` ## Raw OpenAPI Client For direct spec-driven access: ```ts import { createAppPlatformClient } from "@colineapp/sdk"; const client = createAppPlatformClient({ baseUrl: "https://coline.app", apiKey: process.env.COLINE_API_KEY!, }); const { data } = await client.GET("/api/v1/apps"); ``` ## Regenerate OpenAPI Types ```bash pnpm sdk:generate:openapi ```