Summary
The SDK can read project canvas layout via get_project → screenInstances, but provides no first-class API to write/sync screen placement, labels, or canvas membership back to Stitch. Integrators building infinite-canvas UIs must call undocumented REST endpoints directly — and those PATCH operations often fail with API keys, requiring OAuth instead.
Current state
Reading canvas data (works)
get_project returns screenInstances with placement metadata:
const raw = await stitch.callTool("get_project", { name: "projects/{projectId}" });
// raw.screenInstances[]:
// { id, sourceScreen, label, x, y, width, height, hidden, type }
The README mentions project.data.screenInstances for apply_design_system, but there is no documented SDK method to update canvas state.
Writing canvas data (missing / broken for API keys)
There is no SDK method or MCP tool such as:
update_screen_instance — move/resize a screen on the canvas
sync_screen_to_canvas — add a screen to the project canvas with placement
update_project_canvas — batch update screenInstances
update_screen_label — rename the canvas label for a screen
Integrators currently call the REST API directly:
PATCH https://stitch.googleapis.com/v1/projects/{projectId}?updateMask=screenInstances
Body: { "screenInstances": [...] }
Header: X-Goog-Api-Key: {STITCH_API_KEY}
This fails for many API-key users with:
{
"error": {
"code": 401,
"message": "Request is missing required authentication credential. Expected OAuth 2 access token",
"status": "UNAUTHENTICATED"
}
}
Concrete gaps
| Operation |
Workaround today |
Problem |
| Sync screen position (x, y, width, height) |
Direct REST PATCH |
OAuth-only for many accounts; not in SDK |
| Rename screen label on canvas |
Direct REST PATCH screenInstances[].label |
Same |
| Add screen to canvas |
Push new instance to screenInstances |
Same; some projects use screen IDs as instance IDs, breaking apply_design_system |
| Normalize invalid instance IDs |
Manual UUID assignment + PATCH |
Required before design system apply; no SDK helper |
| Remove screen from canvas (without delete) |
Filter screenInstances + PATCH |
Same OAuth issue |
| Bidirectional layout sync |
Read via get_project, write via REST |
No unified SDK abstraction |
Requested API
SDK methods on Project
interface ScreenInstance {
id: string; // canvas instance id (UUID, not screen id)
sourceScreen: string; // "projects/{projectId}/screens/{screenId}"
label?: string;
x: number;
y: number;
width: number;
height: number;
hidden?: boolean;
}
// Read (may already exist via project.data — document it)
const layout = await project.getCanvasLayout(): Promise<ScreenInstance[]>;
// Write
await project.updateCanvasLayout(instances: ScreenInstance[]): Promise<void>;
// Convenience helpers
await project.addScreenToCanvas(screenId: string, placement: { x, y, width, height, label? }): Promise<ScreenInstance>;
await project.updateScreenPlacement(screenId: string, placement: Partial<{ x, y, width, height, label }>): Promise<void>;
await project.removeScreenFromCanvas(screenId: string): Promise<void>;
All methods should work with STITCH_API_KEY (BYOK).
MCP tools
| Tool |
Description |
update_project_canvas |
Replace or patch screenInstances for a project |
update_screen_instance |
Update placement/label for one canvas instance |
Documentation
- Document the
screenInstances schema in the README API reference
- Clarify the difference between screen resource ID (
screens/{id}) and canvas instance ID (screenInstances/{uuid})
- Document which operations require OAuth vs API key
Expected behavior
import { stitch } from "@google/stitch-sdk";
const project = stitch.project("1234567890");
const screen = await project.generate("A login page", "MOBILE");
// Place on canvas at specific coordinates
await project.addScreenToCanvas(screen.screenId, {
x: 100, y: 200, width: 390, height: 844, label: "Login"
});
// User drags screen in external canvas UI → sync back to Stitch
await project.updateScreenPlacement(screen.screenId, { x: 300, y: 200 });
// Rename label visible on Stitch canvas
await project.updateScreenPlacement(screen.screenId, { label: "Sign In" });
const layout = await project.getCanvasLayout();
expect(layout.find(i => i.sourceScreen.endsWith(screen.screenId))).toMatchObject({
x: 300, y: 200, label: "Sign In"
});
Use case
We built an infinite-canvas UI designer on top of Stitch where:
- Users arrange screens on a local canvas (pan/zoom/drag)
- Screen positions are persisted locally and should sync to Stitch so the Stitch web UI shows the same layout
- Renaming a screen locally should update the Stitch canvas label
- New screens generated via SDK should appear on the Stitch project canvas (some projects only list screens in
screenInstances, not via list_screens)
Without SDK canvas sync, we maintain a fragile REST workaround that fails for API-key-only users and requires manual fixes in the Stitch web UI.
Environment
@google/stitch-sdk ^0.3.5
- Auth:
STITCH_API_KEY (BYOK)
- Node.js 22
Related
This complements #364 (delete project/screen). Canvas sync covers the update path for project screenInstances; delete covers resource removal.
Happy to share integration details or help test a fix.
Summary
The SDK can read project canvas layout via
get_project→screenInstances, but provides no first-class API to write/sync screen placement, labels, or canvas membership back to Stitch. Integrators building infinite-canvas UIs must call undocumented REST endpoints directly — and those PATCH operations often fail with API keys, requiring OAuth instead.Current state
Reading canvas data (works)
get_projectreturnsscreenInstanceswith placement metadata:The README mentions
project.data.screenInstancesforapply_design_system, but there is no documented SDK method to update canvas state.Writing canvas data (missing / broken for API keys)
There is no SDK method or MCP tool such as:
update_screen_instance— move/resize a screen on the canvassync_screen_to_canvas— add a screen to the project canvas with placementupdate_project_canvas— batch updatescreenInstancesupdate_screen_label— rename the canvas label for a screenIntegrators currently call the REST API directly:
This fails for many API-key users with:
{ "error": { "code": 401, "message": "Request is missing required authentication credential. Expected OAuth 2 access token", "status": "UNAUTHENTICATED" } }Concrete gaps
screenInstances[].labelscreenInstancesapply_design_systemscreenInstances+ PATCHget_project, write via RESTRequested API
SDK methods on
ProjectAll methods should work with
STITCH_API_KEY(BYOK).MCP tools
update_project_canvasscreenInstancesfor a projectupdate_screen_instanceDocumentation
screenInstancesschema in the README API referencescreens/{id}) and canvas instance ID (screenInstances/{uuid})Expected behavior
Use case
We built an infinite-canvas UI designer on top of Stitch where:
screenInstances, not vialist_screens)Without SDK canvas sync, we maintain a fragile REST workaround that fails for API-key-only users and requires manual fixes in the Stitch web UI.
Environment
@google/stitch-sdk^0.3.5STITCH_API_KEY(BYOK)Related
This complements #364 (delete project/screen). Canvas sync covers the update path for project
screenInstances; delete covers resource removal.Happy to share integration details or help test a fix.