From subframe
Implements Subframe designs into codebases via MCP: fetches design, syncs components, creates pages, adds business logic. For package.json projects post /subframe:design or with URL/ID.
npx claudepluginhub subframeapp/subframe --plugin subframeThis skill uses the workspace's default tool permissions.
Implement Subframe designs in the codebase. Fetch the design via MCP, sync components, and add business logic.
Designs UI pages in Subframe with AI variations and edits for new builds, iterations, explorations. Refine visually, then implement as React/Tailwind code.
Guides creation of production-ready Power Pages code sites as SPAs using React, Angular, Vue, or Astro, from requirements discovery to deployment with live dev server previews and git commits.
Convert designs to React/Next.js components with TailwindCSS, TypeScript, and typed API hooks. Use when scaffolding frontend from designs.
Share bugs, ideas, or general feedback.
Implement Subframe designs in the codebase. Fetch the design via MCP, sync components, and add business logic.
If you cannot find the get_page_info tool (or any Subframe MCP tools), the MCP server likely needs to be authenticated. Ask the user to authenticate the Subframe MCP server. If the user is using Claude Code, instruct them to run /mcp to view and authenticate their MCP servers, and then say "done" when they're finished.
Before starting, check for package.json and .subframe/ folder in the current directory:
| Condition | Action |
|---|---|
No package.json | Run /subframe:setup first — there's no project to implement into yet. |
Has package.json AND has .subframe/ folder | Proceed with the workflow below. |
Has package.json but NO .subframe/ folder | Ask the user (see below). |
If the current directory has a package.json but no .subframe/ folder, ask the user which approach they prefer:
/subframe:setup first, then continue with the Workflow below.get_page_info with the URL, ID, or name.Use this workflow when the user chose to use the design as inspiration in an existing non-Subframe project.
get_page_info with the URL, ID, or name to get the design's layout and structure. Use other available Subframe MCP tools as needed to get additional context (e.g., get_component_info to understand a component's props, get_theme to check theme values).Button → the project's own button component)// By URL
get_page_info({ url: "https://app.subframe.com/PROJECT_ID/design/PAGE_ID/edit" })
// By ID (e.g., from /subframe:design)
get_page_info({ id: "PAGE_ID", projectId: "PROJECT_ID" })
// By name
get_page_info({ name: "Settings Page", projectId: "PROJECT_ID" })
// List all pages first if needed
list_pages({ projectId: "PROJECT_ID" })
Get the projectId from .subframe/sync.json. If .subframe/sync.json doesn't exist or doesn't contain a projectId, call list_projects to get the available projects. Each project includes a projectId, name, teamId, and teamName.
teamName to disambiguate. If the user already mentioned a specific team or project name, match it against the teamName and name fields — but still confirm before proceeding. Never silently pick a project when multiple exist.Sync components when they don't exist locally. You can sync specific components by name:
npx @subframe/cli@latest sync Button Alert TextField
Or sync all components:
npx @subframe/cli@latest sync --all
When to sync:
Never modify synced component files - they get overwritten. Create wrapper components if you need to add logic.
If you must modify a synced component file directly, add // @subframe/sync-disable to the top of the file:
// @subframe/sync-disable
import * as React from "react"
// ... rest of component
This prevents the file from being overwritten on future syncs.
Updating a sync-disabled component:
If the user wants to update a component that has sync-disable, the sync command will skip it. To get the latest version:
get_component_info to fetch the latest code from SubframeSubframe generates presentational code with placeholder data. You add:
Data fetching:
const { data, isLoading, error } = useQuery(...)
if (isLoading) return <Skeleton />
if (error) return <Alert variant="error">{error.message}</Alert>
return <PageComponent {...data} />
Form handling:
const handleSubmit = async (e: FormEvent) => {
e.preventDefault()
await submitForm(formData)
}
Event handlers:
<Button onClick={handleClick}>Submit</Button>
<Card actionSlot={<IconButton onClick={handleDelete} />} />
When a design changes:
When diffing the updated design against the existing code, if there are design changes beyond what the user asked you to design (e.g., layout tweaks, new elements, removed sections), call those out and ask whether to include them.
| Tool | Purpose | Key Parameters |
|---|---|---|
get_page_info | Fetch page code | url, id, or name; projectId |
get_component_info | Fetch component code | url, id, or name; projectId |
list_pages | List all pages | projectId |
list_components | List all components | projectId |
get_theme | Get Tailwind config | projectId, cssType |