The Coline App SDK: apps, tools, file types and surfaces that run inside Coline workspaces, and public websites with Coline Sites. TypeScript, with an in-memory test workspace. MIT.
| * |
| 6 | * - `tree` — tier 1: app logic returns a declarative UI tree; the host |
| 7 | * renders it with its own components on every platform. |
| 8 | * - `react` — tier 2: a Coline-built React bundle runs in the sandboxed |
| 9 | * client runtime. `entry` is the module path within the app |
| 10 | * source. |
| 11 | * - `web` — tier 3: an iframe served from the app's external origin. |
| 12 | * Requires external hosting; excluded from mobile and preview |
| 13 | * composition. |
| 14 | */ |
| 15 |
| 16 | const surfaceEntrySchema = z.string().trim().min(1).max(500); |
| 17 | const surfacePathSchema = z |
| 18 | .string() |
| 19 | .trim() |
| 20 | .min(1) |
| 21 | .max(2000) |
| 22 | .startsWith("/", "Web surface paths must be origin-relative (start with /)."); |
| 23 |
| 24 | export const treeSurfaceSchema = z.object({ |
| 25 | tier: z.literal("tree"), |
| 26 | }); |
| 27 |
| 28 | export const reactSurfaceSchema = z.object({ |
| 29 | tier: z.literal("react"), |
| 30 | entry: surfaceEntrySchema, |
| 31 | }); |
| 32 |
| 33 | export const webSurfaceSchema = z.object({ |
| 34 | tier: z.literal("web"), |
| 35 | path: surfacePathSchema, |
| 36 | }); |
| 37 |
| 38 | export const surfaceVariantSchema = z.discriminatedUnion("tier", [ |
| 39 | treeSurfaceSchema, |
| 40 | reactSurfaceSchema, |
| 41 | webSurfaceSchema, |
| 42 | ]); |
| 43 | export type SurfaceVariant = z.infer<typeof surfaceVariantSchema>; |
| 44 | export type SurfaceTier = SurfaceVariant["tier"]; |
| 45 |
| 46 | /** |
| 47 | * A surface with an optional mobile override (plan §13): universal by |
| 48 | * default; specialize only when the interaction genuinely differs. |
| 49 | */ |
| 50 | export const appSurfaceSchema = z.discriminatedUnion("tier", [ |
| 51 | treeSurfaceSchema.extend({ mobile: surfaceVariantSchema.optional() }), |
| 52 | reactSurfaceSchema.extend({ mobile: surfaceVariantSchema.optional() }), |
| 53 | webSurfaceSchema.extend({ mobile: surfaceVariantSchema.optional() }), |
| 54 | ]); |
| 55 | export type AppSurface = z.infer<typeof appSurfaceSchema>; |
| 56 |
| 57 | /** |
| 58 | * The public surface (plan §7.6): a page people outside the workspace can |
| 59 | * open — forms, client portals, status pages — served at |
| 60 | * `/apps/public/{workspace}/{app}` once a workspace admin turns it on. |
| 61 | * |
| 62 | * Visitors are guests, not members. Public renders run read-only with the |
| 63 | * app principal; visitor interaction reaches the app ONLY through the |
| 64 | * tools listed in `tools`, which run with the app principal under their |
| 65 | * declared effect and per-visitor rate limits. A react public surface's |
| 66 | * sandbox can call those tools and nothing else. |
| 67 | */ |
| 68 | const publicSurfaceExtension = { |
| 69 | title: z.string().trim().min(1).max(120).optional(), |
| 70 | description: z.string().trim().max(500).optional(), |
| 71 | tools: z.array(z.string().trim().min(1).max(160)).max(20).default([]), |
| 72 | }; |
| 73 |
| 74 | export const publicSurfaceSchema = z.discriminatedUnion("tier", [ |
| 75 | treeSurfaceSchema.extend(publicSurfaceExtension), |
| 76 | reactSurfaceSchema.extend(publicSurfaceExtension), |
| 77 | ]); |
| 78 | export type PublicSurface = z.infer<typeof publicSurfaceSchema>; |
| 79 |
| 80 | export const appSurfacesSchema = z |
| 81 | .object({ |
| 82 | home: appSurfaceSchema.optional(), |
| 83 | public: publicSurfaceSchema.optional(), |
| 84 | }) |
| 85 | .default({}); |
| 86 | export type AppSurfaces = z.infer<typeof appSurfacesSchema>; |
| 87 |