create-coline-app 2.1.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +62 -0
- package/README.md +9 -3
- package/package.json +2 -1
- package/src/cli.test.ts +48 -0
- package/templates/backendless/.agents/skills/coline-app-development/SKILL.md +70 -0
- package/templates/backendless/AGENTS.md +169 -0
- package/templates/backendless/CLAUDE.md +6 -0
- package/templates/backendless/README.md +6 -4
- package/templates/backendless/app.config.ts +7 -3
- package/templates/backendless/main.tsx +100 -0
- package/templates/backendless/package.json +10 -5
package/AGENTS.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# create-coline-app package agent guide
|
|
2
|
+
|
|
3
|
+
This package owns the external developer experience: the `create-coline-app`
|
|
4
|
+
scaffold and the `coline-app push/dev` CLI. The template is a tested public
|
|
5
|
+
contract, not illustrative pseudocode.
|
|
6
|
+
|
|
7
|
+
## Source of truth
|
|
8
|
+
|
|
9
|
+
- `src/scaffold.ts` copies `templates/backendless` and replaces app
|
|
10
|
+
placeholders.
|
|
11
|
+
- `src/push.ts` bundles `app.config.ts`, extracts the manifest, and collects
|
|
12
|
+
`main.tsx` plus app `.ts`, `.tsx`, and `.css` source for React surfaces.
|
|
13
|
+
- `templates/backendless/AGENTS.md` is the primary guidance delivered to
|
|
14
|
+
every generated app.
|
|
15
|
+
- `templates/backendless/.agents/skills/` contains the reusable task skill
|
|
16
|
+
discovered by OpenCode/Codex-style agents.
|
|
17
|
+
|
|
18
|
+
## Non-negotiable scaffold contract
|
|
19
|
+
|
|
20
|
+
After a clean `npx create-coline-app app && cd app && npm install`, the project
|
|
21
|
+
must have a working backend example, a working React starter, accurate agent
|
|
22
|
+
guidance, and tests that do not need the Coline product repository or a running
|
|
23
|
+
Coline server.
|
|
24
|
+
|
|
25
|
+
Keep these versions aligned in one release:
|
|
26
|
+
|
|
27
|
+
- `@colineapp/sdk` — logic, manifest, capabilities, tree UI, test workspace
|
|
28
|
+
- `@colineapp/ui` — React provider, hooks, components, stylesheet
|
|
29
|
+
- `@colineapp/app-runtime` — transitive guest/host bridge dependency
|
|
30
|
+
- `create-coline-app` — scaffold and push/dev CLI
|
|
31
|
+
|
|
32
|
+
When any public API changes, update the package README, package `AGENTS.md`,
|
|
33
|
+
template `AGENTS.md`, template skill, template dependencies, and the focused
|
|
34
|
+
smoke test together.
|
|
35
|
+
|
|
36
|
+
## Agent-safety rules
|
|
37
|
+
|
|
38
|
+
- A generated app must be self-describing. Agents should not need to inspect
|
|
39
|
+
`/Users/radin/coline-app`, a worktree, or private first-party apps.
|
|
40
|
+
- Do not make the template point at local workspace packages or private URLs.
|
|
41
|
+
- Do not claim a dependency is “already wired” unless it is in the generated
|
|
42
|
+
`package.json` and exercised by the template.
|
|
43
|
+
- Do not add a React example without the `main.tsx` entry, React peer packages,
|
|
44
|
+
CSS export, and a manifest surface that references it.
|
|
45
|
+
- Keep external hosting, network, auth, and database claims explicit. The
|
|
46
|
+
default app is hosted and backendless.
|
|
47
|
+
|
|
48
|
+
## Verification
|
|
49
|
+
|
|
50
|
+
- Run `pnpm --filter create-coline-app typecheck` and
|
|
51
|
+
`pnpm --filter create-coline-app test`.
|
|
52
|
+
- The CLI tests must assert placeholder replacement, exact package dependency
|
|
53
|
+
wiring, the React starter's presence, and that the app config bundles against
|
|
54
|
+
the real SDK source.
|
|
55
|
+
- Never use a checked-in private app as the only proof that a public scaffold
|
|
56
|
+
works. Add the smallest self-contained fixture instead.
|
|
57
|
+
|
|
58
|
+
## Release hygiene
|
|
59
|
+
|
|
60
|
+
The package publishes `bin`, `src`, `templates`, `README.md`, `AGENTS.md`, and
|
|
61
|
+
`LICENSE`. Bump the CLI version when the template contract changes. Publish
|
|
62
|
+
the three runtime libraries first, then publish this CLI with matching ranges.
|
package/README.md
CHANGED
|
@@ -9,9 +9,10 @@ cd my-app && npm install && npm test
|
|
|
9
9
|
|
|
10
10
|
Two binaries ship from this package:
|
|
11
11
|
|
|
12
|
-
- **`create-coline-app <dir>`** — scaffolds a backendless app:
|
|
13
|
-
`defineApp` config with a Kairo tool, a file type with tree surfaces,
|
|
14
|
-
|
|
12
|
+
- **`create-coline-app <dir>`** — scaffolds a self-contained backendless app:
|
|
13
|
+
a `defineApp` config with a Kairo tool, a file type with tree surfaces, a
|
|
14
|
+
working React home using `@colineapp/ui`, mobile/tree fallback rendering,
|
|
15
|
+
agent guidance, and tests against `@colineapp/sdk/testing`.
|
|
15
16
|
- **`coline-app push | dev`** — builds the logic bundle with esbuild,
|
|
16
17
|
extracts the manifest through the two-artifact model (plan §6.2),
|
|
17
18
|
collects client source when the manifest declares react surfaces, and
|
|
@@ -20,3 +21,8 @@ Two binaries ship from this package:
|
|
|
20
21
|
|
|
21
22
|
The CLI never builds tier-2 client bundles itself — it ships source and
|
|
22
23
|
Coline's reviewed build pipeline produces the bundle.
|
|
24
|
+
|
|
25
|
+
The generated project includes `AGENTS.md` and
|
|
26
|
+
`.agents/skills/coline-app-development/SKILL.md`. Those files are deliberately
|
|
27
|
+
specific to the installed public packages so coding agents can work without
|
|
28
|
+
reading Coline's private product repository.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-coline-app",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Scaffold, push, and iterate on Coline Apps.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"src",
|
|
13
13
|
"templates",
|
|
14
14
|
"README.md",
|
|
15
|
+
"AGENTS.md",
|
|
15
16
|
"LICENSE"
|
|
16
17
|
],
|
|
17
18
|
"dependencies": {
|
package/src/cli.test.ts
CHANGED
|
@@ -48,8 +48,21 @@ describe("runCreate", () => {
|
|
|
48
48
|
expect(config).not.toContain("__APP_KEY__");
|
|
49
49
|
const packageJson = JSON.parse(await readFile(join(dir, "package.json"), "utf8")) as {
|
|
50
50
|
name: string;
|
|
51
|
+
dependencies: Record<string, string>;
|
|
52
|
+
devDependencies: Record<string, string>;
|
|
51
53
|
};
|
|
52
54
|
expect(packageJson.name).toBe("team-crm");
|
|
55
|
+
expect(packageJson.dependencies["@colineapp/sdk"]).toBe("^0.3.1");
|
|
56
|
+
expect(packageJson.dependencies["@colineapp/ui"]).toBe("^0.3.1");
|
|
57
|
+
expect(packageJson.dependencies.react).toBe("^19.0.0");
|
|
58
|
+
expect(packageJson.dependencies["react-dom"]).toBe("^19.0.0");
|
|
59
|
+
expect(packageJson.devDependencies["create-coline-app"]).toBe("^2.3.0");
|
|
60
|
+
await expect(readFile(join(dir, "main.tsx"), "utf8")).resolves.toContain(
|
|
61
|
+
"ColineAppProvider",
|
|
62
|
+
);
|
|
63
|
+
await expect(
|
|
64
|
+
readFile(join(dir, ".agents/skills/coline-app-development/SKILL.md"), "utf8"),
|
|
65
|
+
).resolves.toContain("Do not inspect");
|
|
53
66
|
await expect(readFile(join(dir, ".gitignore"), "utf8")).resolves.toContain("node_modules");
|
|
54
67
|
});
|
|
55
68
|
|
|
@@ -97,4 +110,39 @@ describe("runCreate", () => {
|
|
|
97
110
|
expect(imported.default.manifest.key).toBe("smoke-app");
|
|
98
111
|
expect(imported.default.manifest.tools[0]?.name).toBe("smoke-app.create_note");
|
|
99
112
|
});
|
|
113
|
+
|
|
114
|
+
it("contains a React starter that bundles against the public UI packages", async () => {
|
|
115
|
+
const dir = await scaffoldTemp("react-smoke");
|
|
116
|
+
const packagesRoot = resolve(__dirname, "..", "..");
|
|
117
|
+
const sdkRoot = join(packagesRoot, "sdk");
|
|
118
|
+
const runtimeRoot = join(packagesRoot, "app-runtime");
|
|
119
|
+
const uiRoot = join(packagesRoot, "coline-ui");
|
|
120
|
+
const sdkRequire = createRequire(join(sdkRoot, "package.json"));
|
|
121
|
+
const uiRequire = createRequire(join(uiRoot, "package.json"));
|
|
122
|
+
const result = await build({
|
|
123
|
+
entryPoints: [join(dir, "main.tsx")],
|
|
124
|
+
bundle: true,
|
|
125
|
+
write: false,
|
|
126
|
+
format: "iife",
|
|
127
|
+
platform: "browser",
|
|
128
|
+
target: "es2022",
|
|
129
|
+
jsx: "automatic",
|
|
130
|
+
logLevel: "silent",
|
|
131
|
+
absWorkingDir: packagesRoot,
|
|
132
|
+
nodePaths: [resolve(packagesRoot, "..", "node_modules")],
|
|
133
|
+
alias: {
|
|
134
|
+
"@colineapp/sdk/v2": join(sdkRoot, "src", "v2.ts"),
|
|
135
|
+
"@colineapp/app-runtime": join(runtimeRoot, "src", "index.ts"),
|
|
136
|
+
"@colineapp/ui": join(uiRoot, "src", "index.ts"),
|
|
137
|
+
"@colineapp/ui/styles.css": join(uiRoot, "src", "styles", "base.css"),
|
|
138
|
+
react: uiRequire.resolve("react"),
|
|
139
|
+
"react-dom": uiRequire.resolve("react-dom"),
|
|
140
|
+
"react-dom/client": uiRequire.resolve("react-dom/client"),
|
|
141
|
+
"react/jsx-runtime": uiRequire.resolve("react/jsx-runtime"),
|
|
142
|
+
"zod/v4": sdkRequire.resolve("zod/v4"),
|
|
143
|
+
},
|
|
144
|
+
loader: { ".css": "empty" },
|
|
145
|
+
});
|
|
146
|
+
expect(result.outputFiles?.[0]?.text).toBeTruthy();
|
|
147
|
+
});
|
|
100
148
|
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: coline-app-development
|
|
3
|
+
description: Build and debug a Coline App using the public SDK, hosted capabilities, tree UI, and sandboxed React UI.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Coline App development
|
|
7
|
+
|
|
8
|
+
Use this skill for any task that changes a generated Coline App.
|
|
9
|
+
|
|
10
|
+
## Start from the shipped contract
|
|
11
|
+
|
|
12
|
+
Read the repository `AGENTS.md`, `app.config.ts`, `main.tsx`, `app.test.ts`,
|
|
13
|
+
and `package.json`. The generated project is intentionally self-contained.
|
|
14
|
+
Do not inspect `/Users/radin/coline-app`, private worktrees, first-party apps,
|
|
15
|
+
or product internals to learn an app-authoring API. Use the installed package
|
|
16
|
+
types, README files, and this skill.
|
|
17
|
+
|
|
18
|
+
The project has two halves:
|
|
19
|
+
|
|
20
|
+
- `app.config.ts` is the hosted logic bundle: manifest, permissions, tools,
|
|
21
|
+
file types, tree handlers, and capability calls.
|
|
22
|
+
- `main.tsx` is the React client entry. The starter includes `@colineapp/ui`,
|
|
23
|
+
React, ReactDOM, and the CSS export; do not add a second bridge or fetch
|
|
24
|
+
data from a Coline API route.
|
|
25
|
+
|
|
26
|
+
## Choose the right surface
|
|
27
|
+
|
|
28
|
+
- Use `ui.*` tree nodes for previews, inline surfaces, mobile fallbacks, and
|
|
29
|
+
simple Kairo cards.
|
|
30
|
+
- Use a React surface when the app needs local interaction, filtering, forms,
|
|
31
|
+
or an editor. Declare `{ tier: "react", entry: "main.tsx" }` and keep the
|
|
32
|
+
root wrapped in `<ColineAppProvider>`.
|
|
33
|
+
- Use `useColine()` for capability calls and `useColineQuery()` for a bounded
|
|
34
|
+
loading/error/refetch loop. Never use `fetch`, localStorage, cookies, or
|
|
35
|
+
credentials in the sandbox.
|
|
36
|
+
|
|
37
|
+
## Public SDK rules
|
|
38
|
+
|
|
39
|
+
- Import logic from `@colineapp/sdk/v2` and tests from `@colineapp/sdk/testing`.
|
|
40
|
+
- Prefix every tool name with the app key.
|
|
41
|
+
- Validate inputs with `zod/v4` and declare honest effects (`read`, `write`,
|
|
42
|
+
`destructive`, or `external`).
|
|
43
|
+
- Ask for the minimum permissions. Capability calls still require both the
|
|
44
|
+
declared permission and the tool effect ceiling.
|
|
45
|
+
- Collections are typed record envelopes. `where` is exact-match on top-level
|
|
46
|
+
fields; query bounded pages and filter more complex predicates in memory.
|
|
47
|
+
- Use `ui.*` for hosted handlers. Chat tool cards must stay within the
|
|
48
|
+
validated chat subset and remain small.
|
|
49
|
+
|
|
50
|
+
## UI rules
|
|
51
|
+
|
|
52
|
+
- Import components from `@colineapp/ui` and `@colineapp/ui/styles.css`.
|
|
53
|
+
- Use the host theme tokens (`bg-background`, `text-foreground`,
|
|
54
|
+
`text-muted-foreground`, and related tokens); dark mode is supplied by the
|
|
55
|
+
host.
|
|
56
|
+
- Render explicit loading, empty, and error states.
|
|
57
|
+
- Keep components accessible and use the provided controls before writing
|
|
58
|
+
custom primitives.
|
|
59
|
+
- Do not add a state library or network client for the first implementation.
|
|
60
|
+
|
|
61
|
+
## Verify before pushing
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
npm run typecheck
|
|
65
|
+
npm test
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Then push with `npx coline-app dev --internal` or `npx coline-app push --internal`
|
|
69
|
+
when the user has supplied `COLINE_BASE_URL` and `COLINE_API_KEY`. The local
|
|
70
|
+
test workspace is the first proof; the hosted app is the second.
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# AGENTS.md — building __APP_NAME__ (a Coline App)
|
|
2
|
+
|
|
3
|
+
This is a self-contained Coline App project. Read this file before changing
|
|
4
|
+
code. The public SDK, UI package, tests, and this guide are the contract; do
|
|
5
|
+
not inspect the Coline product repository or private worktrees to discover how
|
|
6
|
+
to build an app.
|
|
7
|
+
|
|
8
|
+
## Project model
|
|
9
|
+
|
|
10
|
+
Coline hosts the app logic. There is no server, database, auth flow, or deploy
|
|
11
|
+
step in this project:
|
|
12
|
+
|
|
13
|
+
- `app.config.ts` is the hosted logic bundle: manifest, permissions, tools,
|
|
14
|
+
file types, tree handlers, and capability calls.
|
|
15
|
+
- `main.tsx` is the React client entry for the starter home surface. It runs in
|
|
16
|
+
a locked sandbox iframe and uses `@colineapp/ui`.
|
|
17
|
+
- `app.test.ts` runs the logic against `createTestWorkspace`, an in-memory
|
|
18
|
+
capability fake. It does not need a Coline server.
|
|
19
|
+
- `.agents/skills/coline-app-development/SKILL.md` is the detailed task
|
|
20
|
+
workflow for agents that support skills.
|
|
21
|
+
|
|
22
|
+
## Commands
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npm install
|
|
26
|
+
npm run typecheck
|
|
27
|
+
npm test
|
|
28
|
+
|
|
29
|
+
# after local checks pass and the user has supplied these variables:
|
|
30
|
+
npx coline-app dev --internal
|
|
31
|
+
npx coline-app push --internal
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`COLINE_BASE_URL` selects the Coline instance and `COLINE_API_KEY` must be a
|
|
35
|
+
workspace API key with `apps.write`. The CLI uploads `app.config.ts` as a
|
|
36
|
+
logic bundle and submits `main.tsx` plus app `.ts`, `.tsx`, and `.css` source
|
|
37
|
+
when the manifest declares a React surface. It never uploads `node_modules`.
|
|
38
|
+
|
|
39
|
+
## Public package contract
|
|
40
|
+
|
|
41
|
+
Use only these app-facing entry points:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { z } from "zod/v4";
|
|
45
|
+
import { defineApp, defineFileType, defineTool, ui } from "@colineapp/sdk/v2";
|
|
46
|
+
import { createTestWorkspace } from "@colineapp/sdk/testing";
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
For React:
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import { createRoot } from "react-dom/client";
|
|
53
|
+
import { ColineAppProvider, useColine, useColineQuery } from "@colineapp/ui";
|
|
54
|
+
import "@colineapp/ui/styles.css";
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The scaffold installs the SDK, UI, React, ReactDOM, and their type packages.
|
|
58
|
+
Do not replace them with private workspace paths or a second bridge.
|
|
59
|
+
|
|
60
|
+
## Manifest and permissions
|
|
61
|
+
|
|
62
|
+
Keep permissions minimal. Common permissions include:
|
|
63
|
+
|
|
64
|
+
| Permission | Use |
|
|
65
|
+
| --- | --- |
|
|
66
|
+
| `storage.app` | App-private key/value and typed record collections |
|
|
67
|
+
| `files.read` / `files.write` | Read or create workspace files |
|
|
68
|
+
| `ai.tools` | Expose app tools to Kairo |
|
|
69
|
+
| `members.read` | Read workspace member summaries |
|
|
70
|
+
| `search.index` / `search.query` | Index or query workspace search |
|
|
71
|
+
| `network.external` | Use `coline.net.fetch` for allowlisted hosts |
|
|
72
|
+
|
|
73
|
+
Tool effects are enforced ceilings, not labels:
|
|
74
|
+
|
|
75
|
+
- `read` for reads only
|
|
76
|
+
- `write` for ordinary mutations
|
|
77
|
+
- `destructive` for irreversible or deletion-like actions
|
|
78
|
+
- `external` for outbound side effects
|
|
79
|
+
|
|
80
|
+
Every tool input is a Zod schema and every tool name is prefixed with the app
|
|
81
|
+
key (`__APP_KEY__.operation`).
|
|
82
|
+
|
|
83
|
+
## Capability patterns
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
interface Decision {
|
|
87
|
+
title: string;
|
|
88
|
+
status: "proposed" | "decided";
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const decisions = context.coline.storage.collection<Decision>("decisions");
|
|
92
|
+
const created = await decisions.insert({ title: "Use Postgres", status: "decided" });
|
|
93
|
+
const page = await decisions.query({
|
|
94
|
+
where: { status: "decided" },
|
|
95
|
+
orderBy: "title",
|
|
96
|
+
order: "asc",
|
|
97
|
+
limit: 50,
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Collection `where` is exact-match on top-level fields. Records are envelopes
|
|
102
|
+
with the user data under `.data`. Keep pages bounded and filter contains,
|
|
103
|
+
search, or range conditions in app code.
|
|
104
|
+
|
|
105
|
+
File capabilities include `list`, `get`, `create`, `update`, `trash`,
|
|
106
|
+
`getDocument`, and `updateDocument`. Navigation includes `openFile`,
|
|
107
|
+
`openAppHome`, `navigate`, and `openReference`.
|
|
108
|
+
|
|
109
|
+
## UI tiers
|
|
110
|
+
|
|
111
|
+
Tree UI is native and works in previews, inline surfaces, mobile, and Kairo
|
|
112
|
+
cards:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
return ui.stack([
|
|
116
|
+
ui.heading("Decisions", { level: 1 }),
|
|
117
|
+
ui.text("No decisions yet.", { tone: "muted" }),
|
|
118
|
+
]);
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The starter home is React with a tree fallback for mobile:
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
surfaces: {
|
|
125
|
+
home: {
|
|
126
|
+
tier: "react",
|
|
127
|
+
entry: "main.tsx",
|
|
128
|
+
mobile: { tier: "tree" },
|
|
129
|
+
},
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
In `main.tsx`, put the app under `ColineAppProvider`. Call capabilities only
|
|
134
|
+
through `useColine()`, and use `useColineQuery(loader, deps)` for bounded
|
|
135
|
+
loading/error/refetch state. The host supplies theme tokens and dark mode.
|
|
136
|
+
Use classes such as `bg-background`, `text-foreground`,
|
|
137
|
+
`text-muted-foreground`, and the exported UI components.
|
|
138
|
+
|
|
139
|
+
Sandbox restrictions are real: no `fetch`, localStorage, cookies, credentials,
|
|
140
|
+
or direct Coline API routes. External access goes through `coline.net.fetch`
|
|
141
|
+
and a manifest allowlist.
|
|
142
|
+
|
|
143
|
+
## Testing workflow
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
const workspace = createTestWorkspace(app);
|
|
147
|
+
const result = await workspace.invokeTool("__APP_KEY__.create_note", {
|
|
148
|
+
title: "Hello",
|
|
149
|
+
});
|
|
150
|
+
expect(result.card).not.toBeNull();
|
|
151
|
+
expect(workspace.files.byType("__APP_KEY__.note")).toHaveLength(1);
|
|
152
|
+
const tree = await workspace.renderHome();
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Test tools and tree handlers without a server. React client behavior is
|
|
156
|
+
covered by the typecheck and the hosted dev loop after the logic tests pass.
|
|
157
|
+
Keep explicit loading, empty, and error states in every async React view.
|
|
158
|
+
|
|
159
|
+
## Agent boundaries
|
|
160
|
+
|
|
161
|
+
- Do not read `/Users/radin/coline-app`, any `*.worktrees` directory, or
|
|
162
|
+
first-party app code to understand this public API.
|
|
163
|
+
- Do not add dependencies until checking whether the installed SDK/UI already
|
|
164
|
+
provides the capability or component.
|
|
165
|
+
- Do not invent signatures from a README snippet: use the installed package
|
|
166
|
+
declarations when a detail is unclear, then update this guide if the public
|
|
167
|
+
contract is missing.
|
|
168
|
+
- Keep changes inside this generated app. Ask the user before changing the
|
|
169
|
+
platform or publishing packages.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Claude Instructions
|
|
2
|
+
|
|
3
|
+
Read and follow [`AGENTS.md`](./AGENTS.md) — it contains the complete
|
|
4
|
+
Coline App contract: capabilities, tools, storage, UI builders, sandbox
|
|
5
|
+
rules, limits, and testing patterns. For app-authoring tasks, also read
|
|
6
|
+
[`.agents/skills/coline-app-development/SKILL.md`](.agents/skills/coline-app-development/SKILL.md).
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# __APP_NAME__
|
|
2
2
|
|
|
3
|
-
A backendless Coline App. The logic in `app.config.ts` runs on
|
|
4
|
-
hosted runtime — no servers to deploy.
|
|
3
|
+
A hosted, backendless Coline App. The logic in `app.config.ts` runs on
|
|
4
|
+
Coline's hosted runtime — no servers to deploy. The starter also includes a
|
|
5
|
+
working React home in `main.tsx` using `@colineapp/ui`.
|
|
5
6
|
|
|
6
7
|
## Develop
|
|
7
8
|
|
|
8
9
|
```sh
|
|
9
10
|
npm install
|
|
10
11
|
npm test # runs against the in-memory test workspace
|
|
12
|
+
npm run typecheck # checks app.config.ts and main.tsx
|
|
11
13
|
```
|
|
12
14
|
|
|
13
15
|
## Push to Coline
|
|
@@ -30,8 +32,8 @@ Versions land in your developer console in draft state. Use
|
|
|
30
32
|
it as a capability ceiling.
|
|
31
33
|
- Add file types with `defineFileType` — tree previews render everywhere
|
|
32
34
|
Coline shows files, including mobile and Kairo chat.
|
|
33
|
-
-
|
|
34
|
-
`
|
|
35
|
+
- The starter home is already a React surface. Keep `main.tsx` as the single
|
|
36
|
+
client entry and use `@colineapp/ui` for components, provider, and hooks.
|
|
35
37
|
- Store app-private data with `coline.storage.kv` and
|
|
36
38
|
`coline.storage.collection(name)`.
|
|
37
39
|
- Call external APIs with `coline.net.fetch` after declaring
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod/v4";
|
|
2
2
|
import { actions, defineApp, defineFileType, defineTool, ui } from "@colineapp/sdk/v2";
|
|
3
3
|
|
|
4
|
-
// __APP_NAME__ — a backendless Coline App. Everything here runs on
|
|
4
|
+
// __APP_NAME__ — a hosted, backendless Coline App. Everything here runs on
|
|
5
5
|
// Coline's hosted runtime: no servers, no deploys. `coline-app push`
|
|
6
6
|
// uploads this file as the logic bundle and main.tsx as client source.
|
|
7
7
|
|
|
@@ -60,12 +60,16 @@ export default defineApp({
|
|
|
60
60
|
permissions: ["files.read", "files.write", "storage.app", "ai.tools"],
|
|
61
61
|
hosting: { default: "coline" },
|
|
62
62
|
surfaces: {
|
|
63
|
-
home: {
|
|
63
|
+
home: {
|
|
64
|
+
tier: "react",
|
|
65
|
+
entry: "main.tsx",
|
|
66
|
+
mobile: { tier: "tree" },
|
|
67
|
+
},
|
|
64
68
|
},
|
|
65
69
|
files: [noteFileType],
|
|
66
70
|
tools: [createNote],
|
|
67
71
|
handlers: {
|
|
68
|
-
// The
|
|
72
|
+
// The mobile/tree fallback. The React home lives in main.tsx.
|
|
69
73
|
renderHome: async (context) => {
|
|
70
74
|
const { files } = await context.coline.files.list({
|
|
71
75
|
typeKey: "__APP_KEY__.note",
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createRoot } from "react-dom/client";
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Card,
|
|
5
|
+
CardContent,
|
|
6
|
+
CardDescription,
|
|
7
|
+
CardHeader,
|
|
8
|
+
CardTitle,
|
|
9
|
+
ColineAppProvider,
|
|
10
|
+
Skeleton,
|
|
11
|
+
useColine,
|
|
12
|
+
useColineQuery,
|
|
13
|
+
} from "@colineapp/ui";
|
|
14
|
+
import type { ColineFileSummaryV2 } from "@colineapp/sdk/v2";
|
|
15
|
+
import "@colineapp/ui/styles.css";
|
|
16
|
+
|
|
17
|
+
function StarterHome() {
|
|
18
|
+
const coline = useColine();
|
|
19
|
+
const files = useColineQuery(
|
|
20
|
+
(capabilities) =>
|
|
21
|
+
capabilities.files.list({ typeKey: "__APP_KEY__.note", limit: 50 }),
|
|
22
|
+
[],
|
|
23
|
+
);
|
|
24
|
+
const notes = files.data?.files ?? [];
|
|
25
|
+
|
|
26
|
+
async function createNote(): Promise<void> {
|
|
27
|
+
const file = await coline.files.create({
|
|
28
|
+
typeKey: "__APP_KEY__.note",
|
|
29
|
+
name: "Untitled note",
|
|
30
|
+
document: { title: "Untitled note", body: "" },
|
|
31
|
+
});
|
|
32
|
+
await coline.navigation.openFile(file.fileId);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<main className="mx-auto flex min-h-screen w-full max-w-3xl flex-col gap-6 bg-background p-6 text-foreground">
|
|
37
|
+
<header className="flex items-center justify-between gap-4">
|
|
38
|
+
<div>
|
|
39
|
+
<h1 className="text-xl font-semibold">__APP_NAME__ is running</h1>
|
|
40
|
+
<p className="mt-1 text-sm text-muted-foreground">
|
|
41
|
+
Edit app.config.ts or main.tsx and save to hot-swap this app.
|
|
42
|
+
</p>
|
|
43
|
+
</div>
|
|
44
|
+
<Button onClick={() => void createNote()}>New note</Button>
|
|
45
|
+
</header>
|
|
46
|
+
|
|
47
|
+
{files.isLoading ? (
|
|
48
|
+
<div className="flex flex-col gap-2">
|
|
49
|
+
<Skeleton className="h-16 w-full" />
|
|
50
|
+
<Skeleton className="h-16 w-full" />
|
|
51
|
+
</div>
|
|
52
|
+
) : files.error ? (
|
|
53
|
+
<Card>
|
|
54
|
+
<CardHeader>
|
|
55
|
+
<CardTitle>Couldn't load notes</CardTitle>
|
|
56
|
+
<CardDescription>{files.error}</CardDescription>
|
|
57
|
+
</CardHeader>
|
|
58
|
+
<CardContent>
|
|
59
|
+
<Button variant="outline" onClick={files.refetch}>
|
|
60
|
+
Retry
|
|
61
|
+
</Button>
|
|
62
|
+
</CardContent>
|
|
63
|
+
</Card>
|
|
64
|
+
) : notes.length === 0 ? (
|
|
65
|
+
<Card>
|
|
66
|
+
<CardHeader>
|
|
67
|
+
<CardTitle>Edit me</CardTitle>
|
|
68
|
+
<CardDescription>
|
|
69
|
+
This is a real React surface. Replace this starter with your app,
|
|
70
|
+
then ask Kairo to create a note called Hello.
|
|
71
|
+
</CardDescription>
|
|
72
|
+
</CardHeader>
|
|
73
|
+
</Card>
|
|
74
|
+
) : (
|
|
75
|
+
<div className="flex flex-col gap-2">
|
|
76
|
+
{notes.map((file: ColineFileSummaryV2) => (
|
|
77
|
+
<button
|
|
78
|
+
key={file.fileId}
|
|
79
|
+
type="button"
|
|
80
|
+
onClick={() => void coline.navigation.openFile(file.fileId)}
|
|
81
|
+
className="rounded-xl border border-border bg-card px-4 py-3 text-left hover:bg-muted/50"
|
|
82
|
+
>
|
|
83
|
+
<p className="text-sm font-medium">{file.name}</p>
|
|
84
|
+
<p className="mt-1 text-xs text-muted-foreground">Open note</p>
|
|
85
|
+
</button>
|
|
86
|
+
))}
|
|
87
|
+
</div>
|
|
88
|
+
)}
|
|
89
|
+
</main>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const root = document.getElementById("root");
|
|
94
|
+
if (root) {
|
|
95
|
+
createRoot(root).render(
|
|
96
|
+
<ColineAppProvider>
|
|
97
|
+
<StarterHome />
|
|
98
|
+
</ColineAppProvider>,
|
|
99
|
+
);
|
|
100
|
+
}
|
|
@@ -10,12 +10,17 @@
|
|
|
10
10
|
"dev": "coline-app dev"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@colineapp/sdk": "^0.3.
|
|
14
|
-
"
|
|
13
|
+
"@colineapp/sdk": "^0.3.1",
|
|
14
|
+
"@colineapp/ui": "^0.3.1",
|
|
15
|
+
"react": "^19.0.0",
|
|
16
|
+
"react-dom": "^19.0.0",
|
|
17
|
+
"zod": "^4.3.6"
|
|
15
18
|
},
|
|
16
19
|
"devDependencies": {
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
+
"@types/react": "^19.0.0",
|
|
21
|
+
"@types/react-dom": "^19.0.0",
|
|
22
|
+
"create-coline-app": "^2.3.0",
|
|
23
|
+
"typescript": "^5.8.2",
|
|
24
|
+
"vitest": "^3.2.4"
|
|
20
25
|
}
|
|
21
26
|
}
|