# UI package agent guide
`@colineapp/ui` is the public React component and bridge-provider package for
tier-2 Coline Apps. It is the app author's UI layer; it is not the platform's
internal component library.
## Required app setup
```tsx
import { createRoot } from "react-dom/client";
import {
Button,
ColineAppProvider,
useColine,
useColineQuery,
} from "@colineapp/ui";
import "@colineapp/ui/styles.css";
function Home() {
const coline = useColine();
const items = useColineQuery(
(capabilities) => capabilities.files.list({ limit: 100 }),
[],
);
return ;
}
const root = document.getElementById("root");
if (root) {
createRoot(root).render(
,
);
}
```
The package requires React 19 and ReactDOM 19 as peer dependencies. The
scaffold installs them for app authors. `ColineAppProvider` is mandatory
before using `useColine`, `useColineContext`, `useColineQuery`, or
`useColorScheme`; it intentionally renders nothing until the bridge connects.
## On a Coline Site
A site's page (`surfaces.site.entry`) has no Coline host. Wrap it in
`ColineSiteProvider` (follows the visitor's light/dark preference; pass
`theme="light"` or `"dark"` to fix one), import `@colineapp/ui/styles.css`,
and import `@colineapp/ui/theme.css` after `tailwindcss` in the site's CSS so
`bg-card`, `text-muted-foreground`, `border-border` and `dark:` match the
components. Build every control from these components; don't hand-roll
buttons, inputs or cards.
A site looks like Coline. Its one design choice is `accent` on
`ColineSiteProvider` (sets `--action` on the root, lifted for dark mode
unless `{ light, dark }` is passed). Everything else stays Coline's: no
className or CSS that changes a component's colors, borders, radius,
padding or fonts, no custom fonts or palettes, `Tabs` / `SegmentedControl`
for navigation. `coline-app check` warns about each of these
(`packages/create-coline-app/src/site-design.ts`). Keep the rules in this
file, the site template's AGENTS.md, the docs' `sites/design` page and
`apps/docs/src/lib/agents.ts` saying the same thing.
Workspace-only, unavailable on sites: `ColineAppProvider`, `useColine`,
`useColineContext`, `useColineQuery`, `useColorScheme`, `useToast`,
`FilePreview`, `FileDropzone`, `SaveAsButton`, `useFilePicker`,
`ConnectButton`. Sites read data with `@colineapp/sdk/site/react`
(`createSiteHooks()`) and upload with `useUpload`.
## Data and sandbox rules
- All app data goes through the injected `coline.*` capability client.
- Do not use `fetch`, localStorage, cookies, direct API routes, or credentials
in a sandboxed app. Network access belongs behind `coline.net.fetch` and the
manifest allowlist.
- `useColineQuery(loader, deps)` is a small loading/error/refetch helper, not a
cache. Keep loaders bounded and put stable values in `deps`.
- Use host theme tokens and the exported components. Do not hardcode light-only
colors or invent a second provider.
## Component contract
The public barrel exports the provider/hooks plus accessible components such
as `Button`, `Card`, `Input`, `Textarea`, `Badge`, `Dialog`, `Select`,
`Checkbox`, `Switch`, `Tabs`, `Table`, `Skeleton`, and `Tooltip`. Check the
component source and declaration output before documenting a new prop.
The CLI bundles `main.tsx`, installed client dependencies, and imported CSS.
Coline rebuilds the uploaded artifact; the sandbox does not install packages.
Browser-compatible npm dependencies can be added to the app package.
## Verification and release
- Run `pnpm --filter @colineapp/ui typecheck` after component/provider changes.
- Keep CSS export and component export changes together.
- Preserve React peer dependency ranges and the `./styles.css` export.
- Update README examples and the scaffold skill when an app-facing contract
changes. The generated app must be able to use the documented API after a
clean `npm install`.
## SDK 0.4 / CLI 2.4 workflow
Run `coline-app check` before pushing: it checks types, the manifest, hosted logic,
and the React bundle without uploading. `dev --internal` updates one development
version; install it in the workspace and reload after changes. The CLI bundles
from the app's installed dependencies and preserves imported CSS and inline assets.
CLI 2.5 compiles app-specific Tailwind v4 and ordinary CSS automatically.
Import UI styles, then app.css; use complete class names. Local `preview` uses
the public test workspace and sandbox bridge, requires no credentials, and can
capture light/dark/mobile/error states with `--screenshots `.
The starter includes a React home and editor, tree mobile fallback, and a tool.
Use `coline.tools.invoke` or `actions.invokeTool` to run the same declared tool
from UI that Kairo runs. Save with `expectedVersion` to detect concurrent edits.
Homes/editors can write within grants; previews and server render handlers cannot.
`createTestWorkspace(app).client()` tests the interactive contract and
`grantedPermissions` simulates revoked consent.
New `tasks`, `calendar`, `messages`, and `references` capabilities require their
explicit manifest permissions and retain the invoking user's workspace access.
Use `files.list({ scope: "workspace" })` for shared files; document writes stay
with the owning app. Collections are install-private. A native mobile React runtime is separate
work; Coline Code builds and publishes apps (see `docs/sdk/full-stack.md`).
`src/live-collection.ts` wraps the SDK's canonical live-record implementation.
Keep state/conflict/sync logic in the SDK; React owns only subscriptions and
lifecycle. Inline serializable query objects must not restart the view on each
render. React Strict Mode cleanup/start must remain supported. Never infer record
permission from optimistic state or broadcast private fields to an install room.
## UI 0.4.1 defaults
Use `Tabs` / `TabsList` / `TabsTrigger` / `TabsContent` for app views. The raised
sliding selection and content transition are automatic. Do not recreate tab
buttons or choose the opt-in line variant for standard Coline navigation.
Use `FilterMenu` for value filters, and `DropdownMenu` for actions. Both use the
canonical Coline menu surface and highlight. `pnpm check:parity` enforces the
vendored dropdown implementation; `pnpm sync:platform` refreshes it.
Keep animation CSS in the package, respect reduced motion, and verify controls
in a portalled dialog as well as on the page. A form submit button needs explicit
`type="submit"`. Do not restyle shared controls with app-specific CSS.
The menu parity sync includes `menu-item-styles.ts`, the shared class definition
used by dropdown items. Keep this dependency in the sync list when canonical
controls extract helpers; a public package build must work in a fresh checkout.
The stylesheet includes the Latin Geist variable font and its SIL Open Font
License in `dist/fonts`. The CLI embeds the font in the app bundle, so sandbox
text uses Coline typography without remote font requests. Other scripts use the
system fallback. Keep font assets and their license in release tarballs.
## UI 0.6 contract
- Components consume host tokens only. Status and chart colors come from the
sandbox bridge (`--status-*`, `--action`, `--chart-*`); never hard-code hex
or raw Tailwind palette colors.
- Motion goes through `lib/motion.ts` (`transitions.enter|quick|indicator|spring`,
`staggerDelay`) and every animation respects `useReducedMotion`.
- After changing components or styles: `pnpm --filter @colineapp/ui typecheck`,
`pnpm --filter @colineapp/ui build:css`, `node scripts/sync-sandbox-styles.mjs`
(regenerates `apps/web/src/lib/apps/sandbox-styles.generated.ts`), and
`pnpm --filter @colineapp/ui check:parity`.
- Re-scaffold every create-coline-app template and run `coline-app check`; the
templates are the kit's real consumers.